aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAngelo Mantellini (manangel) <angelo.mantellini@irt-systemx.fr>2017-04-25 21:17:37 +0200
committerAngelo Mantellini (manangel) <angelo.mantellini@irt-systemx.fr>2017-04-25 23:01:06 +0200
commit208d43c7988c527691b663e4e00b56b42cc19277 (patch)
treee26df3383b4256bcde3c95cc4ce32177c8dd744b
parent4ff32ec79cf0ba8ddb8c46f2f36adce379819643 (diff)
correction link libraries libcurl
Change-Id: I8be291ac6b9ec15f0f7bbaa8b434da9d319ae389 Signed-off-by: Angelo Mantellini (manangel) <angelo.mantellini@irt-systemx.fr>
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/Android.mk53
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/curl.h2336
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/curlbuild.h198
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/curlbuild.h.in197
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/curlrules.h262
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/curlver.h69
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/easy.h102
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/mprintf.h81
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/multi.h399
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/stamp-h21
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/stdcheaders.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/include/curl/typecheck-gcc.h610
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/chkhostname-curl_gethostname.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/curl-nonblock.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/curl-rawstr.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/curl-strdup.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/curl-strtoofft.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/curl-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-base64.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-memdebug.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-mprintf.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-nonblock.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-strequal.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-strtoofft.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-timeval.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/getpart-base64.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/getpart-memdebug.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/getpart-mprintf.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/getpart-nonblock.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/getpart-strequal.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/getpart-strtoofft.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/getpart-timeval.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/getpart-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1501-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1502-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1503-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1504-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1505-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1506-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1507-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1508-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1509-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1510-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1511-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1512-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1513-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1514-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1515-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1525-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1526-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1527-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1528-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib1900-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib2033-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib502-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib503-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib504-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib507-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib518-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib525-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib526-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib527-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib529-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib530-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib532-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib533-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib536-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib537-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib540-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib552-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib555-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib560-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib564-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib571-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib573-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib575-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib582-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib591-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/lib597-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-amigaos.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-asyn-ares.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-asyn-thread.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-base64.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-bundles.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-conncache.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-connect.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-content_encoding.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-cookie.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_addrinfo.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_fnmatch.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_gethostname.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_gssapi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_memrchr.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_multibyte.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_core.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_msgs.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_wb.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_rtmp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sasl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sasl_sspi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sspi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_threads.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-dict.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-dotdot.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-easy.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-escape.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-file.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-fileinfo.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-formdata.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ftp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ftplistparser.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-getenv.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-getinfo.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-gopher.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hash.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hmac.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostasyn.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostcheck.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip4.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip6.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostsyn.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http2.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_chunks.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_digest.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_negotiate.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_negotiate_sspi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_proxy.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-idn_win32.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-if2ip.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-imap.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-inet_ntop.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-inet_pton.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-krb5.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ldap.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-llist.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-md4.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-md5.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-memdebug.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-mprintf.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-multi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-netrc.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-non-ascii.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-nonblock.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-openldap.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-parsedate.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pingpong.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pipeline.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pop3.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-progress.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-rawstr.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-rtsp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-security.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-select.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-sendf.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-share.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-slist.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-smtp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks_gssapi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks_sspi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-speedcheck.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-splay.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ssh.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strdup.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strequal.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strerror.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strtok.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strtoofft.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-telnet.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-tftp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-timeval.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-transfer.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-url.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-version.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-warnless.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-wildcard.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-x509asn1.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-nonblock.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-rawstr.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-strdup.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-strtoofft.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-warnless.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-amigaos.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-asyn-ares.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-asyn-thread.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-base64.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-bundles.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-conncache.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-connect.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-content_encoding.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-cookie.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_addrinfo.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_fnmatch.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_gethostname.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_gssapi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_memrchr.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_multibyte.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_core.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_msgs.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_wb.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_rtmp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sasl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sasl_sspi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sspi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_threads.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-dict.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-dotdot.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-easy.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-escape.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-file.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-fileinfo.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-formdata.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ftp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ftplistparser.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-getenv.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-getinfo.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-gopher.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hash.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hmac.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostasyn.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostcheck.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip4.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip6.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostsyn.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http2.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_chunks.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_digest.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_negotiate.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_negotiate_sspi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_proxy.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-idn_win32.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-if2ip.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-imap.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-inet_ntop.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-inet_pton.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-krb5.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ldap.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-llist.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-md4.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-md5.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-memdebug.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-mprintf.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-multi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-netrc.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-non-ascii.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-nonblock.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-openldap.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-parsedate.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pingpong.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pipeline.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pop3.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-progress.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-rawstr.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-rtsp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-security.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-select.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-sendf.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-share.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-slist.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-smtp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks_gssapi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks_sspi.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-speedcheck.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-splay.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ssh.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strdup.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strequal.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strerror.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strtok.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strtoofft.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-telnet.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-tftp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-timeval.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-transfer.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-url.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-version.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-warnless.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-wildcard.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-x509asn1.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/libntlmconnect-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/resolve-base64.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/resolve-memdebug.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/resolve-mprintf.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/resolve-nonblock.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/resolve-strequal.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/resolve-strtoofft.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/resolve-timeval.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/resolve-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/rtspd-base64.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/rtspd-memdebug.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/rtspd-mprintf.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/rtspd-nonblock.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/rtspd-strequal.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/rtspd-strtoofft.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/rtspd-timeval.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/rtspd-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-base64.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-inet_pton.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-memdebug.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-mprintf.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-nonblock.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-strequal.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-strtoofft.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-timeval.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sockfilt-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-base64.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-inet_pton.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-memdebug.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-mprintf.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-nonblock.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-strequal.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-strtoofft.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-timeval.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/sws-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/tftpd-base64.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/tftpd-memdebug.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/tftpd-mprintf.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/tftpd-nonblock.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/tftpd-strequal.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/tftpd-strtoofft.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/tftpd-timeval.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/.deps/tftpd-warnless.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/Makefile.inc71
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/amigaos.c77
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/amigaos.h39
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/arpa_telnet.h104
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/asyn-ares.c694
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/asyn-thread.c701
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/asyn.h168
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/base64.c314
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/bundles.c110
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/bundles.h45
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-amigaos.h167
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-dos.h187
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-mac.h126
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-os400.h560
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-riscos.h513
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-symbian.h817
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-tpf.h772
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-vxworks.h931
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-win32.h698
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/config-win32ce.h448
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/conncache.c283
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/conncache.h55
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/connect.c1340
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/connect.h122
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/content_encoding.c435
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/content_encoding.h48
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/cookie.c1365
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/cookie.h104
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_addrinfo.c527
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_addrinfo.h97
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_base64.h35
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_config.h1037
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_config.h.in1036
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_fnmatch.c427
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_fnmatch.h44
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_gethostname.c100
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_gethostname.h31
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_gssapi.c75
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_gssapi.h60
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_hmac.h67
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ldap.h35
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_md4.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_md5.h63
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_memory.h140
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_memrchr.c62
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_memrchr.h44
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_multibyte.c82
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_multibyte.h90
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ntlm.c248
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ntlm.h44
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ntlm_core.c651
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ntlm_core.h89
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ntlm_msgs.c1010
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ntlm_msgs.h177
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ntlm_wb.c435
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_ntlm_wb.h37
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_rtmp.c311
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_rtmp.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_sasl.c741
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_sasl.h158
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_sasl_sspi.c696
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_sec.h51
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_setup.h693
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_setup_once.h551
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_sspi.c257
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_sspi.h315
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_threads.c135
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curl_threads.h57
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/curlx.h119
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/dict.c283
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/dict.h29
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/dotdot.c170
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/dotdot.h25
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/easy.c1182
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/easyif.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/escape.c233
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/escape.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/file.c583
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/file.h41
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/fileinfo.c54
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/fileinfo.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/firefox-db2pem.sh54
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/formdata.c1596
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/formdata.h98
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/ftp.c4585
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/ftp.h160
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/ftplistparser.c1053
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/ftplistparser.h41
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/getenv.c53
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/getinfo.c381
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/getinfo.h27
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/gopher.c169
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/gopher.h29
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hash.c400
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hash.h106
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hmac.c133
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hostasyn.c157
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hostcheck.c148
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hostcheck.h32
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hostip.c857
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hostip.h250
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hostip4.c310
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hostip6.c224
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/hostsyn.c111
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http.c3664
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http.h223
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http2.c1036
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http2.h50
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_chunks.c385
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_chunks.h91
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_digest.c598
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_digest.h57
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_negotiate.c243
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_negotiate.h42
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_negotiate_sspi.c290
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_proxy.c598
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/http_proxy.h41
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/idn_win32.c85
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/if2ip.c218
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/if2ip.h74
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/imap.c2893
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/imap.h111
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/inet_ntop.c199
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/inet_ntop.h38
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/inet_pton.c234
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/inet_pton.h37
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/krb5.c342
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/ldap.c709
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/libcurl.rc63
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/llist.c212
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/llist.h57
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/md4.c282
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/md5.c541
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/memdebug.c490
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/memdebug.h176
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/mprintf.c1142
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/multi.c2835
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/multihandle.h142
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/multiif.h97
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/netrc.c201
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/netrc.h36
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/non-ascii.c343
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/non-ascii.h63
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/nonblock.c91
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/nonblock.h31
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/nwlib.c329
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/nwos.c88
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/objnames.inc107
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/openldap.c640
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/parsedate.c583
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/parsedate.h31
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/pingpong.c517
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/pingpong.h150
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/pipeline.c340
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/pipeline.h44
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/pop3.c2339
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/pop3.h110
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/progress.c494
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/progress.h73
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/rawstr.c142
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/rawstr.h47
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/rtsp.c809
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/rtsp.h69
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/security.c601
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/select.c574
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/select.h114
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/sendf.c686
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/sendf.h90
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/setup-os400.h239
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/setup-vms.h399
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/share.c254
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/share.h61
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/sigpipe.h78
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/slist.c143
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/slist.h40
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/smtp.c2378
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/smtp.h106
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/sockaddr.h43
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/socks.c755
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/socks.h77
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/socks_gssapi.c534
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/socks_sspi.c604
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/speedcheck.c74
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/speedcheck.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/splay.c288
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/splay.h66
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/ssh.c3302
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/ssh.h183
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/stamp-h11
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strdup.c52
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strdup.h30
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strequal.c79
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strequal.h31
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strerror.c1127
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strerror.h37
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strtok.c66
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strtok.h34
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strtoofft.c188
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/strtoofft.h68
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/telnet.c1680
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/telnet.h29
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/tftp.c1375
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/tftp.h29
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/timeval.c134
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/timeval.h58
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/transfer.c1993
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/transfer.h70
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/url.c6032
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/url.h82
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/urldata.h1705
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/version.c349
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-axtls.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-curl_darwinssl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-curl_schannel.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-cyassl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-gskit.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-gtls.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-nss.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-openssl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-polarssl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-polarssl_threadlock.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-qssl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-vtls.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-axtls.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-curl_darwinssl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-curl_schannel.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-cyassl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-gskit.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-gtls.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-nss.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-openssl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-polarssl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-polarssl_threadlock.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-qssl.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-vtls.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/axtls.c684
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/axtls.h72
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/curl_darwinssl.c2485
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/curl_darwinssl.h77
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/curl_schannel.c1346
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/curl_schannel.h137
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/cyassl.c655
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/cyassl.h69
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/gskit.c1053
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/gskit.h65
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/gtls.c1323
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/gtls.h79
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/nss.c1943
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/nssg.h89
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/openssl.c2918
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/openssl.h101
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/polarssl.c746
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/polarssl.h73
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/polarssl_threadlock.c156
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/polarssl_threadlock.h53
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/qssl.c527
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/qssl.h62
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/vtls.c705
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/vtls/vtls.h132
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/warnless.c486
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/warnless.h107
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/wildcard.c77
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/wildcard.h58
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/x509asn1.c1183
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/lib/x509asn1.h129
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_binmode.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_bname.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_dbg.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_hdr.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_prg.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_rea.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_see.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_wrt.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_cfgable.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_convert.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_dirhie.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_doswin.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_easysrc.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_formparse.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_getparam.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_getpass.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_help.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_helpers.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_homedir.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_hugehelp.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_libinfo.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_main.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_metalink.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_mfiles.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_msgs.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_operate.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_operhlp.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_panykey.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_paramhlp.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_parsecfg.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_setopt.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_sleep.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_urlglob.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_util.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_vms.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_writeenv.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_writeout.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/curl-tool_xattr.Po1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_binmode.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_bname.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_dbg.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_hdr.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_prg.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_rea.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_see.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_wrt.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cfgable.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_convert.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_dirhie.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_doswin.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_easysrc.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_formparse.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_getparam.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_getpass.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_help.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_helpers.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_homedir.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_hugehelp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_libinfo.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_main.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_metalink.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_mfiles.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_msgs.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_operate.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_operhlp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_panykey.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_paramhlp.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_parsecfg.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_setopt.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_sleep.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_urlglob.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_util.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_vms.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_writeenv.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_writeout.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_xattr.Plo1
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/Makefile.inc113
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/curl.rc63
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_binmode.c52
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_binmode.h37
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_bname.c50
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_bname.h35
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_dbg.c275
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_dbg.h35
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_hdr.c225
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_hdr.h54
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_prg.c150
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_prg.h50
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_rea.c55
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_rea.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_see.c131
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_see.h46
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_wrt.c152
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cb_wrt.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cfgable.c154
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_cfgable.h238
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_convert.c150
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_convert.h45
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_dirhie.c147
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_dirhie.h29
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_doswin.c299
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_doswin.h46
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_easysrc.c229
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_easysrc.h48
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_formparse.c361
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_formparse.h33
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_getparam.c1889
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_getparam.h62
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_getpass.c256
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_getpass.h36
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_help.c333
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_help.h31
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_helpers.c77
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_helpers.h32
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_homedir.c95
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_homedir.h28
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_hugehelp.c8299
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_hugehelp.h28
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_libinfo.c100
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_libinfo.h34
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_main.c275
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_main.h44
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_metalink.c963
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_metalink.h167
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_mfiles.c127
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_mfiles.h46
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_msgs.c100
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_msgs.h31
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_operate.c1858
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_operate.h29
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_operhlp.c171
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_operhlp.h39
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_panykey.c48
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_panykey.h37
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_paramhlp.c513
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_paramhlp.h54
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_parsecfg.c362
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_parsecfg.h29
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_sdecls.h153
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_setopt.c565
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_setopt.h148
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_setup.h75
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_sleep.c58
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_sleep.h29
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_urlglob.c674
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_urlglob.h77
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_util.c138
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_util.h56
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_version.h34
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_vms.c219
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_vms.h47
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_writeenv.c116
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_writeenv.h35
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_writeout.c327
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_writeout.h28
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_xattr.c87
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/tool_xattr.h28
-rwxr-xr-xexternal/libcurl_android/jni/libcurl/src/version.h35
-rwxr-xr-xscripts/compile_androidviper.sh2
-rwxr-xr-xscripts/init.sh15
-rwxr-xr-xscripts/init_qt.sh15
-rwxr-xr-xscripts/update.sh6
-rw-r--r--src/libdash/CMakeLists.txt7
758 files changed, 133635 insertions, 52 deletions
diff --git a/external/libcurl_android/jni/libcurl/Android.mk b/external/libcurl_android/jni/libcurl/Android.mk
index c8c57c48..10946bac 100755
--- a/external/libcurl_android/jni/libcurl/Android.mk
+++ b/external/libcurl_android/jni/libcurl/Android.mk
@@ -56,38 +56,38 @@ common_CFLAGS := -Wpointer-arith -Wwrite-strings -Wunused -Winline -Wnested-exte
#########################
# Build the libcurl library
-#include $(CLEAR_VARS)
-#include $(LOCAL_PATH)/lib/Makefile.inc
-#CURL_HEADERS := \
-# curlbuild.h \
-# curl.h \
-# curlrules.h \
-# curlver.h \
-# easy.h \
-# mprintf.h \
-# multi.h \
-# stdcheaders.h \
-# typecheck-gcc.h
-
-#LOCAL_SRC_FILES := $(addprefix lib/,$(CSOURCES))
-#LOCAL_C_INCLUDES += $(LOCAL_PATH)/include/ $(LOCAL_PATH)/lib
-#LOCAL_CFLAGS += $(common_CFLAGS)
-
-#LOCAL_COPY_HEADERS_TO := libcurl/curl
-#LOCAL_COPY_HEADERS := $(addprefix include/curl/,$(CURL_HEADERS))
-
-#LOCAL_MODULE:= curl-library
-#LOCAL_MODULE_TAGS := optional
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/lib/Makefile.inc
+CURL_HEADERS := \
+ curlbuild.h \
+ curl.h \
+ curlrules.h \
+ curlver.h \
+ easy.h \
+ mprintf.h \
+ multi.h \
+ stdcheaders.h \
+ typecheck-gcc.h
+
+LOCAL_SRC_FILES := $(addprefix lib/,$(CSOURCES))
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include/ $(LOCAL_PATH)/lib
+LOCAL_CFLAGS += $(common_CFLAGS)
+
+LOCAL_COPY_HEADERS_TO := libcurl/curl
+LOCAL_COPY_HEADERS := $(addprefix include/curl/,$(CURL_HEADERS))
+
+LOCAL_MODULE:= curl-library
+LOCAL_MODULE_TAGS := optional
# Copy the licence to a place where Android will find it.
# Actually, this doesn't quite work because the build system searches
# for NOTICE files before it gets to this point, so it will only be seen
# on subsequent builds.
-#ALL_PREBUILT += $(LOCAL_PATH)/NOTICE
-#$(LOCAL_PATH)/NOTICE: $(LOCAL_PATH)/COPYING | $(ACP)
-# $(copy-file-to-target)
+ALL_PREBUILT += $(LOCAL_PATH)/NOTICE
+$(LOCAL_PATH)/NOTICE: $(LOCAL_PATH)/COPYING | $(ACP)
+ $(copy-file-to-target)
-#include $(BUILD_STATIC_LIBRARY)
+include $(BUILD_STATIC_LIBRARY)
#########################
@@ -111,3 +111,4 @@ LOCAL_CFLAGS += $(common_CFLAGS)
#include $(BUILD_EXECUTABLE)
include $(BUILD_STATIC_LIBRARY)
+
diff --git a/external/libcurl_android/jni/libcurl/include/curl/curl.h b/external/libcurl_android/jni/libcurl/include/curl/curl.h
new file mode 100755
index 00000000..d40b2dbb
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/curl.h
@@ -0,0 +1,2336 @@
+#ifndef __CURL_CURL_H
+#define __CURL_CURL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * If you have libcurl problems, all docs and details are found here:
+ * http://curl.haxx.se/libcurl/
+ *
+ * curl-library mailing list subscription and unsubscription web interface:
+ * http://cool.haxx.se/mailman/listinfo/curl-library/
+ */
+
+#include "curlver.h" /* libcurl version defines */
+#include "curlbuild.h" /* libcurl build definitions */
+#include "curlrules.h" /* libcurl rules enforcement */
+
+/*
+ * Define WIN32 when build target is Win32 API
+ */
+
+#if (defined(_WIN32) || defined(__WIN32__)) && \
+ !defined(WIN32) && !defined(__SYMBIAN32__)
+#define WIN32
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+
+#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+/* Needed for __FreeBSD_version symbol definition */
+#include <osreldate.h>
+#endif
+
+/* The include stuff here below is mainly for time_t! */
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || defined(__LWIP_OPT_H__))
+/* The check above prevents the winsock2 inclusion if winsock.h already was
+ included, since they can't co-exist without problems */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#endif
+
+/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
+ libc5-based Linux systems. Only include it on systems that are known to
+ require it! */
+#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
+ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
+ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
+#include <sys/select.h>
+#endif
+
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+#include <sys/socket.h>
+#endif
+
+#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
+#include <sys/time.h>
+#endif
+
+#ifdef __BEOS__
+#include <support/SupportDefs.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void CURL;
+
+/*
+ * libcurl external API function linkage decorations.
+ */
+
+#ifdef CURL_STATICLIB
+# define CURL_EXTERN
+#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
+# if defined(BUILDING_LIBCURL)
+# define CURL_EXTERN __declspec(dllexport)
+# else
+# define CURL_EXTERN __declspec(dllimport)
+# endif
+#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
+# define CURL_EXTERN CURL_EXTERN_SYMBOL
+#else
+# define CURL_EXTERN
+#endif
+
+#ifndef curl_socket_typedef
+/* socket typedef */
+#if defined(WIN32) && !defined(__LWIP_OPT_H__)
+typedef SOCKET curl_socket_t;
+#define CURL_SOCKET_BAD INVALID_SOCKET
+#else
+typedef int curl_socket_t;
+#define CURL_SOCKET_BAD -1
+#endif
+#define curl_socket_typedef
+#endif /* curl_socket_typedef */
+
+struct curl_httppost {
+ struct curl_httppost *next; /* next entry in the list */
+ char *name; /* pointer to allocated name */
+ long namelength; /* length of name length */
+ char *contents; /* pointer to allocated data contents */
+ long contentslength; /* length of contents field */
+ char *buffer; /* pointer to allocated buffer contents */
+ long bufferlength; /* length of buffer field */
+ char *contenttype; /* Content-Type */
+ struct curl_slist* contentheader; /* list of extra headers for this form */
+ struct curl_httppost *more; /* if one field name has more than one
+ file, this link should link to following
+ files */
+ long flags; /* as defined below */
+#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */
+#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */
+#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer
+ do not free in formfree */
+#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
+ do not free in formfree */
+#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */
+#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */
+#define HTTPPOST_CALLBACK (1<<6) /* upload file contents by using the
+ regular read callback to get the data
+ and pass the given pointer as custom
+ pointer */
+
+ char *showfilename; /* The file name to show. If not set, the
+ actual file name will be used (if this
+ is a file part) */
+ void *userp; /* custom pointer used for
+ HTTPPOST_CALLBACK posts */
+};
+
+/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
+ deprecated but was the only choice up until 7.31.0 */
+typedef int (*curl_progress_callback)(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow);
+
+/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
+ 7.32.0, it avoids floating point and provides more detailed information. */
+typedef int (*curl_xferinfo_callback)(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow);
+
+#ifndef CURL_MAX_WRITE_SIZE
+ /* Tests have proven that 20K is a very bad buffer size for uploads on
+ Windows, while 16K for some odd reason performed a lot better.
+ We do the ifndef check to allow this value to easier be changed at build
+ time for those who feel adventurous. The practical minimum is about
+ 400 bytes since libcurl uses a buffer of this size as a scratch area
+ (unrelated to network send operations). */
+#define CURL_MAX_WRITE_SIZE 16384
+#endif
+
+#ifndef CURL_MAX_HTTP_HEADER
+/* The only reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause reallocs
+ infinitely */
+#define CURL_MAX_HTTP_HEADER (100*1024)
+#endif
+
+/* This is a magic return code for the write callback that, when returned,
+ will signal libcurl to pause receiving on the current transfer. */
+#define CURL_WRITEFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_write_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *outstream);
+
+
+
+/* enumeration of file types */
+typedef enum {
+ CURLFILETYPE_FILE = 0,
+ CURLFILETYPE_DIRECTORY,
+ CURLFILETYPE_SYMLINK,
+ CURLFILETYPE_DEVICE_BLOCK,
+ CURLFILETYPE_DEVICE_CHAR,
+ CURLFILETYPE_NAMEDPIPE,
+ CURLFILETYPE_SOCKET,
+ CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
+
+ CURLFILETYPE_UNKNOWN /* should never occur */
+} curlfiletype;
+
+#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0)
+#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1)
+#define CURLFINFOFLAG_KNOWN_TIME (1<<2)
+#define CURLFINFOFLAG_KNOWN_PERM (1<<3)
+#define CURLFINFOFLAG_KNOWN_UID (1<<4)
+#define CURLFINFOFLAG_KNOWN_GID (1<<5)
+#define CURLFINFOFLAG_KNOWN_SIZE (1<<6)
+#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7)
+
+/* Content of this structure depends on information which is known and is
+ achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
+ page for callbacks returning this structure -- some fields are mandatory,
+ some others are optional. The FLAG field has special meaning. */
+struct curl_fileinfo {
+ char *filename;
+ curlfiletype filetype;
+ time_t time;
+ unsigned int perm;
+ int uid;
+ int gid;
+ curl_off_t size;
+ long int hardlinks;
+
+ struct {
+ /* If some of these fields is not NULL, it is a pointer to b_data. */
+ char *time;
+ char *perm;
+ char *user;
+ char *group;
+ char *target; /* pointer to the target filename of a symlink */
+ } strings;
+
+ unsigned int flags;
+
+ /* used internally */
+ char * b_data;
+ size_t b_size;
+ size_t b_used;
+};
+
+/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
+#define CURL_CHUNK_BGN_FUNC_OK 0
+#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */
+#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */
+
+/* if splitting of data transfer is enabled, this callback is called before
+ download of an individual chunk started. Note that parameter "remains" works
+ only for FTP wildcard downloading (for now), otherwise is not used */
+typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
+ void *ptr,
+ int remains);
+
+/* return codes for CURLOPT_CHUNK_END_FUNCTION */
+#define CURL_CHUNK_END_FUNC_OK 0
+#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */
+
+/* If splitting of data transfer is enabled this callback is called after
+ download of an individual chunk finished.
+ Note! After this callback was set then it have to be called FOR ALL chunks.
+ Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
+ This is the reason why we don't need "transfer_info" parameter in this
+ callback and we are not interested in "remains" parameter too. */
+typedef long (*curl_chunk_end_callback)(void *ptr);
+
+/* return codes for FNMATCHFUNCTION */
+#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */
+#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */
+#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */
+
+/* callback type for wildcard downloading pattern matching. If the
+ string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
+typedef int (*curl_fnmatch_callback)(void *ptr,
+ const char *pattern,
+ const char *string);
+
+/* These are the return codes for the seek callbacks */
+#define CURL_SEEKFUNC_OK 0
+#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
+#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
+ libcurl might try other means instead */
+typedef int (*curl_seek_callback)(void *instream,
+ curl_off_t offset,
+ int origin); /* 'whence' */
+
+/* This is a return code for the read callback that, when returned, will
+ signal libcurl to immediately abort the current transfer. */
+#define CURL_READFUNC_ABORT 0x10000000
+/* This is a return code for the read callback that, when returned, will
+ signal libcurl to pause sending data on the current transfer. */
+#define CURL_READFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_read_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *instream);
+
+typedef enum {
+ CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
+ CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
+ CURLSOCKTYPE_LAST /* never use */
+} curlsocktype;
+
+/* The return code from the sockopt_callback can signal information back
+ to libcurl: */
+#define CURL_SOCKOPT_OK 0
+#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
+ CURLE_ABORTED_BY_CALLBACK */
+#define CURL_SOCKOPT_ALREADY_CONNECTED 2
+
+typedef int (*curl_sockopt_callback)(void *clientp,
+ curl_socket_t curlfd,
+ curlsocktype purpose);
+
+struct curl_sockaddr {
+ int family;
+ int socktype;
+ int protocol;
+ unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
+ turned really ugly and painful on the systems that
+ lack this type */
+ struct sockaddr addr;
+};
+
+typedef curl_socket_t
+(*curl_opensocket_callback)(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address);
+
+typedef int
+(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
+
+typedef enum {
+ CURLIOE_OK, /* I/O operation successful */
+ CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
+ CURLIOE_FAILRESTART, /* failed to restart the read */
+ CURLIOE_LAST /* never use */
+} curlioerr;
+
+typedef enum {
+ CURLIOCMD_NOP, /* no operation */
+ CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+ CURLIOCMD_LAST /* never use */
+} curliocmd;
+
+typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
+ int cmd,
+ void *clientp);
+
+/*
+ * The following typedef's are signatures of malloc, free, realloc, strdup and
+ * calloc respectively. Function pointers of these types can be passed to the
+ * curl_global_init_mem() function to set user defined memory management
+ * callback routines.
+ */
+typedef void *(*curl_malloc_callback)(size_t size);
+typedef void (*curl_free_callback)(void *ptr);
+typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
+typedef char *(*curl_strdup_callback)(const char *str);
+typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+
+/* the kind of data that is passed to information_callback*/
+typedef enum {
+ CURLINFO_TEXT = 0,
+ CURLINFO_HEADER_IN, /* 1 */
+ CURLINFO_HEADER_OUT, /* 2 */
+ CURLINFO_DATA_IN, /* 3 */
+ CURLINFO_DATA_OUT, /* 4 */
+ CURLINFO_SSL_DATA_IN, /* 5 */
+ CURLINFO_SSL_DATA_OUT, /* 6 */
+ CURLINFO_END
+} curl_infotype;
+
+typedef int (*curl_debug_callback)
+ (CURL *handle, /* the handle/transfer this concerns */
+ curl_infotype type, /* what kind of data */
+ char *data, /* points to the data */
+ size_t size, /* size of the data pointed to */
+ void *userptr); /* whatever the user please */
+
+/* All possible error codes from all sorts of curl functions. Future versions
+ may return other values, stay prepared.
+
+ Always add new return codes last. Never *EVER* remove any. The return
+ codes must remain the same!
+ */
+
+typedef enum {
+ CURLE_OK = 0,
+ CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
+ CURLE_FAILED_INIT, /* 2 */
+ CURLE_URL_MALFORMAT, /* 3 */
+ CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for
+ 7.17.0, reused in April 2011 for 7.21.5] */
+ CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
+ CURLE_COULDNT_RESOLVE_HOST, /* 6 */
+ CURLE_COULDNT_CONNECT, /* 7 */
+ CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
+ CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
+ due to lack of access - when login fails
+ this is not returned. */
+ CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for
+ 7.15.4, reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
+ CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server
+ [was obsoleted in August 2007 for 7.17.0,
+ reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
+ CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
+ CURLE_FTP_CANT_GET_HOST, /* 15 */
+ CURLE_HTTP2, /* 16 - A problem in the http2 framing layer.
+ [was obsoleted in August 2007 for 7.17.0,
+ reused in July 2014 for 7.38.0] */
+ CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
+ CURLE_PARTIAL_FILE, /* 18 */
+ CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
+ CURLE_OBSOLETE20, /* 20 - NOT USED */
+ CURLE_QUOTE_ERROR, /* 21 - quote command failure */
+ CURLE_HTTP_RETURNED_ERROR, /* 22 */
+ CURLE_WRITE_ERROR, /* 23 */
+ CURLE_OBSOLETE24, /* 24 - NOT USED */
+ CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */
+ CURLE_READ_ERROR, /* 26 - couldn't open/read from file */
+ CURLE_OUT_OF_MEMORY, /* 27 */
+ /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+ instead of a memory allocation error if CURL_DOES_CONVERSIONS
+ is defined
+ */
+ CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */
+ CURLE_OBSOLETE29, /* 29 - NOT USED */
+ CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
+ CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
+ CURLE_OBSOLETE32, /* 32 - NOT USED */
+ CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
+ CURLE_HTTP_POST_ERROR, /* 34 */
+ CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
+ CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
+ CURLE_FILE_COULDNT_READ_FILE, /* 37 */
+ CURLE_LDAP_CANNOT_BIND, /* 38 */
+ CURLE_LDAP_SEARCH_FAILED, /* 39 */
+ CURLE_OBSOLETE40, /* 40 - NOT USED */
+ CURLE_FUNCTION_NOT_FOUND, /* 41 */
+ CURLE_ABORTED_BY_CALLBACK, /* 42 */
+ CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
+ CURLE_OBSOLETE44, /* 44 - NOT USED */
+ CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
+ CURLE_OBSOLETE46, /* 46 - NOT USED */
+ CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
+ CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
+ CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
+ CURLE_OBSOLETE50, /* 50 - NOT USED */
+ CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
+ wasn't verified fine */
+ CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
+ CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
+ CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
+ default */
+ CURLE_SEND_ERROR, /* 55 - failed sending network data */
+ CURLE_RECV_ERROR, /* 56 - failure in receiving network data */
+ CURLE_OBSOLETE57, /* 57 - NOT IN USE */
+ CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
+ CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
+ CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
+ CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
+ CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
+ CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
+ CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
+ CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
+ that failed */
+ CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
+ CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
+ accepted and we failed to login */
+ CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
+ CURLE_TFTP_PERM, /* 69 - permission problem on server */
+ CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */
+ CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
+ CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
+ CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
+ CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
+ CURLE_CONV_FAILED, /* 75 - conversion failed */
+ CURLE_CONV_REQD, /* 76 - caller must register conversion
+ callbacks using curl_easy_setopt options
+ CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ CURLOPT_CONV_TO_NETWORK_FUNCTION, and
+ CURLOPT_CONV_FROM_UTF8_FUNCTION */
+ CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
+ or wrong format */
+ CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
+ CURLE_SSH, /* 79 - error from the SSH layer, somewhat
+ generic so the error message will be of
+ interest when this has happened */
+
+ CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
+ connection */
+ CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
+ wait till it's ready and try again (Added
+ in 7.18.2) */
+ CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
+ wrong format (Added in 7.19.0) */
+ CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
+ 7.19.0) */
+ CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
+ CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
+ CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */
+ CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
+ CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
+ CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
+ session will be queued */
+ CURL_LAST /* never use! */
+} CURLcode;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Previously obsolete error code re-used in 7.38.0 */
+#define CURLE_OBSOLETE16 CURLE_HTTP2
+
+/* Previously obsolete error codes re-used in 7.24.0 */
+#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
+#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
+
+/* compatibility with older names */
+#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
+
+/* The following were added in 7.21.5, April 2011 */
+#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
+
+/* The following were added in 7.17.1 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
+
+/* The following were added in 7.17.0 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
+#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
+#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
+#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
+#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
+#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
+#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
+#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
+#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
+#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
+#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
+#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
+#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
+
+#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
+#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
+#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
+#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
+#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
+#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
+#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
+
+/* The following were added earlier */
+
+#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
+
+#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
+#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
+#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
+
+#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
+#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
+
+/* This was the error code 50 in 7.7.3 and a few earlier versions, this
+ is no longer used by libcurl but is instead #defined here only to not
+ make programs break */
+#define CURLE_ALREADY_COMPLETE 99999
+
+/* Provide defines for really old option names */
+#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
+#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
+#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
+
+/* Since long deprecated options with no code in the lib that does anything
+ with them. */
+#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
+#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
+
+#endif /*!CURL_NO_OLDIES*/
+
+/* This prototype applies to all conversion callbacks */
+typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
+
+typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
+ void *ssl_ctx, /* actually an
+ OpenSSL SSL_CTX */
+ void *userptr);
+
+typedef enum {
+ CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use
+ CONNECT HTTP/1.1 */
+ CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
+ HTTP/1.0 */
+ CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
+ in 7.10 */
+ CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
+ CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
+ CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
+ host name rather than the IP address. added
+ in 7.18.0 */
+} curl_proxytype; /* this enum was added in 7.10 */
+
+/*
+ * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
+ *
+ * CURLAUTH_NONE - No HTTP authentication
+ * CURLAUTH_BASIC - HTTP Basic authentication (default)
+ * CURLAUTH_DIGEST - HTTP Digest authentication
+ * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication
+ * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
+ * CURLAUTH_NTLM - HTTP NTLM authentication
+ * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
+ * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
+ * CURLAUTH_ONLY - Use together with a single other type to force no
+ * authentication or just that single type
+ * CURLAUTH_ANY - All fine types set
+ * CURLAUTH_ANYSAFE - All fine types except Basic
+ */
+
+#define CURLAUTH_NONE ((unsigned long)0)
+#define CURLAUTH_BASIC (((unsigned long)1)<<0)
+#define CURLAUTH_DIGEST (((unsigned long)1)<<1)
+#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2)
+/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
+#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
+#define CURLAUTH_NTLM (((unsigned long)1)<<3)
+#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
+#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
+#define CURLAUTH_ONLY (((unsigned long)1)<<31)
+#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
+#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
+
+#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */
+#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */
+#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
+#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */
+#define CURLSSH_AUTH_HOST (1<<2) /* host key files */
+#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */
+#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */
+#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
+
+#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */
+#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */
+#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */
+
+#define CURL_ERROR_SIZE 256
+
+enum curl_khtype {
+ CURLKHTYPE_UNKNOWN,
+ CURLKHTYPE_RSA1,
+ CURLKHTYPE_RSA,
+ CURLKHTYPE_DSS
+};
+
+struct curl_khkey {
+ const char *key; /* points to a zero-terminated string encoded with base64
+ if len is zero, otherwise to the "raw" data */
+ size_t len;
+ enum curl_khtype keytype;
+};
+
+/* this is the set of return values expected from the curl_sshkeycallback
+ callback */
+enum curl_khstat {
+ CURLKHSTAT_FINE_ADD_TO_FILE,
+ CURLKHSTAT_FINE,
+ CURLKHSTAT_REJECT, /* reject the connection, return an error */
+ CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
+ this causes a CURLE_DEFER error but otherwise the
+ connection will be left intact etc */
+ CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
+};
+
+/* this is the set of status codes pass in to the callback */
+enum curl_khmatch {
+ CURLKHMATCH_OK, /* match */
+ CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
+ CURLKHMATCH_MISSING, /* no matching host/key found */
+ CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */
+};
+
+typedef int
+ (*curl_sshkeycallback) (CURL *easy, /* easy handle */
+ const struct curl_khkey *knownkey, /* known */
+ const struct curl_khkey *foundkey, /* found */
+ enum curl_khmatch, /* libcurl's view on the keys */
+ void *clientp); /* custom pointer passed from app */
+
+/* parameter for the CURLOPT_USE_SSL option */
+typedef enum {
+ CURLUSESSL_NONE, /* do not attempt to use SSL */
+ CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */
+ CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
+ CURLUSESSL_ALL, /* SSL for all communication or fail */
+ CURLUSESSL_LAST /* not an option, never use */
+} curl_usessl;
+
+/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
+
+/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
+ name of improving interoperability with older servers. Some SSL libraries
+ have introduced work-arounds for this flaw but those work-arounds sometimes
+ make the SSL communication fail. To regain functionality with those broken
+ servers, a user can this way allow the vulnerability back. */
+#define CURLSSLOPT_ALLOW_BEAST (1<<0)
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2009 */
+
+#define CURLFTPSSL_NONE CURLUSESSL_NONE
+#define CURLFTPSSL_TRY CURLUSESSL_TRY
+#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
+#define CURLFTPSSL_ALL CURLUSESSL_ALL
+#define CURLFTPSSL_LAST CURLUSESSL_LAST
+#define curl_ftpssl curl_usessl
+#endif /*!CURL_NO_OLDIES*/
+
+/* parameter for the CURLOPT_FTP_SSL_CCC option */
+typedef enum {
+ CURLFTPSSL_CCC_NONE, /* do not send CCC */
+ CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
+ CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */
+ CURLFTPSSL_CCC_LAST /* not an option, never use */
+} curl_ftpccc;
+
+/* parameter for the CURLOPT_FTPSSLAUTH option */
+typedef enum {
+ CURLFTPAUTH_DEFAULT, /* let libcurl decide */
+ CURLFTPAUTH_SSL, /* use "AUTH SSL" */
+ CURLFTPAUTH_TLS, /* use "AUTH TLS" */
+ CURLFTPAUTH_LAST /* not an option, never use */
+} curl_ftpauth;
+
+/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
+typedef enum {
+ CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */
+ CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD
+ again if MKD succeeded, for SFTP this does
+ similar magic */
+ CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
+ again even if MKD failed! */
+ CURLFTP_CREATE_DIR_LAST /* not an option, never use */
+} curl_ftpcreatedir;
+
+/* parameter for the CURLOPT_FTP_FILEMETHOD option */
+typedef enum {
+ CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
+ CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */
+ CURLFTPMETHOD_NOCWD, /* no CWD at all */
+ CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
+ CURLFTPMETHOD_LAST /* not an option, never use */
+} curl_ftpmethod;
+
+/* bitmask defines for CURLOPT_HEADEROPT */
+#define CURLHEADER_UNIFIED 0
+#define CURLHEADER_SEPARATE (1<<0)
+
+/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+#define CURLPROTO_HTTP (1<<0)
+#define CURLPROTO_HTTPS (1<<1)
+#define CURLPROTO_FTP (1<<2)
+#define CURLPROTO_FTPS (1<<3)
+#define CURLPROTO_SCP (1<<4)
+#define CURLPROTO_SFTP (1<<5)
+#define CURLPROTO_TELNET (1<<6)
+#define CURLPROTO_LDAP (1<<7)
+#define CURLPROTO_LDAPS (1<<8)
+#define CURLPROTO_DICT (1<<9)
+#define CURLPROTO_FILE (1<<10)
+#define CURLPROTO_TFTP (1<<11)
+#define CURLPROTO_IMAP (1<<12)
+#define CURLPROTO_IMAPS (1<<13)
+#define CURLPROTO_POP3 (1<<14)
+#define CURLPROTO_POP3S (1<<15)
+#define CURLPROTO_SMTP (1<<16)
+#define CURLPROTO_SMTPS (1<<17)
+#define CURLPROTO_RTSP (1<<18)
+#define CURLPROTO_RTMP (1<<19)
+#define CURLPROTO_RTMPT (1<<20)
+#define CURLPROTO_RTMPE (1<<21)
+#define CURLPROTO_RTMPTE (1<<22)
+#define CURLPROTO_RTMPS (1<<23)
+#define CURLPROTO_RTMPTS (1<<24)
+#define CURLPROTO_GOPHER (1<<25)
+#define CURLPROTO_ALL (~0) /* enable everything */
+
+/* long may be 32 or 64 bits, but we should never depend on anything else
+ but 32 */
+#define CURLOPTTYPE_LONG 0
+#define CURLOPTTYPE_OBJECTPOINT 10000
+#define CURLOPTTYPE_FUNCTIONPOINT 20000
+#define CURLOPTTYPE_OFF_T 30000
+
+/* name is uppercase CURLOPT_<name>,
+ type is one of the defined CURLOPTTYPE_<type>
+ number is unique identifier */
+#ifdef CINIT
+#undef CINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG CURLOPTTYPE_LONG
+#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLOPT_/**/name = type + number
+#endif
+
+/*
+ * This macro-mania below setups the CURLOPT_[what] enum, to be used with
+ * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
+ * word.
+ */
+
+typedef enum {
+ /* This is the FILE * or void * the regular output should be written to. */
+ CINIT(WRITEDATA, OBJECTPOINT, 1),
+
+ /* The full URL to get/put */
+ CINIT(URL, OBJECTPOINT, 2),
+
+ /* Port number to connect to, if other than default. */
+ CINIT(PORT, LONG, 3),
+
+ /* Name of proxy to use. */
+ CINIT(PROXY, OBJECTPOINT, 4),
+
+ /* "user:password;options" to use when fetching. */
+ CINIT(USERPWD, OBJECTPOINT, 5),
+
+ /* "user:password" to use with proxy. */
+ CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
+
+ /* Range to get, specified as an ASCII string. */
+ CINIT(RANGE, OBJECTPOINT, 7),
+
+ /* not used */
+
+ /* Specified file stream to upload from (use as input): */
+ CINIT(READDATA, OBJECTPOINT, 9),
+
+ /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
+ * bytes big. If this is not used, error messages go to stderr instead: */
+ CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+
+ /* Function that will be called to store the output (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+
+ /* Function that will be called to read the input (instead of fread). The
+ * parameters will use fread() syntax, make sure to follow them. */
+ CINIT(READFUNCTION, FUNCTIONPOINT, 12),
+
+ /* Time-out the read operation after this amount of seconds */
+ CINIT(TIMEOUT, LONG, 13),
+
+ /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
+ * how large the file being sent really is. That allows better error
+ * checking and better verifies that the upload was successful. -1 means
+ * unknown size.
+ *
+ * For large file support, there is also a _LARGE version of the key
+ * which takes an off_t type, allowing platforms with larger off_t
+ * sizes to handle larger files. See below for INFILESIZE_LARGE.
+ */
+ CINIT(INFILESIZE, LONG, 14),
+
+ /* POST static input fields. */
+ CINIT(POSTFIELDS, OBJECTPOINT, 15),
+
+ /* Set the referrer page (needed by some CGIs) */
+ CINIT(REFERER, OBJECTPOINT, 16),
+
+ /* Set the FTP PORT string (interface name, named or numerical IP address)
+ Use i.e '-' to use default address. */
+ CINIT(FTPPORT, OBJECTPOINT, 17),
+
+ /* Set the User-Agent string (examined by some CGIs) */
+ CINIT(USERAGENT, OBJECTPOINT, 18),
+
+ /* If the download receives less than "low speed limit" bytes/second
+ * during "low speed time" seconds, the operations is aborted.
+ * You could i.e if you have a pretty high speed connection, abort if
+ * it is less than 2000 bytes/sec during 20 seconds.
+ */
+
+ /* Set the "low speed limit" */
+ CINIT(LOW_SPEED_LIMIT, LONG, 19),
+
+ /* Set the "low speed time" */
+ CINIT(LOW_SPEED_TIME, LONG, 20),
+
+ /* Set the continuation offset.
+ *
+ * Note there is also a _LARGE version of this key which uses
+ * off_t types, allowing for large file offsets on platforms which
+ * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE.
+ */
+ CINIT(RESUME_FROM, LONG, 21),
+
+ /* Set cookie in request: */
+ CINIT(COOKIE, OBJECTPOINT, 22),
+
+ /* This points to a linked list of headers, struct curl_slist kind. This
+ list is also used for RTSP (in spite of its name) */
+ CINIT(HTTPHEADER, OBJECTPOINT, 23),
+
+ /* This points to a linked list of post entries, struct curl_httppost */
+ CINIT(HTTPPOST, OBJECTPOINT, 24),
+
+ /* name of the file keeping your private SSL-certificate */
+ CINIT(SSLCERT, OBJECTPOINT, 25),
+
+ /* password for the SSL or SSH private key */
+ CINIT(KEYPASSWD, OBJECTPOINT, 26),
+
+ /* send TYPE parameter? */
+ CINIT(CRLF, LONG, 27),
+
+ /* send linked-list of QUOTE commands */
+ CINIT(QUOTE, OBJECTPOINT, 28),
+
+ /* send FILE * or void * to store headers to, if you use a callback it
+ is simply passed to the callback unmodified */
+ CINIT(HEADERDATA, OBJECTPOINT, 29),
+
+ /* point to a file to read the initial cookies from, also enables
+ "cookie awareness" */
+ CINIT(COOKIEFILE, OBJECTPOINT, 31),
+
+ /* What version to specifically try to use.
+ See CURL_SSLVERSION defines below. */
+ CINIT(SSLVERSION, LONG, 32),
+
+ /* What kind of HTTP time condition to use, see defines */
+ CINIT(TIMECONDITION, LONG, 33),
+
+ /* Time to use with the above condition. Specified in number of seconds
+ since 1 Jan 1970 */
+ CINIT(TIMEVALUE, LONG, 34),
+
+ /* 35 = OBSOLETE */
+
+ /* Custom request, for customizing the get command like
+ HTTP: DELETE, TRACE and others
+ FTP: to use a different list command
+ */
+ CINIT(CUSTOMREQUEST, OBJECTPOINT, 36),
+
+ /* HTTP request, for odd commands like DELETE, TRACE and others */
+ CINIT(STDERR, OBJECTPOINT, 37),
+
+ /* 38 is not used */
+
+ /* send linked-list of post-transfer QUOTE commands */
+ CINIT(POSTQUOTE, OBJECTPOINT, 39),
+
+ CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
+
+ CINIT(VERBOSE, LONG, 41), /* talk a lot */
+ CINIT(HEADER, LONG, 42), /* throw the header out too */
+ CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */
+ CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */
+ CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */
+ CINIT(UPLOAD, LONG, 46), /* this is an upload */
+ CINIT(POST, LONG, 47), /* HTTP POST method */
+ CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */
+
+ CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */
+
+ /* Specify whether to read the user+password from the .netrc or the URL.
+ * This must be one of the CURL_NETRC_* enums below. */
+ CINIT(NETRC, LONG, 51),
+
+ CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
+
+ CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
+ CINIT(PUT, LONG, 54), /* HTTP PUT */
+
+ /* 55 = OBSOLETE */
+
+ /* DEPRECATED
+ * Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_progress_callback
+ * prototype defines. */
+ CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+
+ /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
+ callbacks */
+ CINIT(PROGRESSDATA, OBJECTPOINT, 57),
+#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+
+ /* We want the referrer field set automatically when following locations */
+ CINIT(AUTOREFERER, LONG, 58),
+
+ /* Port of the proxy, can be set in the proxy string as well with:
+ "[host]:[port]" */
+ CINIT(PROXYPORT, LONG, 59),
+
+ /* size of the POST input data, if strlen() is not good to use */
+ CINIT(POSTFIELDSIZE, LONG, 60),
+
+ /* tunnel non-http operations through a HTTP proxy */
+ CINIT(HTTPPROXYTUNNEL, LONG, 61),
+
+ /* Set the interface string to use as outgoing network interface */
+ CINIT(INTERFACE, OBJECTPOINT, 62),
+
+ /* Set the krb4/5 security level, this also enables krb4/5 awareness. This
+ * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
+ * is set but doesn't match one of these, 'private' will be used. */
+ CINIT(KRBLEVEL, OBJECTPOINT, 63),
+
+ /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
+ CINIT(SSL_VERIFYPEER, LONG, 64),
+
+ /* The CApath or CAfile used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(CAINFO, OBJECTPOINT, 65),
+
+ /* 66 = OBSOLETE */
+ /* 67 = OBSOLETE */
+
+ /* Maximum number of http redirects to follow */
+ CINIT(MAXREDIRS, LONG, 68),
+
+ /* Pass a long set to 1 to get the date of the requested document (if
+ possible)! Pass a zero to shut it off. */
+ CINIT(FILETIME, LONG, 69),
+
+ /* This points to a linked list of telnet options */
+ CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
+
+ /* Max amount of cached alive connections */
+ CINIT(MAXCONNECTS, LONG, 71),
+
+ CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
+
+ /* 73 = OBSOLETE */
+
+ /* Set to explicitly use a new connection for the upcoming transfer.
+ Do not use this unless you're absolutely sure of this, as it makes the
+ operation slower and is less friendly for the network. */
+ CINIT(FRESH_CONNECT, LONG, 74),
+
+ /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+ when done. Do not use this unless you're absolutely sure of this, as it
+ makes the operation slower and is less friendly for the network. */
+ CINIT(FORBID_REUSE, LONG, 75),
+
+ /* Set to a file name that contains random data for libcurl to use to
+ seed the random engine when doing SSL connects. */
+ CINIT(RANDOM_FILE, OBJECTPOINT, 76),
+
+ /* Set to the Entropy Gathering Daemon socket pathname */
+ CINIT(EGDSOCKET, OBJECTPOINT, 77),
+
+ /* Time-out connect operations after this amount of seconds, if connects are
+ OK within this time, then fine... This only aborts the connect phase. */
+ CINIT(CONNECTTIMEOUT, LONG, 78),
+
+ /* Function that will be called to store headers (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+
+ /* Set this to force the HTTP request to get back to GET. Only really usable
+ if POST, PUT or a custom request have been used first.
+ */
+ CINIT(HTTPGET, LONG, 80),
+
+ /* Set if we should verify the Common name from the peer certificate in ssl
+ * handshake, set 1 to check existence, 2 to ensure that it matches the
+ * provided hostname. */
+ CINIT(SSL_VERIFYHOST, LONG, 81),
+
+ /* Specify which file name to write all known cookies in after completed
+ operation. Set file name to "-" (dash) to make it go to stdout. */
+ CINIT(COOKIEJAR, OBJECTPOINT, 82),
+
+ /* Specify which SSL ciphers to use */
+ 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),
+
+ /* Specifically switch on or off the FTP engine's use of the EPSV command. By
+ default, that one will always be attempted before the more traditional
+ PASV command. */
+ CINIT(FTP_USE_EPSV, LONG, 85),
+
+ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
+ CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
+
+ /* name of the file keeping your private SSL-key */
+ CINIT(SSLKEY, OBJECTPOINT, 87),
+
+ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
+ CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
+
+ /* crypto engine for the SSL-sub system */
+ CINIT(SSLENGINE, OBJECTPOINT, 89),
+
+ /* set the crypto engine for the SSL-sub system as default
+ the param has no meaning...
+ */
+ CINIT(SSLENGINE_DEFAULT, LONG, 90),
+
+ /* Non-zero value means to use the global dns cache */
+ CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
+
+ /* DNS cache timeout */
+ CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+
+ /* send linked-list of pre-transfer QUOTE commands */
+ CINIT(PREQUOTE, OBJECTPOINT, 93),
+
+ /* set the debug function */
+ CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
+
+ /* set the data for the debug function */
+ CINIT(DEBUGDATA, OBJECTPOINT, 95),
+
+ /* mark this as start of a cookie session */
+ CINIT(COOKIESESSION, LONG, 96),
+
+ /* The CApath directory used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(CAPATH, OBJECTPOINT, 97),
+
+ /* Instruct libcurl to use a smaller receive buffer */
+ CINIT(BUFFERSIZE, LONG, 98),
+
+ /* Instruct libcurl to not use any signal/alarm handlers, even when using
+ timeouts. This option is useful for multi-threaded applications.
+ See libcurl-the-guide for more background information. */
+ CINIT(NOSIGNAL, LONG, 99),
+
+ /* Provide a CURLShare for mutexing non-ts data */
+ CINIT(SHARE, OBJECTPOINT, 100),
+
+ /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
+ CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
+ CINIT(PROXYTYPE, LONG, 101),
+
+ /* Set the Accept-Encoding string. Use this to tell a server you would like
+ the response to be compressed. Before 7.21.6, this was known as
+ CURLOPT_ENCODING */
+ CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102),
+
+ /* Set pointer to private data */
+ CINIT(PRIVATE, OBJECTPOINT, 103),
+
+ /* Set aliases for HTTP 200 in the HTTP Response header */
+ CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
+
+ /* Continue to send authentication (user+password) when following locations,
+ even when hostname changed. This can potentially send off the name
+ and password to whatever host the server decides. */
+ CINIT(UNRESTRICTED_AUTH, LONG, 105),
+
+ /* Specifically switch on or off the FTP engine's use of the EPRT command (
+ it also disables the LPRT attempt). By default, those ones will always be
+ attempted before the good old traditional PORT command. */
+ CINIT(FTP_USE_EPRT, LONG, 106),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_USERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(HTTPAUTH, LONG, 107),
+
+ /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
+ in second argument. The function must be matching the
+ curl_ssl_ctx_callback proto. */
+ CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
+
+ /* Set the userdata for the ssl context callback function's third
+ argument */
+ CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
+
+ /* FTP Option that causes missing dirs to be created on the remote server.
+ In 7.19.4 we introduced the convenience enums for this option using the
+ CURLFTP_CREATE_DIR prefix.
+ */
+ CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(PROXYAUTH, LONG, 111),
+
+ /* FTP option that changes the timeout, in seconds, associated with
+ getting a response. This is different from transfer timeout time and
+ essentially places a demand on the FTP server to acknowledge commands
+ in a timely manner. */
+ CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
+#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+
+ /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
+ tell libcurl to resolve names to those IP versions only. This only has
+ affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+ CINIT(IPRESOLVE, LONG, 113),
+
+ /* Set this option to limit the size of a file that will be downloaded from
+ an HTTP or FTP server.
+
+ Note there is also _LARGE version which adds large file support for
+ platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */
+ CINIT(MAXFILESIZE, LONG, 114),
+
+ /* See the comment for INFILESIZE above, but in short, specifies
+ * the size of the file being uploaded. -1 means unknown.
+ */
+ CINIT(INFILESIZE_LARGE, OFF_T, 115),
+
+ /* Sets the continuation offset. There is also a LONG version of this;
+ * look above for RESUME_FROM.
+ */
+ CINIT(RESUME_FROM_LARGE, OFF_T, 116),
+
+ /* Sets the maximum size of data that will be downloaded from
+ * an HTTP or FTP server. See MAXFILESIZE above for the LONG version.
+ */
+ CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+
+ /* Set this option to the file name of your .netrc file you want libcurl
+ to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
+ a poor attempt to find the user's home directory and check for a .netrc
+ file in there. */
+ CINIT(NETRC_FILE, OBJECTPOINT, 118),
+
+ /* Enable SSL/TLS for FTP, pick one of:
+ CURLUSESSL_TRY - try using SSL, proceed anyway otherwise
+ CURLUSESSL_CONTROL - SSL for the control connection or fail
+ CURLUSESSL_ALL - SSL for all communication or fail
+ */
+ CINIT(USE_SSL, LONG, 119),
+
+ /* The _LARGE version of the standard POSTFIELDSIZE option */
+ CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+
+ /* Enable/disable the TCP Nagle algorithm */
+ CINIT(TCP_NODELAY, LONG, 121),
+
+ /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 123 OBSOLETE. Gone in 7.16.0 */
+ /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 127 OBSOLETE. Gone in 7.16.0 */
+ /* 128 OBSOLETE. Gone in 7.16.0 */
+
+ /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
+ can be used to change libcurl's default action which is to first try
+ "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
+ response has been received.
+
+ Available parameters are:
+ CURLFTPAUTH_DEFAULT - let libcurl decide
+ CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS
+ CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL
+ */
+ CINIT(FTPSSLAUTH, LONG, 129),
+
+ CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
+ CINIT(IOCTLDATA, OBJECTPOINT, 131),
+
+ /* 132 OBSOLETE. Gone in 7.16.0 */
+ /* 133 OBSOLETE. Gone in 7.16.0 */
+
+ /* zero terminated string for pass on to the FTP server when asked for
+ "account" info */
+ CINIT(FTP_ACCOUNT, OBJECTPOINT, 134),
+
+ /* feed cookies into cookie engine */
+ CINIT(COOKIELIST, OBJECTPOINT, 135),
+
+ /* ignore Content-Length */
+ CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+
+ /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
+ response. Typically used for FTP-SSL purposes but is not restricted to
+ that. libcurl will then instead use the same IP address it used for the
+ control connection. */
+ CINIT(FTP_SKIP_PASV_IP, LONG, 137),
+
+ /* Select "file method" to use when doing FTP, see the curl_ftpmethod
+ above. */
+ CINIT(FTP_FILEMETHOD, LONG, 138),
+
+ /* Local port number to bind the socket to */
+ CINIT(LOCALPORT, LONG, 139),
+
+ /* Number of ports to try, including the first one set with LOCALPORT.
+ Thus, setting it to 1 will make no additional attempts but the first.
+ */
+ CINIT(LOCALPORTRANGE, LONG, 140),
+
+ /* no transfer, set up connection and let application use the socket by
+ extracting it with CURLINFO_LASTSOCKET */
+ CINIT(CONNECT_ONLY, LONG, 141),
+
+ /* Function that will be called to convert from the
+ network encoding (instead of using the iconv calls in libcurl) */
+ CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
+
+ /* Function that will be called to convert to the
+ network encoding (instead of using the iconv calls in libcurl) */
+ CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
+
+ /* Function that will be called to convert from UTF8
+ (instead of using the iconv calls in libcurl)
+ Note that this is used only for SSL certificate processing */
+ CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+
+ /* if the connection proceeds too quickly then need to slow it down */
+ /* limit-rate: maximum number of bytes per second to send or receive */
+ CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
+ CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+
+ /* Pointer to command string to send if USER/PASS fails. */
+ CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
+
+ /* callback function for setting socket options */
+ CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
+ CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
+
+ /* set to 0 to disable session ID re-use for this transfer, default is
+ enabled (== 1) */
+ CINIT(SSL_SESSIONID_CACHE, LONG, 150),
+
+ /* allowed SSH authentication methods */
+ CINIT(SSH_AUTH_TYPES, LONG, 151),
+
+ /* Used by scp/sftp to do public/private key authentication */
+ CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152),
+ CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153),
+
+ /* Send CCC (Clear Command Channel) after authentication */
+ CINIT(FTP_SSL_CCC, LONG, 154),
+
+ /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
+ CINIT(TIMEOUT_MS, LONG, 155),
+ CINIT(CONNECTTIMEOUT_MS, LONG, 156),
+
+ /* set to zero to disable the libcurl's decoding and thus pass the raw body
+ data to the application even when it is encoded/compressed */
+ CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
+ CINIT(HTTP_CONTENT_DECODING, LONG, 158),
+
+ /* Permission used when creating new files and directories on the remote
+ server for protocols that support it, SFTP/SCP/FILE */
+ CINIT(NEW_FILE_PERMS, LONG, 159),
+ CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+
+ /* Set the behaviour of POST when redirecting. Values must be set to one
+ of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
+ CINIT(POSTREDIR, LONG, 161),
+
+ /* used by scp/sftp to verify the host's public key */
+ CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162),
+
+ /* Callback function for opening socket (instead of socket(2)). Optionally,
+ callback is able change the address or refuse to connect returning
+ CURL_SOCKET_BAD. The callback should have type
+ curl_opensocket_callback */
+ CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
+ CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
+
+ /* POST volatile input fields. */
+ CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
+
+ /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
+ CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+
+ /* Callback function for seeking in the input stream */
+ CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
+ CINIT(SEEKDATA, OBJECTPOINT, 168),
+
+ /* CRL file */
+ CINIT(CRLFILE, OBJECTPOINT, 169),
+
+ /* Issuer certificate */
+ CINIT(ISSUERCERT, OBJECTPOINT, 170),
+
+ /* (IPv6) Address scope */
+ CINIT(ADDRESS_SCOPE, LONG, 171),
+
+ /* Collect certificate chain info and allow it to get retrievable with
+ CURLINFO_CERTINFO after the transfer is complete. */
+ CINIT(CERTINFO, LONG, 172),
+
+ /* "name" and "pwd" to use when fetching. */
+ CINIT(USERNAME, OBJECTPOINT, 173),
+ CINIT(PASSWORD, OBJECTPOINT, 174),
+
+ /* "name" and "pwd" to use with Proxy when fetching. */
+ CINIT(PROXYUSERNAME, OBJECTPOINT, 175),
+ CINIT(PROXYPASSWORD, OBJECTPOINT, 176),
+
+ /* Comma separated list of hostnames defining no-proxy zones. These should
+ match both hostnames directly, and hostnames within a domain. For
+ example, local.com will match local.com and www.local.com, but NOT
+ notlocal.com or www.notlocal.com. For compatibility with other
+ implementations of this, .local.com will be considered to be the same as
+ local.com. A single * is the only valid wildcard, and effectively
+ disables the use of proxy. */
+ CINIT(NOPROXY, OBJECTPOINT, 177),
+
+ /* block size for TFTP transfers */
+ CINIT(TFTP_BLKSIZE, LONG, 178),
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179),
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
+
+ /* set the bitmask for the protocols that are allowed to be used for the
+ transfer, which thus helps the app which takes URLs from users or other
+ external inputs and want to restrict what protocol(s) to deal
+ with. Defaults to CURLPROTO_ALL. */
+ CINIT(PROTOCOLS, LONG, 181),
+
+ /* set the bitmask for the protocols that libcurl is allowed to follow to,
+ as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+ to be set in both bitmasks to be allowed to get redirected to. Defaults
+ to all protocols except FILE and SCP. */
+ CINIT(REDIR_PROTOCOLS, LONG, 182),
+
+ /* set the SSH knownhost file name to use */
+ CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183),
+
+ /* set the SSH host key callback, must point to a curl_sshkeycallback
+ function */
+ CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
+
+ /* set the SSH host key callback custom pointer */
+ CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
+
+ /* set the SMTP mail originator */
+ CINIT(MAIL_FROM, OBJECTPOINT, 186),
+
+ /* set the SMTP mail receiver(s) */
+ CINIT(MAIL_RCPT, OBJECTPOINT, 187),
+
+ /* FTP: send PRET before PASV */
+ CINIT(FTP_USE_PRET, LONG, 188),
+
+ /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
+ CINIT(RTSP_REQUEST, LONG, 189),
+
+ /* The RTSP session identifier */
+ CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190),
+
+ /* The RTSP stream URI */
+ CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191),
+
+ /* The Transport: header to use in RTSP requests */
+ CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192),
+
+ /* Manually initialize the client RTSP CSeq for this handle */
+ CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
+
+ /* Manually initialize the server RTSP CSeq for this handle */
+ CINIT(RTSP_SERVER_CSEQ, LONG, 194),
+
+ /* The stream to pass to INTERLEAVEFUNCTION. */
+ CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
+
+ /* Let the application define a custom write method for RTP data */
+ CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
+
+ /* Turn on wildcard matching */
+ CINIT(WILDCARDMATCH, LONG, 197),
+
+ /* Directory matching callback called before downloading of an
+ individual file (chunk) started */
+ CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
+
+ /* Directory matching callback called after the file (chunk)
+ was downloaded, or skipped */
+ CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
+
+ /* Change match (fnmatch-like) callback for wildcard matching */
+ CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
+
+ /* Let the application define custom chunk data pointer */
+ CINIT(CHUNK_DATA, OBJECTPOINT, 201),
+
+ /* FNMATCH_FUNCTION user pointer */
+ CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
+
+ /* send linked-list of name:port:address sets */
+ CINIT(RESOLVE, OBJECTPOINT, 203),
+
+ /* Set a username for authenticated TLS */
+ CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204),
+
+ /* Set a password for authenticated TLS */
+ CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205),
+
+ /* Set authentication type for authenticated TLS */
+ CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206),
+
+ /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
+ compressed transfer-encoded responses. Set to 0 to disable the use of TE:
+ in outgoing requests. The current default is 0, but it might change in a
+ future libcurl release.
+
+ libcurl will ask for the compressed methods it knows of, and if that
+ isn't any, it will not ask for transfer-encoding at all even if this
+ option is set to 1.
+
+ */
+ CINIT(TRANSFER_ENCODING, LONG, 207),
+
+ /* Callback function for closing socket (instead of close(2)). The callback
+ should have type curl_closesocket_callback */
+ CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
+ CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
+
+ /* allow GSSAPI credential delegation */
+ CINIT(GSSAPI_DELEGATION, LONG, 210),
+
+ /* Set the name servers to use for DNS resolution */
+ CINIT(DNS_SERVERS, OBJECTPOINT, 211),
+
+ /* Time-out accept operations (currently for FTP only) after this amount
+ of miliseconds. */
+ CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
+
+ /* Set TCP keepalive */
+ CINIT(TCP_KEEPALIVE, LONG, 213),
+
+ /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
+ CINIT(TCP_KEEPIDLE, LONG, 214),
+ CINIT(TCP_KEEPINTVL, LONG, 215),
+
+ /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
+ CINIT(SSL_OPTIONS, LONG, 216),
+
+ /* Set the SMTP auth originator */
+ CINIT(MAIL_AUTH, OBJECTPOINT, 217),
+
+ /* Enable/disable SASL initial response */
+ CINIT(SASL_IR, LONG, 218),
+
+ /* Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_xferinfo_callback
+ * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
+ CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
+
+ /* The XOAUTH2 bearer token */
+ CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
+
+ /* Set the interface string to use as outgoing network
+ * interface for DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
+
+ /* Set the local IPv4 address to use for outgoing DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
+
+ /* Set the local IPv4 address to use for outgoing DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
+
+ /* Set authentication options directly */
+ CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224),
+
+ /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
+ CINIT(SSL_ENABLE_NPN, LONG, 225),
+
+ /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
+ CINIT(SSL_ENABLE_ALPN, LONG, 226),
+
+ /* Time to wait for a response to a HTTP request containing an
+ * Expect: 100-continue header before sending the data anyway. */
+ CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
+
+ /* This points to a linked list of headers used for proxy requests only,
+ struct curl_slist kind */
+ CINIT(PROXYHEADER, OBJECTPOINT, 228),
+
+ /* Pass in a bitmask of "header options" */
+ CINIT(HEADEROPT, LONG, 229),
+
+ CURLOPT_LASTENTRY /* the last unused */
+} CURLoption;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2011 */
+
+/* This was added in version 7.19.1 */
+#define CURLOPT_POST301 CURLOPT_POSTREDIR
+
+/* These are scheduled to disappear by 2009 */
+
+/* The following were added in 7.17.0 */
+#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_FTPAPPEND CURLOPT_APPEND
+#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
+#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
+
+/* The following were added earlier */
+
+#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
+
+#else
+/* This is set if CURL_NO_OLDIES is defined at compile-time */
+#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
+#endif
+
+
+ /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
+ name resolves addresses using more than one IP protocol version, this
+ option might be handy to force libcurl to use a specific IP version. */
+#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+ versions that your system allows */
+#define CURL_IPRESOLVE_V4 1 /* resolve to ipv4 addresses */
+#define CURL_IPRESOLVE_V6 2 /* resolve to ipv6 addresses */
+
+ /* three convenient "aliases" that follow the name scheme better */
+#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
+
+ /* 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_2_0, /* please use HTTP 2.0 in the request */
+
+ CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
+};
+
+/*
+ * Public API enums for RTSP requests
+ */
+enum {
+ CURL_RTSPREQ_NONE, /* first in list */
+ CURL_RTSPREQ_OPTIONS,
+ CURL_RTSPREQ_DESCRIBE,
+ CURL_RTSPREQ_ANNOUNCE,
+ CURL_RTSPREQ_SETUP,
+ CURL_RTSPREQ_PLAY,
+ CURL_RTSPREQ_PAUSE,
+ CURL_RTSPREQ_TEARDOWN,
+ CURL_RTSPREQ_GET_PARAMETER,
+ CURL_RTSPREQ_SET_PARAMETER,
+ CURL_RTSPREQ_RECORD,
+ CURL_RTSPREQ_RECEIVE,
+ CURL_RTSPREQ_LAST /* last in list */
+};
+
+ /* These enums are for use with the CURLOPT_NETRC option. */
+enum CURL_NETRC_OPTION {
+ CURL_NETRC_IGNORED, /* The .netrc will never be read.
+ * This is the default. */
+ CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
+ * to one in the .netrc. */
+ CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
+ * Unless one is set programmatically, the .netrc
+ * will be queried. */
+ CURL_NETRC_LAST
+};
+
+enum {
+ CURL_SSLVERSION_DEFAULT,
+ CURL_SSLVERSION_TLSv1, /* TLS 1.x */
+ CURL_SSLVERSION_SSLv2,
+ CURL_SSLVERSION_SSLv3,
+ CURL_SSLVERSION_TLSv1_0,
+ CURL_SSLVERSION_TLSv1_1,
+ CURL_SSLVERSION_TLSv1_2,
+
+ CURL_SSLVERSION_LAST /* never use, keep last */
+};
+
+enum CURL_TLSAUTH {
+ CURL_TLSAUTH_NONE,
+ CURL_TLSAUTH_SRP,
+ CURL_TLSAUTH_LAST /* never use, keep last */
+};
+
+/* symbols to use with CURLOPT_POSTREDIR.
+ CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
+ can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
+ | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
+
+#define CURL_REDIR_GET_ALL 0
+#define CURL_REDIR_POST_301 1
+#define CURL_REDIR_POST_302 2
+#define CURL_REDIR_POST_303 4
+#define CURL_REDIR_POST_ALL \
+ (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
+
+typedef enum {
+ CURL_TIMECOND_NONE,
+
+ CURL_TIMECOND_IFMODSINCE,
+ CURL_TIMECOND_IFUNMODSINCE,
+ CURL_TIMECOND_LASTMOD,
+
+ CURL_TIMECOND_LAST
+} curl_TimeCond;
+
+
+/* curl_strequal() and curl_strnequal() are subject for removal in a future
+ libcurl, see lib/README.curlx for details */
+CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
+CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
+
+/* name is uppercase CURLFORM_<name> */
+#ifdef CFINIT
+#undef CFINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CFINIT(name) CURLFORM_ ## name
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define CFINIT(name) CURLFORM_/**/name
+#endif
+
+typedef enum {
+ CFINIT(NOTHING), /********* the first one is unused ************/
+
+ /* */
+ CFINIT(COPYNAME),
+ CFINIT(PTRNAME),
+ CFINIT(NAMELENGTH),
+ CFINIT(COPYCONTENTS),
+ CFINIT(PTRCONTENTS),
+ CFINIT(CONTENTSLENGTH),
+ CFINIT(FILECONTENT),
+ CFINIT(ARRAY),
+ CFINIT(OBSOLETE),
+ CFINIT(FILE),
+
+ CFINIT(BUFFER),
+ CFINIT(BUFFERPTR),
+ CFINIT(BUFFERLENGTH),
+
+ CFINIT(CONTENTTYPE),
+ CFINIT(CONTENTHEADER),
+ CFINIT(FILENAME),
+ CFINIT(END),
+ CFINIT(OBSOLETE2),
+
+ CFINIT(STREAM),
+
+ CURLFORM_LASTENTRY /* the last unused */
+} CURLformoption;
+
+#undef CFINIT /* done */
+
+/* structure to be used as parameter for CURLFORM_ARRAY */
+struct curl_forms {
+ CURLformoption option;
+ const char *value;
+};
+
+/* use this for multipart formpost building */
+/* Returns code for curl_formadd()
+ *
+ * Returns:
+ * CURL_FORMADD_OK on success
+ * CURL_FORMADD_MEMORY if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
+ * CURL_FORMADD_NULL if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated
+ * CURL_FORMADD_MEMORY if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
+ *
+ ***************************************************************************/
+typedef enum {
+ CURL_FORMADD_OK, /* first, no error */
+
+ CURL_FORMADD_MEMORY,
+ CURL_FORMADD_OPTION_TWICE,
+ CURL_FORMADD_NULL,
+ CURL_FORMADD_UNKNOWN_OPTION,
+ CURL_FORMADD_INCOMPLETE,
+ CURL_FORMADD_ILLEGAL_ARRAY,
+ CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
+
+ CURL_FORMADD_LAST /* last */
+} CURLFORMcode;
+
+/*
+ * NAME curl_formadd()
+ *
+ * DESCRIPTION
+ *
+ * Pretty advanced function for building multi-part formposts. Each invoke
+ * adds one part that together construct a full post. Then use
+ * CURLOPT_HTTPPOST to send it off to libcurl.
+ */
+CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...);
+
+/*
+ * callback function for curl_formget()
+ * The void *arg pointer will be the one passed as second argument to
+ * curl_formget().
+ * The character buffer passed to it must not be freed.
+ * Should return the buffer length passed to it as the argument "len" on
+ * success.
+ */
+typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
+ size_t len);
+
+/*
+ * NAME curl_formget()
+ *
+ * DESCRIPTION
+ *
+ * Serialize a curl_httppost struct built with curl_formadd().
+ * Accepts a void pointer as second argument which will be passed to
+ * the curl_formget_callback function.
+ * Returns 0 on success.
+ */
+CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append);
+/*
+ * NAME curl_formfree()
+ *
+ * DESCRIPTION
+ *
+ * Free a multipart formpost previously built with curl_formadd().
+ */
+CURL_EXTERN void curl_formfree(struct curl_httppost *form);
+
+/*
+ * NAME curl_getenv()
+ *
+ * DESCRIPTION
+ *
+ * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
+ * complete. DEPRECATED - see lib/README.curlx
+ */
+CURL_EXTERN char *curl_getenv(const char *variable);
+
+/*
+ * NAME curl_version()
+ *
+ * DESCRIPTION
+ *
+ * Returns a static ascii string of the libcurl version.
+ */
+CURL_EXTERN char *curl_version(void);
+
+/*
+ * NAME curl_easy_escape()
+ *
+ * DESCRIPTION
+ *
+ * Escapes URL strings (converts all letters consider illegal in URLs to their
+ * %XX versions). This function returns a new allocated string or NULL if an
+ * error occurred.
+ */
+CURL_EXTERN char *curl_easy_escape(CURL *handle,
+ const char *string,
+ int length);
+
+/* the previous version: */
+CURL_EXTERN char *curl_escape(const char *string,
+ int length);
+
+
+/*
+ * NAME curl_easy_unescape()
+ *
+ * DESCRIPTION
+ *
+ * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
+ * versions). This function returns a new allocated string or NULL if an error
+ * occurred.
+ * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
+ * converted into the host encoding.
+ */
+CURL_EXTERN char *curl_easy_unescape(CURL *handle,
+ const char *string,
+ int length,
+ int *outlength);
+
+/* the previous version */
+CURL_EXTERN char *curl_unescape(const char *string,
+ int length);
+
+/*
+ * NAME curl_free()
+ *
+ * DESCRIPTION
+ *
+ * Provided for de-allocation in the same translation unit that did the
+ * allocation. Added in libcurl 7.10
+ */
+CURL_EXTERN void curl_free(void *p);
+
+/*
+ * NAME curl_global_init()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() should be invoked exactly once for each application that
+ * uses libcurl and before any call of other libcurl functions.
+ *
+ * This function is not thread-safe!
+ */
+CURL_EXTERN CURLcode curl_global_init(long flags);
+
+/*
+ * NAME curl_global_init_mem()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() or curl_global_init_mem() should be invoked exactly once
+ * for each application that uses libcurl. This function can be used to
+ * initialize libcurl and set user defined memory management callback
+ * functions. Users can implement memory management routines to check for
+ * memory leaks, check for mis-use of the curl library etc. User registered
+ * callback routines with be invoked by this library instead of the system
+ * memory management routines like malloc, free etc.
+ */
+CURL_EXTERN CURLcode curl_global_init_mem(long flags,
+ curl_malloc_callback m,
+ curl_free_callback f,
+ curl_realloc_callback r,
+ curl_strdup_callback s,
+ curl_calloc_callback c);
+
+/*
+ * NAME curl_global_cleanup()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_cleanup() should be invoked exactly once for each application
+ * that uses libcurl
+ */
+CURL_EXTERN void curl_global_cleanup(void);
+
+/* linked-list structure for the CURLOPT_QUOTE option (and other) */
+struct curl_slist {
+ char *data;
+ struct curl_slist *next;
+};
+
+/*
+ * NAME curl_slist_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
+ const char *);
+
+/*
+ * NAME curl_slist_free_all()
+ *
+ * DESCRIPTION
+ *
+ * free a previously built curl_slist.
+ */
+CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
+
+/*
+ * NAME curl_getdate()
+ *
+ * DESCRIPTION
+ *
+ * Returns the time, in seconds since 1 Jan 1970 of the time string given in
+ * the first argument. The time argument in the second parameter is unused
+ * and should be set to NULL.
+ */
+CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
+
+/* info about the certificate chain, only for OpenSSL builds. Asked
+ for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+struct curl_certinfo {
+ int num_of_certs; /* number of certificates with information */
+ struct curl_slist **certinfo; /* for each index in this array, there's a
+ linked list with textual information in the
+ format "name: value" */
+};
+
+/* enum for the different supported SSL backends */
+typedef enum {
+ CURLSSLBACKEND_NONE = 0,
+ CURLSSLBACKEND_OPENSSL = 1,
+ CURLSSLBACKEND_GNUTLS = 2,
+ CURLSSLBACKEND_NSS = 3,
+ CURLSSLBACKEND_QSOSSL = 4,
+ CURLSSLBACKEND_GSKIT = 5,
+ CURLSSLBACKEND_POLARSSL = 6,
+ CURLSSLBACKEND_CYASSL = 7,
+ CURLSSLBACKEND_SCHANNEL = 8,
+ CURLSSLBACKEND_DARWINSSL = 9,
+ CURLSSLBACKEND_AXTLS = 10
+} curl_sslbackend;
+
+/* Information about the SSL library used and the respective internal SSL
+ handle, which can be used to obtain further information regarding the
+ connection. Asked for with CURLINFO_TLS_SESSION. */
+struct curl_tlssessioninfo {
+ curl_sslbackend backend;
+ void *internals;
+};
+
+#define CURLINFO_STRING 0x100000
+#define CURLINFO_LONG 0x200000
+#define CURLINFO_DOUBLE 0x300000
+#define CURLINFO_SLIST 0x400000
+#define CURLINFO_MASK 0x0fffff
+#define CURLINFO_TYPEMASK 0xf00000
+
+typedef enum {
+ CURLINFO_NONE, /* first, never use this */
+ CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
+ CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
+ CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3,
+ CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
+ CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
+ CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
+ CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
+ CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
+ CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
+ CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
+ CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
+ CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
+ CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
+ CURLINFO_FILETIME = CURLINFO_LONG + 14,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
+ CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
+ CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
+ CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
+ CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
+ CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
+ CURLINFO_PRIVATE = CURLINFO_STRING + 21,
+ CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22,
+ CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23,
+ CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24,
+ CURLINFO_OS_ERRNO = CURLINFO_LONG + 25,
+ CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
+ CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
+ CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
+ CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
+ CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
+ CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
+ CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
+ CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
+ CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
+ CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
+ CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
+ CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
+ CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
+ CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
+ CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
+ CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
+ CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
+ CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
+ /* Fill in new entries below here! */
+
+ CURLINFO_LASTONE = 43
+} CURLINFO;
+
+/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+ CURLINFO_HTTP_CODE */
+#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
+
+typedef enum {
+ CURLCLOSEPOLICY_NONE, /* first, never use this */
+
+ CURLCLOSEPOLICY_OLDEST,
+ CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
+ CURLCLOSEPOLICY_LEAST_TRAFFIC,
+ CURLCLOSEPOLICY_SLOWEST,
+ CURLCLOSEPOLICY_CALLBACK,
+
+ CURLCLOSEPOLICY_LAST /* last, never use this */
+} curl_closepolicy;
+
+#define CURL_GLOBAL_SSL (1<<0)
+#define CURL_GLOBAL_WIN32 (1<<1)
+#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
+#define CURL_GLOBAL_NOTHING 0
+#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
+#define CURL_GLOBAL_ACK_EINTR (1<<2)
+
+
+/*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+/* Different data locks for a single share */
+typedef enum {
+ CURL_LOCK_DATA_NONE = 0,
+ /* CURL_LOCK_DATA_SHARE is used internally to say that
+ * the locking is just made to change the internal state of the share
+ * itself.
+ */
+ CURL_LOCK_DATA_SHARE,
+ CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_DATA_DNS,
+ CURL_LOCK_DATA_SSL_SESSION,
+ CURL_LOCK_DATA_CONNECT,
+ CURL_LOCK_DATA_LAST
+} curl_lock_data;
+
+/* Different lock access types */
+typedef enum {
+ CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */
+ CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
+ CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
+ CURL_LOCK_ACCESS_LAST /* never use */
+} curl_lock_access;
+
+typedef void (*curl_lock_function)(CURL *handle,
+ curl_lock_data data,
+ curl_lock_access locktype,
+ void *userptr);
+typedef void (*curl_unlock_function)(CURL *handle,
+ curl_lock_data data,
+ void *userptr);
+
+typedef void CURLSH;
+
+typedef enum {
+ CURLSHE_OK, /* all is fine */
+ CURLSHE_BAD_OPTION, /* 1 */
+ CURLSHE_IN_USE, /* 2 */
+ CURLSHE_INVALID, /* 3 */
+ CURLSHE_NOMEM, /* 4 out of memory */
+ CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
+ CURLSHE_LAST /* never use */
+} CURLSHcode;
+
+typedef enum {
+ CURLSHOPT_NONE, /* don't use */
+ CURLSHOPT_SHARE, /* specify a data type to share */
+ CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
+ CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */
+ CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
+ CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock
+ callback functions */
+ CURLSHOPT_LAST /* never use */
+} CURLSHoption;
+
+CURL_EXTERN CURLSH *curl_share_init(void);
+CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
+CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
+
+/****************************************************************************
+ * Structures for querying information about the curl library at runtime.
+ */
+
+typedef enum {
+ CURLVERSION_FIRST,
+ CURLVERSION_SECOND,
+ CURLVERSION_THIRD,
+ CURLVERSION_FOURTH,
+ CURLVERSION_LAST /* never actually use this */
+} CURLversion;
+
+/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
+ basically all programs ever that want to get version information. It is
+ meant to be a built-in version number for what kind of struct the caller
+ expects. If the struct ever changes, we redefine the NOW to another enum
+ from above. */
+#define CURLVERSION_NOW CURLVERSION_FOURTH
+
+typedef struct {
+ CURLversion age; /* age of the returned struct */
+ const char *version; /* LIBCURL_VERSION */
+ unsigned int version_num; /* LIBCURL_VERSION_NUM */
+ const char *host; /* OS/host/cpu/machine when configured */
+ int features; /* bitmask, see defines below */
+ const char *ssl_version; /* human readable string */
+ long ssl_version_num; /* not used anymore, always 0 */
+ const char *libz_version; /* human readable string */
+ /* protocols is terminated by an entry with a NULL protoname */
+ const char * const *protocols;
+
+ /* The fields below this were added in CURLVERSION_SECOND */
+ const char *ares;
+ int ares_num;
+
+ /* This field was added in CURLVERSION_THIRD */
+ const char *libidn;
+
+ /* These field were added in CURLVERSION_FOURTH */
+
+ /* Same as '_libiconv_version' if built with HAVE_ICONV */
+ int iconv_ver_num;
+
+ const char *libssh_version; /* human readable string */
+
+} curl_version_info_data;
+
+#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
+#define CURL_VERSION_KERBEROS4 (1<<1) /* kerberos auth is supported */
+#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
+#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
+#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
+#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support
+ (deprecated) */
+#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */
+#define CURL_VERSION_ASYNCHDNS (1<<7) /* asynchronous dns resolves */
+#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */
+#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
+#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */
+#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */
+#define CURL_VERSION_CONV (1<<12) /* character conversions supported */
+#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
+#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
+#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */
+#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
+#define CURL_VERSION_GSSAPI (1<<17) /* GSS-API is supported */
+
+ /*
+ * NAME curl_version_info()
+ *
+ * DESCRIPTION
+ *
+ * This function returns a pointer to a static copy of the version info
+ * struct. See above.
+ */
+CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+
+/*
+ * NAME curl_easy_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_strerror function may be used to turn a CURLcode value
+ * into the equivalent human readable error string. This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_easy_strerror(CURLcode);
+
+/*
+ * NAME curl_share_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_share_strerror function may be used to turn a CURLSHcode value
+ * into the equivalent human readable error string. This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
+
+/*
+ * NAME curl_easy_pause()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_pause function pauses or unpauses transfers. Select the new
+ * state by setting the bitmask, use the convenience defines below.
+ *
+ */
+CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
+
+#define CURLPAUSE_RECV (1<<0)
+#define CURLPAUSE_RECV_CONT (0)
+
+#define CURLPAUSE_SEND (1<<2)
+#define CURLPAUSE_SEND_CONT (0)
+
+#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND)
+#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* unfortunately, the easy.h and multi.h include files need options and info
+ stuff before they can be included! */
+#include "easy.h" /* nothing in curl is fun without the easy stuff */
+#include "multi.h"
+
+/* the typechecker doesn't work in C++ (yet) */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+ ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
+ !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
+#include "typecheck-gcc.h"
+#else
+#if defined(__STDC__) && (__STDC__ >= 1)
+/* This preprocessor magic that replaces a call with the exact same call is
+ only done to make sure application authors pass exactly three arguments
+ to these functions. */
+#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
+#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+#endif /* __STDC__ >= 1 */
+#endif /* gcc >= 4.3 && !__cplusplus */
+
+#endif /* __CURL_CURL_H */
diff --git a/external/libcurl_android/jni/libcurl/include/curl/curlbuild.h b/external/libcurl_android/jni/libcurl/include/curl/curlbuild.h
new file mode 100755
index 00000000..15a321ec
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/curlbuild.h
@@ -0,0 +1,198 @@
+/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */
+#ifndef __CURL_CURLBUILD_H
+#define __CURL_CURLBUILD_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * If you think that something actually needs to be changed, adjusted
+ * or fixed in this file, then, report it on the libcurl development
+ * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * This header file shall only export symbols which are 'curl' or 'CURL'
+ * prefixed, otherwise public name space would be polluted.
+ *
+ * NOTE 2:
+ * -------
+ *
+ * Right now you might be staring at file include/curl/curlbuild.h.in or
+ * at file include/curl/curlbuild.h, this is due to the following reason:
+ *
+ * On systems capable of running the configure script, the configure process
+ * will overwrite the distributed include/curl/curlbuild.h file with one that
+ * is suitable and specific to the library being configured and built, which
+ * is generated from the include/curl/curlbuild.h.in template file.
+ *
+ */
+
+/* ================================================================ */
+/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
+/* ================================================================ */
+
+#ifdef CURL_SIZEOF_LONG
+#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
+#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_T
+#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_TU
+#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
+#endif
+
+#ifdef CURL_FORMAT_OFF_T
+#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_OFF_T
+#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_T
+#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_TU
+#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
+#endif
+
+/* ================================================================ */
+/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
+/* ================================================================ */
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file ws2tcpip.h must be included by the external interface. */
+/* #undef CURL_PULL_WS2TCPIP_H */
+#ifdef CURL_PULL_WS2TCPIP_H
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/types.h must be included by the external interface. */
+#define CURL_PULL_SYS_TYPES_H 1
+#ifdef CURL_PULL_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file stdint.h must be included by the external interface. */
+#define CURL_PULL_STDINT_H 1
+#ifdef CURL_PULL_STDINT_H
+# include <stdint.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file inttypes.h must be included by the external interface. */
+#define CURL_PULL_INTTYPES_H 1
+#ifdef CURL_PULL_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/socket.h must be included by the external interface. */
+#define CURL_PULL_SYS_SOCKET_H 1
+#ifdef CURL_PULL_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/poll.h must be included by the external interface. */
+/* #undef CURL_PULL_SYS_POLL_H */
+#ifdef CURL_PULL_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+
+/* The size of `long', as computed by sizeof. */
+#define CURL_SIZEOF_LONG 4
+
+/* Integral data type used for curl_socklen_t. */
+#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+
+/* The size of `curl_socklen_t', as computed by sizeof. */
+#define CURL_SIZEOF_CURL_SOCKLEN_T 4
+
+/* Data type definition of curl_socklen_t. */
+typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+
+/* Signed integral data type used for curl_off_t. */
+#define CURL_TYPEOF_CURL_OFF_T int64_t
+
+/* Data type definition of curl_off_t. */
+typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+
+/* curl_off_t formatting string directive without "%" conversion specifier. */
+#define CURL_FORMAT_CURL_OFF_T "lld"
+
+/* unsigned curl_off_t formatting string without "%" conversion specifier. */
+#define CURL_FORMAT_CURL_OFF_TU "llu"
+
+/* curl_off_t formatting string directive with "%" conversion specifier. */
+#define CURL_FORMAT_OFF_T "%lld"
+
+/* The size of `curl_off_t', as computed by sizeof. */
+#define CURL_SIZEOF_CURL_OFF_T 8
+
+/* curl_off_t constant suffix. */
+#define CURL_SUFFIX_CURL_OFF_T LL
+
+/* unsigned curl_off_t constant suffix. */
+#define CURL_SUFFIX_CURL_OFF_TU ULL
+
+#endif /* __CURL_CURLBUILD_H */
diff --git a/external/libcurl_android/jni/libcurl/include/curl/curlbuild.h.in b/external/libcurl_android/jni/libcurl/include/curl/curlbuild.h.in
new file mode 100755
index 00000000..e29f195d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/curlbuild.h.in
@@ -0,0 +1,197 @@
+#ifndef __CURL_CURLBUILD_H
+#define __CURL_CURLBUILD_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * If you think that something actually needs to be changed, adjusted
+ * or fixed in this file, then, report it on the libcurl development
+ * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * This header file shall only export symbols which are 'curl' or 'CURL'
+ * prefixed, otherwise public name space would be polluted.
+ *
+ * NOTE 2:
+ * -------
+ *
+ * Right now you might be staring at file include/curl/curlbuild.h.in or
+ * at file include/curl/curlbuild.h, this is due to the following reason:
+ *
+ * On systems capable of running the configure script, the configure process
+ * will overwrite the distributed include/curl/curlbuild.h file with one that
+ * is suitable and specific to the library being configured and built, which
+ * is generated from the include/curl/curlbuild.h.in template file.
+ *
+ */
+
+/* ================================================================ */
+/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
+/* ================================================================ */
+
+#ifdef CURL_SIZEOF_LONG
+#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
+#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
+#endif
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_T
+#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_FORMAT_CURL_OFF_TU
+#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
+#endif
+
+#ifdef CURL_FORMAT_OFF_T
+#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SIZEOF_CURL_OFF_T
+#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_T
+#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
+#endif
+
+#ifdef CURL_SUFFIX_CURL_OFF_TU
+#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
+#endif
+
+/* ================================================================ */
+/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
+/* ================================================================ */
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file ws2tcpip.h must be included by the external interface. */
+#undef CURL_PULL_WS2TCPIP_H
+#ifdef CURL_PULL_WS2TCPIP_H
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/types.h must be included by the external interface. */
+#undef CURL_PULL_SYS_TYPES_H
+#ifdef CURL_PULL_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file stdint.h must be included by the external interface. */
+#undef CURL_PULL_STDINT_H
+#ifdef CURL_PULL_STDINT_H
+# include <stdint.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file inttypes.h must be included by the external interface. */
+#undef CURL_PULL_INTTYPES_H
+#ifdef CURL_PULL_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/socket.h must be included by the external interface. */
+#undef CURL_PULL_SYS_SOCKET_H
+#ifdef CURL_PULL_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+/* Configure process defines this to 1 when it finds out that system */
+/* header file sys/poll.h must be included by the external interface. */
+#undef CURL_PULL_SYS_POLL_H
+#ifdef CURL_PULL_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+
+/* The size of `long', as computed by sizeof. */
+#undef CURL_SIZEOF_LONG
+
+/* Integral data type used for curl_socklen_t. */
+#undef CURL_TYPEOF_CURL_SOCKLEN_T
+
+/* The size of `curl_socklen_t', as computed by sizeof. */
+#undef CURL_SIZEOF_CURL_SOCKLEN_T
+
+/* Data type definition of curl_socklen_t. */
+typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+
+/* Signed integral data type used for curl_off_t. */
+#undef CURL_TYPEOF_CURL_OFF_T
+
+/* Data type definition of curl_off_t. */
+typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+
+/* curl_off_t formatting string directive without "%" conversion specifier. */
+#undef CURL_FORMAT_CURL_OFF_T
+
+/* unsigned curl_off_t formatting string without "%" conversion specifier. */
+#undef CURL_FORMAT_CURL_OFF_TU
+
+/* curl_off_t formatting string directive with "%" conversion specifier. */
+#undef CURL_FORMAT_OFF_T
+
+/* The size of `curl_off_t', as computed by sizeof. */
+#undef CURL_SIZEOF_CURL_OFF_T
+
+/* curl_off_t constant suffix. */
+#undef CURL_SUFFIX_CURL_OFF_T
+
+/* unsigned curl_off_t constant suffix. */
+#undef CURL_SUFFIX_CURL_OFF_TU
+
+#endif /* __CURL_CURLBUILD_H */
diff --git a/external/libcurl_android/jni/libcurl/include/curl/curlrules.h b/external/libcurl_android/jni/libcurl/include/curl/curlrules.h
new file mode 100755
index 00000000..7c2ede35
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/curlrules.h
@@ -0,0 +1,262 @@
+#ifndef __CURL_CURLRULES_H
+#define __CURL_CURLRULES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* COMPILE TIME SANITY CHECKS */
+/* ================================================================ */
+
+/*
+ * NOTE 1:
+ * -------
+ *
+ * All checks done in this file are intentionally placed in a public
+ * header file which is pulled by curl/curl.h when an application is
+ * being built using an already built libcurl library. Additionally
+ * this file is also included and used when building the library.
+ *
+ * If compilation fails on this file it is certainly sure that the
+ * problem is elsewhere. It could be a problem in the curlbuild.h
+ * header file, or simply that you are using different compilation
+ * settings than those used to build the library.
+ *
+ * Nothing in this file is intended to be modified or adjusted by the
+ * curl library user nor by the curl library builder.
+ *
+ * Do not deactivate any check, these are done to make sure that the
+ * library is properly built and used.
+ *
+ * You can find further help on the libcurl development mailing list:
+ * http://cool.haxx.se/mailman/listinfo/curl-library/
+ *
+ * NOTE 2
+ * ------
+ *
+ * Some of the following compile time checks are based on the fact
+ * that the dimension of a constant array can not be a negative one.
+ * In this way if the compile time verification fails, the compilation
+ * will fail issuing an error. The error description wording is compiler
+ * dependent but it will be quite similar to one of the following:
+ *
+ * "negative subscript or subscript is too large"
+ * "array must have at least one element"
+ * "-1 is an illegal array size"
+ * "size of array is negative"
+ *
+ * If you are building an application which tries to use an already
+ * built libcurl library and you are getting this kind of errors on
+ * this file, it is a clear indication that there is a mismatch between
+ * how the library was built and how you are trying to use it for your
+ * application. Your already compiled or binary library provider is the
+ * only one who can give you the details you need to properly use it.
+ */
+
+/*
+ * Verify that some macros are actually defined.
+ */
+
+#ifndef CURL_SIZEOF_LONG
+# error "CURL_SIZEOF_LONG definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
+#endif
+
+#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
+# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
+#endif
+
+#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
+# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
+#endif
+
+#ifndef CURL_TYPEOF_CURL_OFF_T
+# error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_FORMAT_CURL_OFF_T
+# error "CURL_FORMAT_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_FORMAT_CURL_OFF_TU
+# error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
+#endif
+
+#ifndef CURL_FORMAT_OFF_T
+# error "CURL_FORMAT_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SIZEOF_CURL_OFF_T
+# error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SUFFIX_CURL_OFF_T
+# error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
+#endif
+
+#ifndef CURL_SUFFIX_CURL_OFF_TU
+# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
+ Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
+#endif
+
+/*
+ * Macros private to this header file.
+ */
+
+#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
+
+#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
+
+/*
+ * Verify that the size previously defined and expected for long
+ * is the same as the one reported by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_01__
+ [CurlchkszEQ(long, CURL_SIZEOF_LONG)];
+
+/*
+ * Verify that the size previously defined and expected for
+ * curl_off_t is actually the the same as the one reported
+ * by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_02__
+ [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
+
+/*
+ * Verify at compile time that the size of curl_off_t as reported
+ * by sizeof() is greater or equal than the one reported for long
+ * for the current compilation.
+ */
+
+typedef char
+ __curl_rule_03__
+ [CurlchkszGE(curl_off_t, long)];
+
+/*
+ * Verify that the size previously defined and expected for
+ * curl_socklen_t is actually the the same as the one reported
+ * by sizeof() at compile time.
+ */
+
+typedef char
+ __curl_rule_04__
+ [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
+
+/*
+ * Verify at compile time that the size of curl_socklen_t as reported
+ * by sizeof() is greater or equal than the one reported for int for
+ * the current compilation.
+ */
+
+typedef char
+ __curl_rule_05__
+ [CurlchkszGE(curl_socklen_t, int)];
+
+/* ================================================================ */
+/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
+/* ================================================================ */
+
+/*
+ * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
+ * these to be visible and exported by the external libcurl interface API,
+ * while also making them visible to the library internals, simply including
+ * curl_setup.h, without actually needing to include curl.h internally.
+ * If some day this section would grow big enough, all this should be moved
+ * to its own header file.
+ */
+
+/*
+ * Figure out if we can use the ## preprocessor operator, which is supported
+ * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
+ * or __cplusplus so we need to carefully check for them too.
+ */
+
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
+ defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
+ defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
+ defined(__ILEC400__)
+ /* This compiler is believed to have an ISO compatible preprocessor */
+#define CURL_ISOCPP
+#else
+ /* This compiler is believed NOT to have an ISO compatible preprocessor */
+#undef CURL_ISOCPP
+#endif
+
+/*
+ * Macros for minimum-width signed and unsigned curl_off_t integer constants.
+ */
+
+#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
+# define __CURL_OFF_T_C_HLPR2(x) x
+# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
+# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
+# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
+#else
+# ifdef CURL_ISOCPP
+# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
+# else
+# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
+# endif
+# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
+# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
+# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
+#endif
+
+/*
+ * Get rid of macros private to this header file.
+ */
+
+#undef CurlchkszEQ
+#undef CurlchkszGE
+
+/*
+ * Get rid of macros not intended to exist beyond this point.
+ */
+
+#undef CURL_PULL_WS2TCPIP_H
+#undef CURL_PULL_SYS_TYPES_H
+#undef CURL_PULL_SYS_SOCKET_H
+#undef CURL_PULL_SYS_POLL_H
+#undef CURL_PULL_STDINT_H
+#undef CURL_PULL_INTTYPES_H
+
+#undef CURL_TYPEOF_CURL_SOCKLEN_T
+#undef CURL_TYPEOF_CURL_OFF_T
+
+#ifdef CURL_NO_OLDIES
+#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
+#endif
+
+#endif /* __CURL_CURLRULES_H */
diff --git a/external/libcurl_android/jni/libcurl/include/curl/curlver.h b/external/libcurl_android/jni/libcurl/include/curl/curlver.h
new file mode 100755
index 00000000..ee9a0589
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/curlver.h
@@ -0,0 +1,69 @@
+#ifndef __CURL_CURLVER_H
+#define __CURL_CURLVER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This header file contains nothing but libcurl version info, generated by
+ a script at release-time. This was made its own header file in 7.11.2 */
+
+/* This is the global package copyright */
+#define LIBCURL_COPYRIGHT "1996 - 2014 Daniel Stenberg, <daniel@haxx.se>."
+
+/* This is the version number of the libcurl package from which this header
+ file origins: */
+#define LIBCURL_VERSION "7.38.0"
+
+/* The numeric version number is also available "in parts" by using these
+ defines: */
+#define LIBCURL_VERSION_MAJOR 7
+#define LIBCURL_VERSION_MINOR 38
+#define LIBCURL_VERSION_PATCH 0
+
+/* This is the numeric version of the libcurl version number, meant for easier
+ parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+ always follow this syntax:
+
+ 0xXXYYZZ
+
+ Where XX, YY and ZZ are the main version, release and patch numbers in
+ hexadecimal (using 8 bits each). All three numbers are always represented
+ using two digits. 1.2 would appear as "0x010200" while version 9.11.7
+ appears as "0x090b07".
+
+ This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+ and it is always a greater number in a more recent release. It makes
+ comparisons with greater than and less than work.
+*/
+#define LIBCURL_VERSION_NUM 0x072600
+
+/*
+ * This is the date and time when the full source package was created. The
+ * timestamp is not stored in git, as the timestamp is properly set in the
+ * tarballs by the maketgz script.
+ *
+ * The format of the date should follow this template:
+ *
+ * "Mon Feb 12 11:35:33 UTC 2007"
+ */
+#define LIBCURL_TIMESTAMP "Wed Sep 10 06:19:50 UTC 2014"
+
+#endif /* __CURL_CURLVER_H */
diff --git a/external/libcurl_android/jni/libcurl/include/curl/easy.h b/external/libcurl_android/jni/libcurl/include/curl/easy.h
new file mode 100755
index 00000000..c1e3e760
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/easy.h
@@ -0,0 +1,102 @@
+#ifndef __CURL_EASY_H
+#define __CURL_EASY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN CURL *curl_easy_init(void);
+CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
+CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
+CURL_EXTERN void curl_easy_cleanup(CURL *curl);
+
+/*
+ * NAME curl_easy_getinfo()
+ *
+ * DESCRIPTION
+ *
+ * Request internal information from the curl session with this function. The
+ * third argument MUST be a pointer to a long, a pointer to a char * or a
+ * pointer to a double (as the documentation describes elsewhere). The data
+ * pointed to will be filled in accordingly and can be relied upon only if the
+ * function returns CURLE_OK. This function is intended to get used *AFTER* a
+ * performed transfer, all results from this function are undefined until the
+ * transfer is completed.
+ */
+CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
+
+
+/*
+ * NAME curl_easy_duphandle()
+ *
+ * DESCRIPTION
+ *
+ * Creates a new curl session handle with the same options set for the handle
+ * passed in. Duplicating a handle could only be a matter of cloning data and
+ * options, internal state info and things like persistent connections cannot
+ * be transferred. It is useful in multithreaded applications when you can run
+ * curl_easy_duphandle() for each new thread to avoid a series of identical
+ * curl_easy_setopt() invokes in every thread.
+ */
+CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
+
+/*
+ * NAME curl_easy_reset()
+ *
+ * DESCRIPTION
+ *
+ * Re-initializes a CURL handle to the default values. This puts back the
+ * handle to the same state as it was in when it was just created.
+ *
+ * It does keep: live connections, the Session ID cache, the DNS cache and the
+ * cookies.
+ */
+CURL_EXTERN void curl_easy_reset(CURL *curl);
+
+/*
+ * NAME curl_easy_recv()
+ *
+ * DESCRIPTION
+ *
+ * Receives data from the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *n);
+
+/*
+ * NAME curl_easy_send()
+ *
+ * DESCRIPTION
+ *
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/include/curl/mprintf.h b/external/libcurl_android/jni/libcurl/include/curl/mprintf.h
new file mode 100755
index 00000000..cc9e7f5d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/mprintf.h
@@ -0,0 +1,81 @@
+#ifndef __CURL_MPRINTF_H
+#define __CURL_MPRINTF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <stdarg.h>
+#include <stdio.h> /* needed for FILE */
+
+#include "curl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN int curl_mprintf(const char *format, ...);
+CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
+CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
+CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
+ const char *format, ...);
+CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
+CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
+CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
+CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
+ const char *format, va_list args);
+CURL_EXTERN char *curl_maprintf(const char *format, ...);
+CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
+
+#ifdef _MPRINTF_REPLACE
+# undef printf
+# undef fprintf
+# undef sprintf
+# undef vsprintf
+# undef snprintf
+# undef vprintf
+# undef vfprintf
+# undef vsnprintf
+# undef aprintf
+# undef vaprintf
+# define printf curl_mprintf
+# define fprintf curl_mfprintf
+#ifdef CURLDEBUG
+/* When built with CURLDEBUG we define away the sprintf functions since we
+ don't want internal code to be using them */
+# define sprintf sprintf_was_used
+# define vsprintf vsprintf_was_used
+#else
+# define sprintf curl_msprintf
+# define vsprintf curl_mvsprintf
+#endif
+# define snprintf curl_msnprintf
+# define vprintf curl_mvprintf
+# define vfprintf curl_mvfprintf
+# define vsnprintf curl_mvsnprintf
+# define aprintf curl_maprintf
+# define vaprintf curl_mvaprintf
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CURL_MPRINTF_H */
diff --git a/external/libcurl_android/jni/libcurl/include/curl/multi.h b/external/libcurl_android/jni/libcurl/include/curl/multi.h
new file mode 100755
index 00000000..3c4acb0f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/multi.h
@@ -0,0 +1,399 @@
+#ifndef __CURL_MULTI_H
+#define __CURL_MULTI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ This is an "external" header file. Don't give away any internals here!
+
+ GOALS
+
+ o Enable a "pull" interface. The application that uses libcurl decides where
+ and when to ask libcurl to get/send data.
+
+ o Enable multiple simultaneous transfers in the same thread without making it
+ complicated for the application.
+
+ o Enable the application to select() on its own file descriptors and curl's
+ file descriptors simultaneous easily.
+
+*/
+
+/*
+ * This header file should not really need to include "curl.h" since curl.h
+ * itself includes this file and we expect user applications to do #include
+ * <curl/curl.h> without the need for especially including multi.h.
+ *
+ * For some reason we added this include here at one point, and rather than to
+ * break existing (wrongly written) libcurl applications, we leave it as-is
+ * but with this warning attached.
+ */
+#include "curl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void CURLM;
+
+typedef enum {
+ CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
+ curl_multi_socket*() soon */
+ CURLM_OK,
+ CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
+ CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
+ CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
+ CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
+ CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
+ CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
+ CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
+ attempted to get added - again */
+ CURLM_LAST
+} CURLMcode;
+
+/* just to make code nicer when using curl_multi_socket() you can now check
+ for CURLM_CALL_MULTI_SOCKET too in the same style it works for
+ curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
+
+typedef enum {
+ CURLMSG_NONE, /* first, not used */
+ CURLMSG_DONE, /* This easy handle has completed. 'result' contains
+ the CURLcode of the transfer */
+ CURLMSG_LAST /* last, not used */
+} CURLMSG;
+
+struct CURLMsg {
+ CURLMSG msg; /* what this message means */
+ CURL *easy_handle; /* the handle it concerns */
+ union {
+ void *whatever; /* message-specific data */
+ CURLcode result; /* return code for transfer */
+ } data;
+};
+typedef struct CURLMsg CURLMsg;
+
+/* Based on poll(2) structure and values.
+ * We don't use pollfd and POLL* constants explicitly
+ * to cover platforms without poll(). */
+#define CURL_WAIT_POLLIN 0x0001
+#define CURL_WAIT_POLLPRI 0x0002
+#define CURL_WAIT_POLLOUT 0x0004
+
+struct curl_waitfd {
+ curl_socket_t fd;
+ short events;
+ short revents; /* not supported yet */
+};
+
+/*
+ * Name: curl_multi_init()
+ *
+ * Desc: inititalize multi-style curl usage
+ *
+ * Returns: a new CURLM handle to use in all 'curl_multi' functions.
+ */
+CURL_EXTERN CURLM *curl_multi_init(void);
+
+/*
+ * Name: curl_multi_add_handle()
+ *
+ * Desc: add a standard curl handle to the multi stack
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+ CURL *curl_handle);
+
+ /*
+ * Name: curl_multi_remove_handle()
+ *
+ * Desc: removes a curl handle from the multi stack again
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+ CURL *curl_handle);
+
+ /*
+ * Name: curl_multi_fdset()
+ *
+ * Desc: Ask curl for its fd_set sets. The app can use these to select() or
+ * poll() on. We want curl_multi_perform() called as soon as one of
+ * them are ready.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *exc_fd_set,
+ int *max_fd);
+
+/*
+ * Name: curl_multi_wait()
+ *
+ * Desc: Poll on all fds within a CURLM set as well as any
+ * additional fds passed to the function.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret);
+
+ /*
+ * Name: curl_multi_perform()
+ *
+ * Desc: When the app thinks there's data available for curl it calls this
+ * function to read/write whatever there is right now. This returns
+ * as soon as the reads and writes are done. This function does not
+ * require that there actually is data available for reading or that
+ * data can be written, it can be called just in case. It returns
+ * the number of handles that still transfer data in the second
+ * argument's integer-pointer.
+ *
+ * Returns: CURLMcode type, general multi error code. *NOTE* that this only
+ * returns errors etc regarding the whole multi stack. There might
+ * still have occurred problems on invidual transfers even when this
+ * returns OK.
+ */
+CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
+ int *running_handles);
+
+ /*
+ * Name: curl_multi_cleanup()
+ *
+ * Desc: Cleans up and removes a whole multi stack. It does not free or
+ * touch any individual easy handles in any way. We need to define
+ * in what state those handles will be if this function is called
+ * in the middle of a transfer.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
+
+/*
+ * Name: curl_multi_info_read()
+ *
+ * Desc: Ask the multi handle if there's any messages/informationals from
+ * the individual transfers. Messages include informationals such as
+ * error code from the transfer or just the fact that a transfer is
+ * completed. More details on these should be written down as well.
+ *
+ * Repeated calls to this function will return a new struct each
+ * time, until a special "end of msgs" struct is returned as a signal
+ * that there is no more to get at this point.
+ *
+ * The data the returned pointer points to will not survive calling
+ * curl_multi_cleanup().
+ *
+ * The 'CURLMsg' struct is meant to be very simple and only contain
+ * very basic informations. If more involved information is wanted,
+ * we will provide the particular "transfer handle" in that struct
+ * and that should/could/would be used in subsequent
+ * curl_easy_getinfo() calls (or similar). The point being that we
+ * must never expose complex structs to applications, as then we'll
+ * undoubtably get backwards compatibility problems in the future.
+ *
+ * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
+ * of structs. It also writes the number of messages left in the
+ * queue (after this read) in the integer the second argument points
+ * to.
+ */
+CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
+ int *msgs_in_queue);
+
+/*
+ * Name: curl_multi_strerror()
+ *
+ * Desc: The curl_multi_strerror function may be used to turn a CURLMcode
+ * value into the equivalent human readable error string. This is
+ * useful for printing meaningful error messages.
+ *
+ * Returns: A pointer to a zero-terminated error message.
+ */
+CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
+
+/*
+ * Name: curl_multi_socket() and
+ * curl_multi_socket_all()
+ *
+ * Desc: An alternative version of curl_multi_perform() that allows the
+ * application to pass in one of the file descriptors that have been
+ * detected to have "action" on them and let libcurl perform.
+ * See man page for details.
+ */
+#define CURL_POLL_NONE 0
+#define CURL_POLL_IN 1
+#define CURL_POLL_OUT 2
+#define CURL_POLL_INOUT 3
+#define CURL_POLL_REMOVE 4
+
+#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
+
+#define CURL_CSELECT_IN 0x01
+#define CURL_CSELECT_OUT 0x02
+#define CURL_CSELECT_ERR 0x04
+
+typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
+ curl_socket_t s, /* socket */
+ int what, /* see above */
+ void *userp, /* private callback
+ pointer */
+ void *socketp); /* private socket
+ pointer */
+/*
+ * Name: curl_multi_timer_callback
+ *
+ * Desc: Called by libcurl whenever the library detects a change in the
+ * maximum number of milliseconds the app is allowed to wait before
+ * curl_multi_socket() or curl_multi_perform() must be called
+ * (to allow libcurl's timed events to take place).
+ *
+ * Returns: The callback should return zero.
+ */
+typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
+ long timeout_ms, /* see above */
+ void *userp); /* private callback
+ pointer */
+
+CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+ int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
+ curl_socket_t s,
+ int ev_bitmask,
+ int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+ int *running_handles);
+
+#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
+/* This macro below was added in 7.16.3 to push users who recompile to use
+ the new curl_multi_socket_action() instead of the old curl_multi_socket()
+*/
+#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
+#endif
+
+/*
+ * Name: curl_multi_timeout()
+ *
+ * Desc: Returns the maximum number of milliseconds the app is allowed to
+ * wait before curl_multi_socket() or curl_multi_perform() must be
+ * called (to allow libcurl's timed events to take place).
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
+ long *milliseconds);
+
+#undef CINIT /* re-using the same name as in curl.h */
+
+#ifdef CURL_ISOCPP
+#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG CURLOPTTYPE_LONG
+#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
+#endif
+
+typedef enum {
+ /* This is the socket callback function pointer */
+ CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
+
+ /* This is the argument passed to the socket callback */
+ CINIT(SOCKETDATA, OBJECTPOINT, 2),
+
+ /* set to 1 to enable pipelining for this multi handle */
+ CINIT(PIPELINING, LONG, 3),
+
+ /* This is the timer callback function pointer */
+ CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
+
+ /* This is the argument passed to the timer callback */
+ CINIT(TIMERDATA, OBJECTPOINT, 5),
+
+ /* maximum number of entries in the connection cache */
+ CINIT(MAXCONNECTS, LONG, 6),
+
+ /* maximum number of (pipelining) connections to one host */
+ CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
+
+ /* maximum number of requests in a pipeline */
+ CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
+
+ /* a connection with a content-length longer than this
+ will not be considered for pipelining */
+ CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
+
+ /* a connection with a chunk length longer than this
+ will not be considered for pipelining */
+ CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
+
+ /* a list of site names(+port) that are blacklisted from
+ pipelining */
+ CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
+
+ /* a list of server types that are blacklisted from
+ pipelining */
+ CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
+
+ /* maximum number of open connections in total */
+ CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
+
+ CURLMOPT_LASTENTRY /* the last unused */
+} CURLMoption;
+
+
+/*
+ * Name: curl_multi_setopt()
+ *
+ * Desc: Sets options for the multi handle.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
+ CURLMoption option, ...);
+
+
+/*
+ * Name: curl_multi_assign()
+ *
+ * Desc: This function sets an association in the multi handle between the
+ * given socket and a private pointer of the application. This is
+ * (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t sockfd, void *sockp);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/include/curl/stamp-h2 b/external/libcurl_android/jni/libcurl/include/curl/stamp-h2
new file mode 100755
index 00000000..e4ea1b88
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/stamp-h2
@@ -0,0 +1 @@
+timestamp for include/curl/curlbuild.h
diff --git a/external/libcurl_android/jni/libcurl/include/curl/stdcheaders.h b/external/libcurl_android/jni/libcurl/include/curl/stdcheaders.h
new file mode 100755
index 00000000..ad82ef63
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/stdcheaders.h
@@ -0,0 +1,33 @@
+#ifndef __STDC_HEADERS_H
+#define __STDC_HEADERS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <sys/types.h>
+
+size_t fread (void *, size_t, size_t, FILE *);
+size_t fwrite (const void *, size_t, size_t, FILE *);
+
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, size_t);
+
+#endif /* __STDC_HEADERS_H */
diff --git a/external/libcurl_android/jni/libcurl/include/curl/typecheck-gcc.h b/external/libcurl_android/jni/libcurl/include/curl/typecheck-gcc.h
new file mode 100755
index 00000000..69d41a20
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/include/curl/typecheck-gcc.h
@@ -0,0 +1,610 @@
+#ifndef __CURL_TYPECHECK_GCC_H
+#define __CURL_TYPECHECK_GCC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* wraps curl_easy_setopt() with typechecking */
+
+/* To add a new kind of warning, add an
+ * if(_curl_is_sometype_option(_curl_opt))
+ * if(!_curl_is_sometype(value))
+ * _curl_easy_setopt_err_sometype();
+ * block and define _curl_is_sometype_option, _curl_is_sometype and
+ * _curl_easy_setopt_err_sometype below
+ *
+ * NOTE: We use two nested 'if' statements here instead of the && operator, in
+ * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
+ * when compiling with -Wlogical-op.
+ *
+ * To add an option that uses the same type as an existing option, you'll just
+ * need to extend the appropriate _curl_*_option macro
+ */
+#define curl_easy_setopt(handle, option, value) \
+__extension__ ({ \
+ __typeof__ (option) _curl_opt = option; \
+ if(__builtin_constant_p(_curl_opt)) { \
+ if(_curl_is_long_option(_curl_opt)) \
+ if(!_curl_is_long(value)) \
+ _curl_easy_setopt_err_long(); \
+ if(_curl_is_off_t_option(_curl_opt)) \
+ if(!_curl_is_off_t(value)) \
+ _curl_easy_setopt_err_curl_off_t(); \
+ if(_curl_is_string_option(_curl_opt)) \
+ if(!_curl_is_string(value)) \
+ _curl_easy_setopt_err_string(); \
+ if(_curl_is_write_cb_option(_curl_opt)) \
+ if(!_curl_is_write_cb(value)) \
+ _curl_easy_setopt_err_write_callback(); \
+ if((_curl_opt) == CURLOPT_READFUNCTION) \
+ if(!_curl_is_read_cb(value)) \
+ _curl_easy_setopt_err_read_cb(); \
+ if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
+ if(!_curl_is_ioctl_cb(value)) \
+ _curl_easy_setopt_err_ioctl_cb(); \
+ if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
+ if(!_curl_is_sockopt_cb(value)) \
+ _curl_easy_setopt_err_sockopt_cb(); \
+ if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
+ if(!_curl_is_opensocket_cb(value)) \
+ _curl_easy_setopt_err_opensocket_cb(); \
+ if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
+ if(!_curl_is_progress_cb(value)) \
+ _curl_easy_setopt_err_progress_cb(); \
+ if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
+ if(!_curl_is_debug_cb(value)) \
+ _curl_easy_setopt_err_debug_cb(); \
+ if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
+ if(!_curl_is_ssl_ctx_cb(value)) \
+ _curl_easy_setopt_err_ssl_ctx_cb(); \
+ if(_curl_is_conv_cb_option(_curl_opt)) \
+ if(!_curl_is_conv_cb(value)) \
+ _curl_easy_setopt_err_conv_cb(); \
+ if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
+ if(!_curl_is_seek_cb(value)) \
+ _curl_easy_setopt_err_seek_cb(); \
+ if(_curl_is_cb_data_option(_curl_opt)) \
+ if(!_curl_is_cb_data(value)) \
+ _curl_easy_setopt_err_cb_data(); \
+ if((_curl_opt) == CURLOPT_ERRORBUFFER) \
+ if(!_curl_is_error_buffer(value)) \
+ _curl_easy_setopt_err_error_buffer(); \
+ if((_curl_opt) == CURLOPT_STDERR) \
+ if(!_curl_is_FILE(value)) \
+ _curl_easy_setopt_err_FILE(); \
+ if(_curl_is_postfields_option(_curl_opt)) \
+ if(!_curl_is_postfields(value)) \
+ _curl_easy_setopt_err_postfields(); \
+ if((_curl_opt) == CURLOPT_HTTPPOST) \
+ if(!_curl_is_arr((value), struct curl_httppost)) \
+ _curl_easy_setopt_err_curl_httpost(); \
+ if(_curl_is_slist_option(_curl_opt)) \
+ if(!_curl_is_arr((value), struct curl_slist)) \
+ _curl_easy_setopt_err_curl_slist(); \
+ if((_curl_opt) == CURLOPT_SHARE) \
+ if(!_curl_is_ptr((value), CURLSH)) \
+ _curl_easy_setopt_err_CURLSH(); \
+ } \
+ curl_easy_setopt(handle, _curl_opt, value); \
+})
+
+/* wraps curl_easy_getinfo() with typechecking */
+/* FIXME: don't allow const pointers */
+#define curl_easy_getinfo(handle, info, arg) \
+__extension__ ({ \
+ __typeof__ (info) _curl_info = info; \
+ if(__builtin_constant_p(_curl_info)) { \
+ if(_curl_is_string_info(_curl_info)) \
+ if(!_curl_is_arr((arg), char *)) \
+ _curl_easy_getinfo_err_string(); \
+ if(_curl_is_long_info(_curl_info)) \
+ if(!_curl_is_arr((arg), long)) \
+ _curl_easy_getinfo_err_long(); \
+ if(_curl_is_double_info(_curl_info)) \
+ if(!_curl_is_arr((arg), double)) \
+ _curl_easy_getinfo_err_double(); \
+ if(_curl_is_slist_info(_curl_info)) \
+ if(!_curl_is_arr((arg), struct curl_slist *)) \
+ _curl_easy_getinfo_err_curl_slist(); \
+ } \
+ curl_easy_getinfo(handle, _curl_info, arg); \
+})
+
+/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
+ * for now just make sure that the functions are called with three
+ * arguments
+ */
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+
+
+/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
+ * functions */
+
+/* To define a new warning, use _CURL_WARNING(identifier, "message") */
+#define _CURL_WARNING(id, message) \
+ static void __attribute__((__warning__(message))) \
+ __attribute__((__unused__)) __attribute__((__noinline__)) \
+ id(void) { __asm__(""); }
+
+_CURL_WARNING(_curl_easy_setopt_err_long,
+ "curl_easy_setopt expects a long argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
+ "curl_easy_setopt expects a curl_off_t argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_string,
+ "curl_easy_setopt expects a "
+ "string (char* or char[]) argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_write_callback,
+ "curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_read_cb,
+ "curl_easy_setopt expects a curl_read_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
+ "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
+ "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
+ "curl_easy_setopt expects a "
+ "curl_opensocket_callback argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
+ "curl_easy_setopt expects a curl_progress_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
+ "curl_easy_setopt expects a curl_debug_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
+ "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
+ "curl_easy_setopt expects a curl_conv_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
+ "curl_easy_setopt expects a curl_seek_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_cb_data,
+ "curl_easy_setopt expects a "
+ "private data pointer as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
+ "curl_easy_setopt expects a "
+ "char buffer of CURL_ERROR_SIZE as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_FILE,
+ "curl_easy_setopt expects a FILE* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_postfields,
+ "curl_easy_setopt expects a void* or char* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
+ "curl_easy_setopt expects a struct curl_httppost* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
+ "curl_easy_setopt expects a struct curl_slist* argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
+ "curl_easy_setopt expects a CURLSH* argument for this option")
+
+_CURL_WARNING(_curl_easy_getinfo_err_string,
+ "curl_easy_getinfo expects a pointer to char * for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_long,
+ "curl_easy_getinfo expects a pointer to long for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_double,
+ "curl_easy_getinfo expects a pointer to double for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
+ "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
+
+/* groups of curl_easy_setops options that take the same type of argument */
+
+/* To add a new option to one of the groups, just add
+ * (option) == CURLOPT_SOMETHING
+ * to the or-expression. If the option takes a long or curl_off_t, you don't
+ * have to do anything
+ */
+
+/* evaluates to true if option takes a long argument */
+#define _curl_is_long_option(option) \
+ (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
+
+#define _curl_is_off_t_option(option) \
+ ((option) > CURLOPTTYPE_OFF_T)
+
+/* evaluates to true if option takes a char* argument */
+#define _curl_is_string_option(option) \
+ ((option) == CURLOPT_URL || \
+ (option) == CURLOPT_PROXY || \
+ (option) == CURLOPT_INTERFACE || \
+ (option) == CURLOPT_NETRC_FILE || \
+ (option) == CURLOPT_USERPWD || \
+ (option) == CURLOPT_USERNAME || \
+ (option) == CURLOPT_PASSWORD || \
+ (option) == CURLOPT_PROXYUSERPWD || \
+ (option) == CURLOPT_PROXYUSERNAME || \
+ (option) == CURLOPT_PROXYPASSWORD || \
+ (option) == CURLOPT_NOPROXY || \
+ (option) == CURLOPT_ACCEPT_ENCODING || \
+ (option) == CURLOPT_REFERER || \
+ (option) == CURLOPT_USERAGENT || \
+ (option) == CURLOPT_COOKIE || \
+ (option) == CURLOPT_COOKIEFILE || \
+ (option) == CURLOPT_COOKIEJAR || \
+ (option) == CURLOPT_COOKIELIST || \
+ (option) == CURLOPT_FTPPORT || \
+ (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_FTP_ACCOUNT || \
+ (option) == CURLOPT_RANGE || \
+ (option) == CURLOPT_CUSTOMREQUEST || \
+ (option) == CURLOPT_SSLCERT || \
+ (option) == CURLOPT_SSLCERTTYPE || \
+ (option) == CURLOPT_SSLKEY || \
+ (option) == CURLOPT_SSLKEYTYPE || \
+ (option) == CURLOPT_KEYPASSWD || \
+ (option) == CURLOPT_SSLENGINE || \
+ (option) == CURLOPT_CAINFO || \
+ (option) == CURLOPT_CAPATH || \
+ (option) == CURLOPT_RANDOM_FILE || \
+ (option) == CURLOPT_EGDSOCKET || \
+ (option) == CURLOPT_SSL_CIPHER_LIST || \
+ (option) == CURLOPT_KRBLEVEL || \
+ (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
+ (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
+ (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
+ (option) == CURLOPT_CRLFILE || \
+ (option) == CURLOPT_ISSUERCERT || \
+ (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
+ (option) == CURLOPT_SSH_KNOWNHOSTS || \
+ (option) == CURLOPT_MAIL_FROM || \
+ (option) == CURLOPT_RTSP_SESSION_ID || \
+ (option) == CURLOPT_RTSP_STREAM_URI || \
+ (option) == CURLOPT_RTSP_TRANSPORT || \
+ (option) == CURLOPT_XOAUTH2_BEARER || \
+ (option) == CURLOPT_DNS_SERVERS || \
+ (option) == CURLOPT_DNS_INTERFACE || \
+ (option) == CURLOPT_DNS_LOCAL_IP4 || \
+ (option) == CURLOPT_DNS_LOCAL_IP6 || \
+ (option) == CURLOPT_LOGIN_OPTIONS || \
+ 0)
+
+/* evaluates to true if option takes a curl_write_callback argument */
+#define _curl_is_write_cb_option(option) \
+ ((option) == CURLOPT_HEADERFUNCTION || \
+ (option) == CURLOPT_WRITEFUNCTION)
+
+/* evaluates to true if option takes a curl_conv_callback argument */
+#define _curl_is_conv_cb_option(option) \
+ ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
+
+/* evaluates to true if option takes a data argument to pass to a callback */
+#define _curl_is_cb_data_option(option) \
+ ((option) == CURLOPT_WRITEDATA || \
+ (option) == CURLOPT_READDATA || \
+ (option) == CURLOPT_IOCTLDATA || \
+ (option) == CURLOPT_SOCKOPTDATA || \
+ (option) == CURLOPT_OPENSOCKETDATA || \
+ (option) == CURLOPT_PROGRESSDATA || \
+ (option) == CURLOPT_HEADERDATA || \
+ (option) == CURLOPT_DEBUGDATA || \
+ (option) == CURLOPT_SSL_CTX_DATA || \
+ (option) == CURLOPT_SEEKDATA || \
+ (option) == CURLOPT_PRIVATE || \
+ (option) == CURLOPT_SSH_KEYDATA || \
+ (option) == CURLOPT_INTERLEAVEDATA || \
+ (option) == CURLOPT_CHUNK_DATA || \
+ (option) == CURLOPT_FNMATCH_DATA || \
+ 0)
+
+/* evaluates to true if option takes a POST data argument (void* or char*) */
+#define _curl_is_postfields_option(option) \
+ ((option) == CURLOPT_POSTFIELDS || \
+ (option) == CURLOPT_COPYPOSTFIELDS || \
+ 0)
+
+/* evaluates to true if option takes a struct curl_slist * argument */
+#define _curl_is_slist_option(option) \
+ ((option) == CURLOPT_HTTPHEADER || \
+ (option) == CURLOPT_HTTP200ALIASES || \
+ (option) == CURLOPT_QUOTE || \
+ (option) == CURLOPT_POSTQUOTE || \
+ (option) == CURLOPT_PREQUOTE || \
+ (option) == CURLOPT_TELNETOPTIONS || \
+ (option) == CURLOPT_MAIL_RCPT || \
+ 0)
+
+/* groups of curl_easy_getinfo infos that take the same type of argument */
+
+/* evaluates to true if info expects a pointer to char * argument */
+#define _curl_is_string_info(info) \
+ (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+
+/* evaluates to true if info expects a pointer to long argument */
+#define _curl_is_long_info(info) \
+ (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
+
+/* evaluates to true if info expects a pointer to double argument */
+#define _curl_is_double_info(info) \
+ (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
+
+/* true if info expects a pointer to struct curl_slist * argument */
+#define _curl_is_slist_info(info) \
+ (CURLINFO_SLIST < (info))
+
+
+/* typecheck helpers -- check whether given expression has requested type*/
+
+/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
+ * otherwise define a new macro. Search for __builtin_types_compatible_p
+ * in the GCC manual.
+ * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
+ * the actual expression passed to the curl_easy_setopt macro. This
+ * means that you can only apply the sizeof and __typeof__ operators, no
+ * == or whatsoever.
+ */
+
+/* XXX: should evaluate to true iff expr is a pointer */
+#define _curl_is_any_ptr(expr) \
+ (sizeof(expr) == sizeof(void*))
+
+/* evaluates to true if expr is NULL */
+/* XXX: must not evaluate expr, so this check is not accurate */
+#define _curl_is_NULL(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
+
+/* evaluates to true if expr is type*, const type* or NULL */
+#define _curl_is_ptr(expr, type) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), type *) || \
+ __builtin_types_compatible_p(__typeof__(expr), const type *))
+
+/* evaluates to true if expr is one of type[], type*, NULL or const type* */
+#define _curl_is_arr(expr, type) \
+ (_curl_is_ptr((expr), type) || \
+ __builtin_types_compatible_p(__typeof__(expr), type []))
+
+/* evaluates to true if expr is a string */
+#define _curl_is_string(expr) \
+ (_curl_is_arr((expr), char) || \
+ _curl_is_arr((expr), signed char) || \
+ _curl_is_arr((expr), unsigned char))
+
+/* evaluates to true if expr is a long (no matter the signedness)
+ * XXX: for now, int is also accepted (and therefore short and char, which
+ * are promoted to int when passed to a variadic function) */
+#define _curl_is_long(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), long) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed long) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
+ __builtin_types_compatible_p(__typeof__(expr), int) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed int) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
+ __builtin_types_compatible_p(__typeof__(expr), short) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed short) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
+ __builtin_types_compatible_p(__typeof__(expr), char) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed char) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned char))
+
+/* evaluates to true if expr is of type curl_off_t */
+#define _curl_is_off_t(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
+
+/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
+/* XXX: also check size of an char[] array? */
+#define _curl_is_error_buffer(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), char *) || \
+ __builtin_types_compatible_p(__typeof__(expr), char[]))
+
+/* evaluates to true if expr is of type (const) void* or (const) FILE* */
+#if 0
+#define _curl_is_cb_data(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_ptr((expr), FILE))
+#else /* be less strict */
+#define _curl_is_cb_data(expr) \
+ _curl_is_any_ptr(expr)
+#endif
+
+/* evaluates to true if expr is of type FILE* */
+#define _curl_is_FILE(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), FILE *))
+
+/* evaluates to true if expr can be passed as POST data (void* or char*) */
+#define _curl_is_postfields(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_arr((expr), char))
+
+/* FIXME: the whole callback checking is messy...
+ * The idea is to tolerate char vs. void and const vs. not const
+ * pointers in arguments at least
+ */
+/* helper: __builtin_types_compatible_p distinguishes between functions and
+ * function pointers, hide it */
+#define _curl_callback_compatible(func, type) \
+ (__builtin_types_compatible_p(__typeof__(func), type) || \
+ __builtin_types_compatible_p(__typeof__(func), type*))
+
+/* evaluates to true if expr is of type curl_read_callback or "similar" */
+#define _curl_is_read_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \
+ _curl_callback_compatible((expr), _curl_read_callback1) || \
+ _curl_callback_compatible((expr), _curl_read_callback2) || \
+ _curl_callback_compatible((expr), _curl_read_callback3) || \
+ _curl_callback_compatible((expr), _curl_read_callback4) || \
+ _curl_callback_compatible((expr), _curl_read_callback5) || \
+ _curl_callback_compatible((expr), _curl_read_callback6))
+typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
+typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
+typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
+typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
+typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
+typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
+
+/* evaluates to true if expr is of type curl_write_callback or "similar" */
+#define _curl_is_write_cb(expr) \
+ (_curl_is_read_cb(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \
+ _curl_callback_compatible((expr), _curl_write_callback1) || \
+ _curl_callback_compatible((expr), _curl_write_callback2) || \
+ _curl_callback_compatible((expr), _curl_write_callback3) || \
+ _curl_callback_compatible((expr), _curl_write_callback4) || \
+ _curl_callback_compatible((expr), _curl_write_callback5) || \
+ _curl_callback_compatible((expr), _curl_write_callback6))
+typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
+ const void*);
+typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
+typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
+ const void*);
+typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
+
+/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
+#define _curl_is_ioctl_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback1) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback2) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback3) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback4))
+typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
+typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
+typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
+typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
+
+/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
+#define _curl_is_sockopt_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback1) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback2))
+typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
+ curlsocktype);
+
+/* evaluates to true if expr is of type curl_opensocket_callback or
+ "similar" */
+#define _curl_is_opensocket_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
+ _curl_callback_compatible((expr), _curl_opensocket_callback1) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback2) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback3) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback4))
+typedef curl_socket_t (_curl_opensocket_callback1)
+ (void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback2)
+ (void *, curlsocktype, const struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback3)
+ (const void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (_curl_opensocket_callback4)
+ (const void *, curlsocktype, const struct curl_sockaddr *);
+
+/* evaluates to true if expr is of type curl_progress_callback or "similar" */
+#define _curl_is_progress_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \
+ _curl_callback_compatible((expr), _curl_progress_callback1) || \
+ _curl_callback_compatible((expr), _curl_progress_callback2))
+typedef int (_curl_progress_callback1)(void *,
+ double, double, double, double);
+typedef int (_curl_progress_callback2)(const void *,
+ double, double, double, double);
+
+/* evaluates to true if expr is of type curl_debug_callback or "similar" */
+#define _curl_is_debug_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \
+ _curl_callback_compatible((expr), _curl_debug_callback1) || \
+ _curl_callback_compatible((expr), _curl_debug_callback2) || \
+ _curl_callback_compatible((expr), _curl_debug_callback3) || \
+ _curl_callback_compatible((expr), _curl_debug_callback4) || \
+ _curl_callback_compatible((expr), _curl_debug_callback5) || \
+ _curl_callback_compatible((expr), _curl_debug_callback6) || \
+ _curl_callback_compatible((expr), _curl_debug_callback7) || \
+ _curl_callback_compatible((expr), _curl_debug_callback8))
+typedef int (_curl_debug_callback1) (CURL *,
+ curl_infotype, char *, size_t, void *);
+typedef int (_curl_debug_callback2) (CURL *,
+ curl_infotype, char *, size_t, const void *);
+typedef int (_curl_debug_callback3) (CURL *,
+ curl_infotype, const char *, size_t, void *);
+typedef int (_curl_debug_callback4) (CURL *,
+ curl_infotype, const char *, size_t, const void *);
+typedef int (_curl_debug_callback5) (CURL *,
+ curl_infotype, unsigned char *, size_t, void *);
+typedef int (_curl_debug_callback6) (CURL *,
+ curl_infotype, unsigned char *, size_t, const void *);
+typedef int (_curl_debug_callback7) (CURL *,
+ curl_infotype, const unsigned char *, size_t, void *);
+typedef int (_curl_debug_callback8) (CURL *,
+ curl_infotype, const unsigned char *, size_t, const void *);
+
+/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
+/* this is getting even messier... */
+#define _curl_is_ssl_ctx_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
+typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
+#ifdef HEADER_SSL_H
+/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
+ * this will of course break if we're included before OpenSSL headers...
+ */
+typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
+ const void *);
+#else
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
+#endif
+
+/* evaluates to true if expr is of type curl_conv_callback or "similar" */
+#define _curl_is_conv_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \
+ _curl_callback_compatible((expr), _curl_conv_callback1) || \
+ _curl_callback_compatible((expr), _curl_conv_callback2) || \
+ _curl_callback_compatible((expr), _curl_conv_callback3) || \
+ _curl_callback_compatible((expr), _curl_conv_callback4))
+typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
+typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
+typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
+typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
+
+/* evaluates to true if expr is of type curl_seek_callback or "similar" */
+#define _curl_is_seek_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \
+ _curl_callback_compatible((expr), _curl_seek_callback1) || \
+ _curl_callback_compatible((expr), _curl_seek_callback2))
+typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
+typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
+
+
+#endif /* __CURL_TYPECHECK_GCC_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/chkhostname-curl_gethostname.Po b/external/libcurl_android/jni/libcurl/lib/.deps/chkhostname-curl_gethostname.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/chkhostname-curl_gethostname.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/curl-nonblock.Po b/external/libcurl_android/jni/libcurl/lib/.deps/curl-nonblock.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/curl-nonblock.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/curl-rawstr.Po b/external/libcurl_android/jni/libcurl/lib/.deps/curl-rawstr.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/curl-rawstr.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/curl-strdup.Po b/external/libcurl_android/jni/libcurl/lib/.deps/curl-strdup.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/curl-strdup.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/curl-strtoofft.Po b/external/libcurl_android/jni/libcurl/lib/.deps/curl-strtoofft.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/curl-strtoofft.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/curl-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/curl-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/curl-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-base64.Po b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-base64.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-base64.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-memdebug.Po b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-memdebug.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-memdebug.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-mprintf.Po b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-mprintf.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-mprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-nonblock.Po b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-nonblock.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-nonblock.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-strequal.Po b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-strequal.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-strequal.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-strtoofft.Po b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-strtoofft.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-strtoofft.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-timeval.Po b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-timeval.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-timeval.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/fake_ntlm-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/getpart-base64.Po b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-base64.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-base64.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/getpart-memdebug.Po b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-memdebug.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-memdebug.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/getpart-mprintf.Po b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-mprintf.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-mprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/getpart-nonblock.Po b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-nonblock.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-nonblock.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/getpart-strequal.Po b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-strequal.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-strequal.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/getpart-strtoofft.Po b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-strtoofft.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-strtoofft.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/getpart-timeval.Po b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-timeval.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-timeval.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/getpart-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/getpart-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1501-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1501-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1501-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1502-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1502-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1502-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1503-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1503-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1503-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1504-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1504-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1504-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1505-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1505-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1505-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1506-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1506-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1506-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1507-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1507-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1507-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1508-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1508-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1508-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1509-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1509-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1509-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1510-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1510-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1510-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1511-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1511-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1511-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1512-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1512-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1512-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1513-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1513-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1513-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1514-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1514-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1514-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1515-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1515-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1515-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1525-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1525-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1525-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1526-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1526-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1526-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1527-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1527-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1527-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1528-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1528-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1528-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib1900-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib1900-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib1900-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib2033-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib2033-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib2033-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib502-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib502-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib502-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib503-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib503-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib503-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib504-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib504-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib504-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib507-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib507-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib507-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib518-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib518-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib518-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib525-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib525-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib525-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib526-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib526-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib526-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib527-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib527-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib527-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib529-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib529-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib529-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib530-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib530-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib530-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib532-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib532-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib532-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib533-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib533-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib533-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib536-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib536-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib536-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib537-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib537-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib537-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib540-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib540-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib540-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib552-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib552-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib552-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib555-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib555-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib555-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib560-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib560-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib560-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib564-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib564-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib564-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib571-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib571-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib571-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib573-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib573-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib573-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib575-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib575-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib575-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib582-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib582-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib582-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib591-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib591-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib591-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/lib597-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/lib597-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/lib597-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-amigaos.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-amigaos.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-amigaos.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-asyn-ares.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-asyn-ares.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-asyn-ares.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-asyn-thread.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-asyn-thread.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-asyn-thread.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-base64.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-base64.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-base64.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-bundles.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-bundles.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-bundles.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-conncache.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-conncache.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-conncache.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-connect.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-connect.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-connect.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-content_encoding.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-content_encoding.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-content_encoding.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-cookie.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-cookie.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-cookie.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_addrinfo.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_addrinfo.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_addrinfo.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_fnmatch.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_fnmatch.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_fnmatch.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_gethostname.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_gethostname.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_gethostname.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_gssapi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_gssapi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_gssapi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_memrchr.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_memrchr.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_memrchr.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_multibyte.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_multibyte.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_multibyte.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_core.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_core.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_core.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_msgs.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_msgs.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_msgs.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_wb.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_wb.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_ntlm_wb.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_rtmp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_rtmp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_rtmp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sasl.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sasl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sasl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sasl_sspi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sasl_sspi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sasl_sspi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sspi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sspi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_sspi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_threads.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_threads.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-curl_threads.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-dict.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-dict.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-dict.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-dotdot.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-dotdot.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-dotdot.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-easy.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-easy.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-easy.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-escape.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-escape.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-escape.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-file.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-file.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-file.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-fileinfo.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-fileinfo.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-fileinfo.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-formdata.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-formdata.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-formdata.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ftp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ftp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ftp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ftplistparser.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ftplistparser.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ftplistparser.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-getenv.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-getenv.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-getenv.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-getinfo.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-getinfo.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-getinfo.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-gopher.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-gopher.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-gopher.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hash.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hash.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hash.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hmac.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hmac.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hmac.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostasyn.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostasyn.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostasyn.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostcheck.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostcheck.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostcheck.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip4.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip4.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip4.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip6.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip6.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostip6.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostsyn.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostsyn.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-hostsyn.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http2.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http2.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http2.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_chunks.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_chunks.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_chunks.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_digest.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_digest.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_digest.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_negotiate.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_negotiate.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_negotiate.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_negotiate_sspi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_negotiate_sspi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_negotiate_sspi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_proxy.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_proxy.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-http_proxy.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-idn_win32.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-idn_win32.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-idn_win32.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-if2ip.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-if2ip.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-if2ip.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-imap.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-imap.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-imap.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-inet_ntop.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-inet_ntop.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-inet_ntop.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-inet_pton.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-inet_pton.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-inet_pton.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-krb5.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-krb5.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-krb5.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ldap.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ldap.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ldap.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-llist.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-llist.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-llist.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-md4.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-md4.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-md4.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-md5.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-md5.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-md5.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-memdebug.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-memdebug.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-memdebug.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-mprintf.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-mprintf.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-mprintf.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-multi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-multi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-multi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-netrc.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-netrc.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-netrc.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-non-ascii.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-non-ascii.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-non-ascii.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-nonblock.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-nonblock.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-nonblock.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-openldap.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-openldap.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-openldap.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-parsedate.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-parsedate.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-parsedate.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pingpong.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pingpong.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pingpong.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pipeline.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pipeline.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pipeline.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pop3.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pop3.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-pop3.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-progress.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-progress.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-progress.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-rawstr.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-rawstr.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-rawstr.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-rtsp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-rtsp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-rtsp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-security.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-security.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-security.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-select.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-select.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-select.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-sendf.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-sendf.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-sendf.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-share.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-share.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-share.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-slist.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-slist.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-slist.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-smtp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-smtp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-smtp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks_gssapi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks_gssapi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks_gssapi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks_sspi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks_sspi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-socks_sspi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-speedcheck.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-speedcheck.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-speedcheck.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-splay.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-splay.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-splay.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ssh.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ssh.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-ssh.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strdup.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strdup.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strdup.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strequal.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strequal.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strequal.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strerror.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strerror.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strerror.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strtok.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strtok.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strtok.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strtoofft.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strtoofft.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-strtoofft.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-telnet.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-telnet.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-telnet.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-tftp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-tftp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-tftp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-timeval.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-timeval.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-timeval.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-transfer.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-transfer.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-transfer.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-url.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-url.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-url.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-version.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-version.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-version.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-warnless.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-warnless.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-warnless.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-wildcard.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-wildcard.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-wildcard.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-x509asn1.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-x509asn1.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurl_la-x509asn1.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-nonblock.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-nonblock.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-nonblock.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-rawstr.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-rawstr.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-rawstr.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-strdup.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-strdup.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-strdup.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-strtoofft.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-strtoofft.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-strtoofft.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-warnless.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-warnless.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurltool_la-warnless.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-amigaos.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-amigaos.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-amigaos.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-asyn-ares.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-asyn-ares.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-asyn-ares.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-asyn-thread.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-asyn-thread.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-asyn-thread.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-base64.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-base64.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-base64.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-bundles.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-bundles.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-bundles.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-conncache.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-conncache.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-conncache.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-connect.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-connect.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-connect.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-content_encoding.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-content_encoding.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-content_encoding.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-cookie.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-cookie.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-cookie.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_addrinfo.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_addrinfo.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_addrinfo.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_fnmatch.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_fnmatch.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_fnmatch.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_gethostname.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_gethostname.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_gethostname.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_gssapi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_gssapi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_gssapi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_memrchr.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_memrchr.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_memrchr.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_multibyte.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_multibyte.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_multibyte.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_core.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_core.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_core.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_msgs.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_msgs.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_msgs.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_wb.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_wb.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_ntlm_wb.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_rtmp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_rtmp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_rtmp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sasl.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sasl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sasl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sasl_sspi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sasl_sspi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sasl_sspi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sspi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sspi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_sspi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_threads.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_threads.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-curl_threads.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-dict.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-dict.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-dict.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-dotdot.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-dotdot.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-dotdot.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-easy.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-easy.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-easy.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-escape.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-escape.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-escape.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-file.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-file.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-file.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-fileinfo.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-fileinfo.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-fileinfo.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-formdata.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-formdata.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-formdata.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ftp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ftp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ftp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ftplistparser.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ftplistparser.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ftplistparser.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-getenv.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-getenv.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-getenv.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-getinfo.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-getinfo.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-getinfo.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-gopher.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-gopher.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-gopher.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hash.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hash.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hash.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hmac.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hmac.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hmac.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostasyn.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostasyn.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostasyn.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostcheck.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostcheck.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostcheck.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip4.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip4.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip4.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip6.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip6.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostip6.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostsyn.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostsyn.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-hostsyn.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http2.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http2.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http2.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_chunks.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_chunks.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_chunks.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_digest.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_digest.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_digest.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_negotiate.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_negotiate.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_negotiate.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_negotiate_sspi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_negotiate_sspi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_negotiate_sspi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_proxy.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_proxy.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-http_proxy.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-idn_win32.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-idn_win32.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-idn_win32.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-if2ip.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-if2ip.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-if2ip.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-imap.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-imap.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-imap.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-inet_ntop.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-inet_ntop.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-inet_ntop.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-inet_pton.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-inet_pton.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-inet_pton.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-krb5.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-krb5.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-krb5.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ldap.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ldap.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ldap.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-llist.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-llist.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-llist.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-md4.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-md4.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-md4.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-md5.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-md5.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-md5.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-memdebug.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-memdebug.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-memdebug.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-mprintf.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-mprintf.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-mprintf.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-multi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-multi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-multi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-netrc.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-netrc.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-netrc.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-non-ascii.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-non-ascii.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-non-ascii.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-nonblock.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-nonblock.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-nonblock.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-openldap.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-openldap.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-openldap.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-parsedate.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-parsedate.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-parsedate.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pingpong.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pingpong.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pingpong.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pipeline.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pipeline.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pipeline.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pop3.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pop3.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-pop3.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-progress.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-progress.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-progress.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-rawstr.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-rawstr.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-rawstr.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-rtsp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-rtsp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-rtsp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-security.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-security.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-security.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-select.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-select.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-select.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-sendf.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-sendf.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-sendf.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-share.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-share.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-share.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-slist.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-slist.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-slist.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-smtp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-smtp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-smtp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks_gssapi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks_gssapi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks_gssapi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks_sspi.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks_sspi.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-socks_sspi.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-speedcheck.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-speedcheck.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-speedcheck.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-splay.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-splay.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-splay.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ssh.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ssh.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-ssh.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strdup.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strdup.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strdup.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strequal.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strequal.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strequal.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strerror.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strerror.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strerror.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strtok.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strtok.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strtok.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strtoofft.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strtoofft.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-strtoofft.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-telnet.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-telnet.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-telnet.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-tftp.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-tftp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-tftp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-timeval.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-timeval.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-timeval.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-transfer.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-transfer.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-transfer.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-url.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-url.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-url.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-version.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-version.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-version.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-warnless.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-warnless.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-warnless.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-wildcard.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-wildcard.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-wildcard.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-x509asn1.Plo b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-x509asn1.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libcurlu_la-x509asn1.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/libntlmconnect-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/libntlmconnect-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/libntlmconnect-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/resolve-base64.Po b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-base64.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-base64.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/resolve-memdebug.Po b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-memdebug.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-memdebug.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/resolve-mprintf.Po b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-mprintf.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-mprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/resolve-nonblock.Po b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-nonblock.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-nonblock.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/resolve-strequal.Po b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-strequal.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-strequal.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/resolve-strtoofft.Po b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-strtoofft.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-strtoofft.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/resolve-timeval.Po b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-timeval.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-timeval.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/resolve-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/resolve-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-base64.Po b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-base64.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-base64.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-memdebug.Po b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-memdebug.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-memdebug.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-mprintf.Po b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-mprintf.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-mprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-nonblock.Po b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-nonblock.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-nonblock.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-strequal.Po b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-strequal.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-strequal.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-strtoofft.Po b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-strtoofft.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-strtoofft.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-timeval.Po b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-timeval.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-timeval.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/rtspd-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-base64.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-base64.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-base64.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-inet_pton.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-inet_pton.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-inet_pton.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-memdebug.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-memdebug.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-memdebug.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-mprintf.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-mprintf.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-mprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-nonblock.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-nonblock.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-nonblock.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-strequal.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-strequal.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-strequal.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-strtoofft.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-strtoofft.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-strtoofft.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-timeval.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-timeval.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-timeval.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sockfilt-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-base64.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-base64.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-base64.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-inet_pton.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-inet_pton.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-inet_pton.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-memdebug.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-memdebug.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-memdebug.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-mprintf.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-mprintf.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-mprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-nonblock.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-nonblock.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-nonblock.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-strequal.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-strequal.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-strequal.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-strtoofft.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-strtoofft.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-strtoofft.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-timeval.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-timeval.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-timeval.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/sws-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/sws-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/sws-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-base64.Po b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-base64.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-base64.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-memdebug.Po b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-memdebug.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-memdebug.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-mprintf.Po b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-mprintf.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-mprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-nonblock.Po b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-nonblock.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-nonblock.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-strequal.Po b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-strequal.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-strequal.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-strtoofft.Po b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-strtoofft.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-strtoofft.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-timeval.Po b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-timeval.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-timeval.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-warnless.Po b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-warnless.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/.deps/tftpd-warnless.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/Makefile.inc b/external/libcurl_android/jni/libcurl/lib/Makefile.inc
new file mode 100755
index 00000000..462d72a5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/Makefile.inc
@@ -0,0 +1,71 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+
+LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
+ vtls/qssl.c vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c \
+ vtls/cyassl.c vtls/curl_schannel.c vtls/curl_darwinssl.c vtls/gskit.c
+
+LIB_VTLS_HFILES = vtls/qssl.h vtls/openssl.h vtls/vtls.h vtls/gtls.h \
+ vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h \
+ vtls/cyassl.h vtls/curl_schannel.h vtls/curl_darwinssl.h vtls/gskit.h
+
+LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
+ cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
+ ldap.c version.c getenv.c escape.c mprintf.c telnet.c netrc.c \
+ getinfo.c transfer.c strequal.c easy.c security.c curl_fnmatch.c \
+ fileinfo.c ftplistparser.c wildcard.c krb5.c memdebug.c http_chunks.c \
+ strtok.c connect.c llist.c hash.c multi.c content_encoding.c share.c \
+ http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \
+ strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \
+ inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \
+ ssh.c rawstr.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
+ curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \
+ pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \
+ openldap.c curl_gethostname.c gopher.c idn_win32.c \
+ http_negotiate_sspi.c http_proxy.c non-ascii.c asyn-ares.c \
+ asyn-thread.c curl_gssapi.c curl_ntlm.c curl_ntlm_wb.c \
+ curl_ntlm_core.c curl_ntlm_msgs.c curl_sasl.c curl_multibyte.c \
+ hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.c \
+ http2.c curl_sasl_sspi.c
+
+LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
+ formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
+ speedcheck.h urldata.h curl_ldap.h escape.h telnet.h getinfo.h \
+ strequal.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \
+ wildcard.h fileinfo.h ftplistparser.h strtok.h connect.h llist.h \
+ hash.h content_encoding.h share.h curl_md4.h curl_md5.h http_digest.h \
+ http_negotiate.h inet_pton.h amigaos.h strtoofft.h strerror.h \
+ inet_ntop.h curlx.h curl_memory.h curl_setup.h transfer.h select.h \
+ easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h \
+ socks.h ssh.h curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h \
+ slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \
+ rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \
+ curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \
+ curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \
+ curl_ntlm_msgs.h curl_sasl.h curl_multibyte.h hostcheck.h bundles.h \
+ conncache.h curl_setup_once.h multihandle.h setup-vms.h pipeline.h \
+ dotdot.h x509asn1.h http2.h sigpipe.h
+
+LIB_RCFILES = libcurl.rc
+
+CSOURCES = $(LIB_CFILES) $(LIB_VTLS_CFILES)
+HHEADERS = $(LIB_HFILES) $(LIB_VTLS_HFILES)
diff --git a/external/libcurl_android/jni/libcurl/lib/amigaos.c b/external/libcurl_android/jni/libcurl/lib/amigaos.c
new file mode 100755
index 00000000..34f95e9b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/amigaos.c
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(__AMIGA__) && !defined(__ixemul__)
+
+#include <amitcp/socketbasetags.h>
+
+#include "amigaos.h"
+
+struct Library *SocketBase = NULL;
+extern int errno, h_errno;
+
+#ifdef __libnix__
+#include <stabs.h>
+void __request(const char *msg);
+#else
+# define __request( msg ) Printf( msg "\n\a")
+#endif
+
+void Curl_amiga_cleanup()
+{
+ if(SocketBase) {
+ CloseLibrary(SocketBase);
+ SocketBase = NULL;
+ }
+}
+
+bool Curl_amiga_init()
+{
+ if(!SocketBase)
+ SocketBase = OpenLibrary("bsdsocket.library", 4);
+
+ if(!SocketBase) {
+ __request("No TCP/IP Stack running!");
+ return FALSE;
+ }
+
+ if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
+ SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL",
+ TAG_DONE)) {
+ __request("SocketBaseTags ERROR");
+ return FALSE;
+ }
+
+#ifndef __libnix__
+ atexit(Curl_amiga_cleanup);
+#endif
+
+ return TRUE;
+}
+
+#ifdef __libnix__
+ADD2EXIT(Curl_amiga_cleanup,-50);
+#endif
+
+#endif /* __AMIGA__ && ! __ixemul__ */
diff --git a/external/libcurl_android/jni/libcurl/lib/amigaos.h b/external/libcurl_android/jni/libcurl/lib/amigaos.h
new file mode 100755
index 00000000..76578be8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/amigaos.h
@@ -0,0 +1,39 @@
+#ifndef HEADER_CURL_AMIGAOS_H
+#define HEADER_CURL_AMIGAOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(__AMIGA__) && !defined(__ixemul__)
+
+bool Curl_amiga_init();
+void Curl_amiga_cleanup();
+
+#else
+
+#define Curl_amiga_init() 1
+#define Curl_amiga_cleanup() Curl_nop_stmt
+
+#endif
+
+#endif /* HEADER_CURL_AMIGAOS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/arpa_telnet.h b/external/libcurl_android/jni/libcurl/lib/arpa_telnet.h
new file mode 100755
index 00000000..098d9a92
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/arpa_telnet.h
@@ -0,0 +1,104 @@
+#ifndef HEADER_CURL_ARPA_TELNET_H
+#define HEADER_CURL_ARPA_TELNET_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_TELNET
+/*
+ * Telnet option defines. Add more here if in need.
+ */
+#define CURL_TELOPT_BINARY 0 /* binary 8bit data */
+#define CURL_TELOPT_ECHO 1 /* just echo! */
+#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */
+#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */
+#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */
+#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */
+#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */
+
+#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */
+#define CURL_NEW_ENV_VAR 0
+#define CURL_NEW_ENV_VALUE 1
+
+/*
+ * The telnet options represented as strings
+ */
+static const char * const telnetoptions[]=
+{
+ "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD",
+ "NAME", "STATUS", "TIMING MARK", "RCTE",
+ "NAOL", "NAOP", "NAOCRD", "NAOHTS",
+ "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD",
+ "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+ "DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION",
+ "TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING",
+ "TTYLOC", "3270 REGIME", "X3 PAD", "NAWS",
+ "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
+ "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
+};
+
+#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
+
+#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
+#define CURL_TELOPT(x) telnetoptions[x]
+
+#define CURL_NTELOPTS 40
+
+/*
+ * First some defines
+ */
+#define CURL_xEOF 236 /* End Of File */
+#define CURL_SE 240 /* Sub negotiation End */
+#define CURL_NOP 241 /* No OPeration */
+#define CURL_DM 242 /* Data Mark */
+#define CURL_GA 249 /* Go Ahead, reverse the line */
+#define CURL_SB 250 /* SuBnegotiation */
+#define CURL_WILL 251 /* Our side WILL use this option */
+#define CURL_WONT 252 /* Our side WON'T use this option */
+#define CURL_DO 253 /* DO use this option! */
+#define CURL_DONT 254 /* DON'T use this option! */
+#define CURL_IAC 255 /* Interpret As Command */
+
+/*
+ * Then those numbers represented as strings:
+ */
+static const char * const telnetcmds[]=
+{
+ "EOF", "SUSP", "ABORT", "EOR", "SE",
+ "NOP", "DMARK", "BRK", "IP", "AO",
+ "AYT", "EC", "EL", "GA", "SB",
+ "WILL", "WONT", "DO", "DONT", "IAC"
+};
+
+#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */
+#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */
+
+#define CURL_TELQUAL_IS 0
+#define CURL_TELQUAL_SEND 1
+#define CURL_TELQUAL_INFO 2
+#define CURL_TELQUAL_NAME 3
+
+#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
+ ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
+#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM]
+
+#endif /* CURL_DISABLE_TELNET */
+
+#endif /* HEADER_CURL_ARPA_TELNET_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/asyn-ares.c b/external/libcurl_android/jni/libcurl/lib/asyn-ares.c
new file mode 100755
index 00000000..01a9c9b5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/asyn-ares.c
@@ -0,0 +1,694 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+/***********************************************************************
+ * Only for ares-enabled builds
+ * And only for functions that fulfill the asynch resolver backend API
+ * as defined in asyn.h, nothing else belongs in this file!
+ **********************************************************************/
+
+#ifdef CURLRES_ARES
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "multiif.h"
+#include "inet_pton.h"
+#include "connect.h"
+#include "select.h"
+#include "progress.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+# define CARES_STATICLIB
+# endif
+# include <ares.h>
+# include <ares_version.h> /* really old c-ares didn't include this by
+ itself */
+
+#if ARES_VERSION >= 0x010500
+/* c-ares 1.5.0 or later, the callback proto is modified */
+#define HAVE_CARES_CALLBACK_TIMEOUTS 1
+#endif
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+struct ResolverResults {
+ int num_pending; /* number of ares_gethostbyname() requests */
+ Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
+ int last_status;
+};
+
+/*
+ * Curl_resolver_global_init() - the generic low-level asynchronous name
+ * resolve API. Called from curl_global_init() to initialize global resolver
+ * environment. Initializes ares library.
+ */
+int Curl_resolver_global_init(void)
+{
+#ifdef CARES_HAVE_ARES_LIBRARY_INIT
+ if(ares_library_init(ARES_LIB_INIT_ALL)) {
+ return CURLE_FAILED_INIT;
+ }
+#endif
+ return CURLE_OK;
+}
+
+/*
+ * Curl_resolver_global_cleanup()
+ *
+ * Called from curl_global_cleanup() to destroy global resolver environment.
+ * Deinitializes ares library.
+ */
+void Curl_resolver_global_cleanup(void)
+{
+#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
+ ares_library_cleanup();
+#endif
+}
+
+/*
+ * Curl_resolver_init()
+ *
+ * Called from curl_easy_init() -> Curl_open() to initialize resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Fills the passed pointer by the initialized ares_channel.
+ */
+CURLcode Curl_resolver_init(void **resolver)
+{
+ int status = ares_init((ares_channel*)resolver);
+ if(status != ARES_SUCCESS) {
+ if(status == ARES_ENOMEM)
+ return CURLE_OUT_OF_MEMORY;
+ else
+ return CURLE_FAILED_INIT;
+ }
+ return CURLE_OK;
+ /* make sure that all other returns from this function should destroy the
+ ares channel before returning error! */
+}
+
+/*
+ * Curl_resolver_cleanup()
+ *
+ * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Destroys the ares channel.
+ */
+void Curl_resolver_cleanup(void *resolver)
+{
+ ares_destroy((ares_channel)resolver);
+}
+
+/*
+ * Curl_resolver_duphandle()
+ *
+ * Called from curl_easy_duphandle() to duplicate resolver URL-state specific
+ * environment ('resolver' member of the UrlState structure). Duplicates the
+ * 'from' ares channel and passes the resulting channel to the 'to' pointer.
+ */
+int Curl_resolver_duphandle(void **to, void *from)
+{
+ /* Clone the ares channel for the new handle */
+ if(ARES_SUCCESS != ares_dup((ares_channel*)to,(ares_channel)from))
+ return CURLE_FAILED_INIT;
+ return CURLE_OK;
+}
+
+static void destroy_async_data (struct Curl_async *async);
+
+/*
+ * Cancel all possibly still on-going resolves for this connection.
+ */
+void Curl_resolver_cancel(struct connectdata *conn)
+{
+ if(conn && conn->data && conn->data->state.resolver)
+ ares_cancel((ares_channel)conn->data->state.resolver);
+ destroy_async_data(&conn->async);
+}
+
+/*
+ * destroy_async_data() cleans up async resolver data.
+ */
+static void destroy_async_data (struct Curl_async *async)
+{
+ if(async->hostname)
+ free(async->hostname);
+
+ if(async->os_specific) {
+ struct ResolverResults *res = (struct ResolverResults *)async->os_specific;
+ if(res) {
+ if(res->temp_ai) {
+ Curl_freeaddrinfo(res->temp_ai);
+ res->temp_ai = NULL;
+ }
+ free(res);
+ }
+ async->os_specific = NULL;
+ }
+
+ async->hostname = NULL;
+}
+
+/*
+ * Curl_resolver_getsock() is called when someone from the outside world
+ * (using curl_multi_fdset()) wants to get our fd_set setup and we're talking
+ * with ares. The caller must make sure that this function is only called when
+ * we have a working ares channel.
+ *
+ * Returns: sockets-in-use-bitmap
+ */
+
+int Curl_resolver_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+
+{
+ struct timeval maxtime;
+ struct timeval timebuf;
+ struct timeval *timeout;
+ long milli;
+ int max = ares_getsock((ares_channel)conn->data->state.resolver,
+ (ares_socket_t *)socks, numsocks);
+
+ maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
+ maxtime.tv_usec = 0;
+
+ timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime,
+ &timebuf);
+ milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
+ if(milli == 0)
+ milli += 10;
+ Curl_expire_latest(conn->data, milli);
+
+ return max;
+}
+
+/*
+ * waitperform()
+ *
+ * 1) Ask ares what sockets it currently plays with, then
+ * 2) wait for the timeout period to check for action on ares' sockets.
+ * 3) tell ares to act on all the sockets marked as "with action"
+ *
+ * return number of sockets it worked on
+ */
+
+static int waitperform(struct connectdata *conn, int timeout_ms)
+{
+ struct SessionHandle *data = conn->data;
+ int nfds;
+ int bitmask;
+ ares_socket_t socks[ARES_GETSOCK_MAXNUM];
+ struct pollfd pfd[ARES_GETSOCK_MAXNUM];
+ int i;
+ int num = 0;
+
+ bitmask = ares_getsock((ares_channel)data->state.resolver, socks,
+ ARES_GETSOCK_MAXNUM);
+
+ for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
+ pfd[i].events = 0;
+ pfd[i].revents = 0;
+ if(ARES_GETSOCK_READABLE(bitmask, i)) {
+ pfd[i].fd = socks[i];
+ pfd[i].events |= POLLRDNORM|POLLIN;
+ }
+ if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
+ pfd[i].fd = socks[i];
+ pfd[i].events |= POLLWRNORM|POLLOUT;
+ }
+ if(pfd[i].events != 0)
+ num++;
+ else
+ break;
+ }
+
+ if(num)
+ nfds = Curl_poll(pfd, num, timeout_ms);
+ else
+ nfds = 0;
+
+ if(!nfds)
+ /* Call ares_process() unconditonally here, even if we simply timed out
+ above, as otherwise the ares name resolve won't timeout! */
+ ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD,
+ ARES_SOCKET_BAD);
+ else {
+ /* move through the descriptors and ask for processing on them */
+ for(i=0; i < num; i++)
+ ares_process_fd((ares_channel)data->state.resolver,
+ pfd[i].revents & (POLLRDNORM|POLLIN)?
+ pfd[i].fd:ARES_SOCKET_BAD,
+ pfd[i].revents & (POLLWRNORM|POLLOUT)?
+ pfd[i].fd:ARES_SOCKET_BAD);
+ }
+ return nfds;
+}
+
+/*
+ * Curl_resolver_is_resolved() is called repeatedly to check if a previous
+ * name resolve request has completed. It should also make sure to time-out if
+ * the operation seems to take too long.
+ *
+ * Returns normal CURLcode errors.
+ */
+CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dns)
+{
+ struct SessionHandle *data = conn->data;
+ struct ResolverResults *res = (struct ResolverResults *)
+ conn->async.os_specific;
+ CURLcode rc = CURLE_OK;
+
+ *dns = NULL;
+
+ waitperform(conn, 0);
+
+ if(res && !res->num_pending) {
+ (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+ /* temp_ai ownership is moved to the connection, so we need not free-up
+ them */
+ res->temp_ai = NULL;
+ if(!conn->async.dns) {
+ failf(data, "Could not resolve: %s (%s)",
+ conn->async.hostname, ares_strerror(conn->async.status));
+ rc = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ CURLE_COULDNT_RESOLVE_HOST;
+ }
+ else
+ *dns = conn->async.dns;
+
+ destroy_async_data(&conn->async);
+ }
+
+ return rc;
+}
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
+ */
+CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+ struct Curl_dns_entry **entry)
+{
+ CURLcode rc=CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ long timeout;
+ struct timeval now = Curl_tvnow();
+ struct Curl_dns_entry *temp_entry;
+
+ timeout = Curl_timeleft(data, &now, TRUE);
+ if(!timeout)
+ timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
+
+ /* Wait for the name resolve query to complete. */
+ for(;;) {
+ struct timeval *tvp, tv, store;
+ long timediff;
+ int itimeout;
+ int timeout_ms;
+
+ itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
+
+ store.tv_sec = itimeout/1000;
+ store.tv_usec = (itimeout%1000)*1000;
+
+ tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv);
+
+ /* use the timeout period ares returned to us above if less than one
+ second is left, otherwise just use 1000ms to make sure the progress
+ callback gets called frequent enough */
+ if(!tvp->tv_sec)
+ timeout_ms = (int)(tvp->tv_usec/1000);
+ else
+ timeout_ms = 1000;
+
+ waitperform(conn, timeout_ms);
+ Curl_resolver_is_resolved(conn,&temp_entry);
+
+ if(conn->async.done)
+ break;
+
+ if(Curl_pgrsUpdate(conn)) {
+ rc = CURLE_ABORTED_BY_CALLBACK;
+ timeout = -1; /* trigger the cancel below */
+ }
+ else {
+ struct timeval now2 = Curl_tvnow();
+ timediff = Curl_tvdiff(now2, now); /* spent time */
+ timeout -= timediff?timediff:1; /* always deduct at least 1 */
+ now = now2; /* for next loop */
+ }
+ if(timeout < 0) {
+ /* our timeout, so we cancel the ares operation */
+ ares_cancel((ares_channel)data->state.resolver);
+ break;
+ }
+ }
+
+ /* Operation complete, if the lookup was successful we now have the entry
+ in the cache. */
+
+ if(entry)
+ *entry = conn->async.dns;
+
+ if(rc)
+ /* close the connection, since we can't return failure here without
+ cleaning up this connection properly.
+ TODO: remove this action from here, it is not a name resolver decision.
+ */
+ connclose(conn, "c-ares resolve failed");
+
+ return rc;
+}
+
+/* Connects results to the list */
+static void compound_results(struct ResolverResults *res,
+ Curl_addrinfo *ai)
+{
+ Curl_addrinfo *ai_tail;
+ if(!ai)
+ return;
+ ai_tail = ai;
+
+ while(ai_tail->ai_next)
+ ai_tail = ai_tail->ai_next;
+
+ /* Add the new results to the list of old results. */
+ ai_tail->ai_next = res->temp_ai;
+ res->temp_ai = ai;
+}
+
+/*
+ * ares_query_completed_cb() is the callback that ares will call when
+ * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
+ * when using ares, is completed either successfully or with failure.
+ */
+static void query_completed_cb(void *arg, /* (struct connectdata *) */
+ int status,
+#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
+ int timeouts,
+#endif
+ struct hostent *hostent)
+{
+ struct connectdata *conn = (struct connectdata *)arg;
+ struct ResolverResults *res;
+
+#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
+ (void)timeouts; /* ignored */
+#endif
+
+ if(ARES_EDESTRUCTION == status)
+ /* when this ares handle is getting destroyed, the 'arg' pointer may not
+ be valid so only defer it when we know the 'status' says its fine! */
+ return;
+
+ res = (struct ResolverResults *)conn->async.os_specific;
+ res->num_pending--;
+
+ if(CURL_ASYNC_SUCCESS == status) {
+ Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+ if(ai) {
+ compound_results(res, ai);
+ }
+ }
+ /* A successful result overwrites any previous error */
+ if(res->last_status != ARES_SUCCESS)
+ res->last_status = status;
+}
+
+/*
+ * Curl_resolver_getaddrinfo() - when using ares
+ *
+ * Returns name information about the given hostname and port number. If
+ * successful, the 'hostent' is returned and the forth argument will point to
+ * memory we need to free after use. That memory *MUST* be freed with
+ * Curl_freeaddrinfo(), nothing else.
+ */
+Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ char *bufp;
+ struct SessionHandle *data = conn->data;
+ struct in_addr in;
+ int family = PF_INET;
+#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+ struct in6_addr in6;
+#endif /* CURLRES_IPV6 */
+
+ *waitp = 0; /* default to synchronous response */
+
+ /* First check if this is an IPv4 address string */
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+ }
+
+#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+ /* Otherwise, check if this is an IPv6 address string */
+ if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0)
+ /* This must be an IPv6 address literal. */
+ return Curl_ip2addr(AF_INET6, &in6, hostname, port);
+
+ switch(conn->ip_version) {
+ default:
+#if ARES_VERSION >= 0x010601
+ family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
+ c-ares versions this just falls through and defaults
+ to PF_INET */
+ break;
+#endif
+ case CURL_IPRESOLVE_V4:
+ family = PF_INET;
+ break;
+ case CURL_IPRESOLVE_V6:
+ family = PF_INET6;
+ break;
+ }
+#endif /* CURLRES_IPV6 */
+
+ bufp = strdup(hostname);
+ if(bufp) {
+ struct ResolverResults *res = NULL;
+ Curl_safefree(conn->async.hostname);
+ conn->async.hostname = bufp;
+ conn->async.port = port;
+ conn->async.done = FALSE; /* not done */
+ conn->async.status = 0; /* clear */
+ conn->async.dns = NULL; /* clear */
+ res = calloc(sizeof(struct ResolverResults),1);
+ if(!res) {
+ Curl_safefree(conn->async.hostname);
+ conn->async.hostname = NULL;
+ return NULL;
+ }
+ conn->async.os_specific = res;
+
+ /* initial status - failed */
+ res->last_status = ARES_ENOTFOUND;
+#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+ if(family == PF_UNSPEC) {
+ if(Curl_ipv6works()) {
+ res->num_pending = 2;
+
+ /* areschannel is already setup in the Curl_open() function */
+ ares_gethostbyname((ares_channel)data->state.resolver, hostname,
+ PF_INET, query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.resolver, hostname,
+ PF_INET6, query_completed_cb, conn);
+ }
+ else {
+ res->num_pending = 1;
+
+ /* areschannel is already setup in the Curl_open() function */
+ ares_gethostbyname((ares_channel)data->state.resolver, hostname,
+ PF_INET, query_completed_cb, conn);
+ }
+ }
+ else
+#endif /* CURLRES_IPV6 */
+ {
+ res->num_pending = 1;
+
+ /* areschannel is already setup in the Curl_open() function */
+ ares_gethostbyname((ares_channel)data->state.resolver, hostname, family,
+ query_completed_cb, conn);
+ }
+
+ *waitp = 1; /* expect asynchronous response */
+ }
+ return NULL; /* no struct yet */
+}
+
+CURLcode Curl_set_dns_servers(struct SessionHandle *data,
+ char *servers)
+{
+ CURLcode result = CURLE_NOT_BUILT_IN;
+ int ares_result;
+
+ /* If server is NULL or empty, this would purge all DNS servers
+ * from ares library, which will cause any and all queries to fail.
+ * So, just return OK if none are configured and don't actually make
+ * any changes to c-ares. This lets c-ares use it's defaults, which
+ * it gets from the OS (for instance from /etc/resolv.conf on Linux).
+ */
+ if(!(servers && servers[0]))
+ return CURLE_OK;
+
+#if (ARES_VERSION >= 0x010704)
+ ares_result = ares_set_servers_csv(data->state.resolver, servers);
+ switch(ares_result) {
+ case ARES_SUCCESS:
+ result = CURLE_OK;
+ break;
+ case ARES_ENOMEM:
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ case ARES_ENOTINITIALIZED:
+ case ARES_ENODATA:
+ case ARES_EBADSTR:
+ default:
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ break;
+ }
+#else /* too old c-ares version! */
+ (void)data;
+ (void)(ares_result);
+#endif
+ return result;
+}
+
+CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+ const char *interf)
+{
+#if (ARES_VERSION >= 0x010704)
+ if(!interf)
+ interf = "";
+
+ ares_set_local_dev((ares_channel)data->state.resolver, interf);
+
+ return CURLE_OK;
+#else /* c-ares version too old! */
+ (void)data;
+ (void)interf;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+ const char *local_ip4)
+{
+#if (ARES_VERSION >= 0x010704)
+ struct in_addr a4;
+
+ if((!local_ip4) || (local_ip4[0] == 0)) {
+ a4.s_addr = 0; /* disabled: do not bind to a specific address */
+ }
+ else {
+ if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+
+ ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr));
+
+ return CURLE_OK;
+#else /* c-ares version too old! */
+ (void)data;
+ (void)local_ip4;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+ const char *local_ip6)
+{
+#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6)
+ unsigned char a6[INET6_ADDRSTRLEN];
+
+ if((!local_ip6) || (local_ip6[0] == 0)) {
+ /* disabled: do not bind to a specific address */
+ memset(a6, 0, sizeof(a6));
+ }
+ else {
+ if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+
+ ares_set_local_ip6((ares_channel)data->state.resolver, a6);
+
+ return CURLE_OK;
+#else /* c-ares version too old! */
+ (void)data;
+ (void)local_ip6;
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+#endif /* CURLRES_ARES */
diff --git a/external/libcurl_android/jni/libcurl/lib/asyn-thread.c b/external/libcurl_android/jni/libcurl/lib/asyn-thread.c
new file mode 100755
index 00000000..e4ad32bb
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/asyn-thread.c
@@ -0,0 +1,701 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if defined(USE_THREADS_POSIX)
+# ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+# endif
+#elif defined(USE_THREADS_WIN32)
+# ifdef HAVE_PROCESS_H
+# include <process.h>
+# endif
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#ifdef HAVE_GETADDRINFO
+# define RESOLVER_ENOMEM EAI_MEMORY
+#else
+# define RESOLVER_ENOMEM ENOMEM
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "multiif.h"
+#include "inet_pton.h"
+#include "inet_ntop.h"
+#include "curl_threads.h"
+#include "connect.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for threaded name resolves builds
+ **********************************************************************/
+#ifdef CURLRES_THREADED
+
+/*
+ * Curl_resolver_global_init()
+ * Called from curl_global_init() to initialize global resolver environment.
+ * Does nothing here.
+ */
+int Curl_resolver_global_init(void)
+{
+ return CURLE_OK;
+}
+
+/*
+ * Curl_resolver_global_cleanup()
+ * Called from curl_global_cleanup() to destroy global resolver environment.
+ * Does nothing here.
+ */
+void Curl_resolver_global_cleanup(void)
+{
+}
+
+/*
+ * Curl_resolver_init()
+ * Called from curl_easy_init() -> Curl_open() to initialize resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Does nothing here.
+ */
+CURLcode Curl_resolver_init(void **resolver)
+{
+ (void)resolver;
+ return CURLE_OK;
+}
+
+/*
+ * Curl_resolver_cleanup()
+ * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Does nothing here.
+ */
+void Curl_resolver_cleanup(void *resolver)
+{
+ (void)resolver;
+}
+
+/*
+ * Curl_resolver_duphandle()
+ * Called from curl_easy_duphandle() to duplicate resolver URL state-specific
+ * environment ('resolver' member of the UrlState structure). Does nothing
+ * here.
+ */
+int Curl_resolver_duphandle(void **to, void *from)
+{
+ (void)to;
+ (void)from;
+ return CURLE_OK;
+}
+
+static void destroy_async_data(struct Curl_async *);
+
+/*
+ * Cancel all possibly still on-going resolves for this connection.
+ */
+void Curl_resolver_cancel(struct connectdata *conn)
+{
+ destroy_async_data(&conn->async);
+}
+
+/* This function is used to init a threaded resolve */
+static bool init_resolve_thread(struct connectdata *conn,
+ const char *hostname, int port,
+ const struct addrinfo *hints);
+
+
+/* Data for synchronization between resolver thread and its parent */
+struct thread_sync_data {
+ curl_mutex_t * mtx;
+ int done;
+
+ char * hostname; /* hostname to resolve, Curl_async.hostname
+ duplicate */
+ int port;
+ int sock_error;
+ Curl_addrinfo *res;
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints;
+#endif
+ struct thread_data *td; /* for thread-self cleanup */
+};
+
+struct thread_data {
+ curl_thread_t thread_hnd;
+ unsigned int poll_interval;
+ long interval_end;
+ struct thread_sync_data tsd;
+};
+
+static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
+{
+ return &(((struct thread_data *)conn->async.os_specific)->tsd);
+}
+
+#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd);
+
+/* Destroy resolver thread synchronization data */
+static
+void destroy_thread_sync_data(struct thread_sync_data * tsd)
+{
+ if(tsd->mtx) {
+ Curl_mutex_destroy(tsd->mtx);
+ free(tsd->mtx);
+ }
+
+ if(tsd->hostname)
+ free(tsd->hostname);
+
+ if(tsd->res)
+ Curl_freeaddrinfo(tsd->res);
+
+ memset(tsd,0,sizeof(*tsd));
+}
+
+/* Initialize resolver thread synchronization data */
+static
+int init_thread_sync_data(struct thread_data * td,
+ const char * hostname,
+ int port,
+ const struct addrinfo *hints)
+{
+ struct thread_sync_data *tsd = &td->tsd;
+
+ memset(tsd, 0, sizeof(*tsd));
+
+ tsd->td = td;
+ tsd->port = port;
+#ifdef HAVE_GETADDRINFO
+ DEBUGASSERT(hints);
+ tsd->hints = *hints;
+#else
+ (void) hints;
+#endif
+
+ tsd->mtx = malloc(sizeof(curl_mutex_t));
+ if(tsd->mtx == NULL)
+ goto err_exit;
+
+ Curl_mutex_init(tsd->mtx);
+
+ tsd->sock_error = CURL_ASYNC_SUCCESS;
+
+ /* Copying hostname string because original can be destroyed by parent
+ * thread during gethostbyname execution.
+ */
+ tsd->hostname = strdup(hostname);
+ if(!tsd->hostname)
+ goto err_exit;
+
+ return 1;
+
+ err_exit:
+ /* Memory allocation failed */
+ destroy_thread_sync_data(tsd);
+ return 0;
+}
+
+static int getaddrinfo_complete(struct connectdata *conn)
+{
+ struct thread_sync_data *tsd = conn_thread_sync_data(conn);
+ int rc;
+
+ rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res);
+ /* The tsd->res structure has been copied to async.dns and perhaps the DNS
+ cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
+ */
+ tsd->res = NULL;
+
+ return rc;
+}
+
+
+#ifdef HAVE_GETADDRINFO
+
+/*
+ * getaddrinfo_thread() resolves a name and then exits.
+ *
+ * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
+ * and wait on it.
+ */
+static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
+{
+ struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
+ struct thread_data *td = tsd->td;
+ char service[12];
+ int rc;
+
+ snprintf(service, sizeof(service), "%d", tsd->port);
+
+ rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
+
+ if(rc != 0) {
+ tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
+ if(tsd->sock_error == 0)
+ tsd->sock_error = RESOLVER_ENOMEM;
+ }
+
+ Curl_mutex_acquire(tsd->mtx);
+ if(tsd->done) {
+ /* too late, gotta clean up the mess */
+ Curl_mutex_release(tsd->mtx);
+ destroy_thread_sync_data(tsd);
+ free(td);
+ }
+ else {
+ tsd->done = 1;
+ Curl_mutex_release(tsd->mtx);
+ }
+
+ return 0;
+}
+
+#else /* HAVE_GETADDRINFO */
+
+/*
+ * gethostbyname_thread() resolves a name and then exits.
+ */
+static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
+{
+ struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
+ struct thread_data *td = tsd->td;
+
+ tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
+
+ if(!tsd->res) {
+ tsd->sock_error = SOCKERRNO;
+ if(tsd->sock_error == 0)
+ tsd->sock_error = RESOLVER_ENOMEM;
+ }
+
+ Curl_mutex_acquire(tsd->mtx);
+ if(tsd->done) {
+ /* too late, gotta clean up the mess */
+ Curl_mutex_release(tsd->mtx);
+ destroy_thread_sync_data(tsd);
+ free(td);
+ }
+ else {
+ tsd->done = 1;
+ Curl_mutex_release(tsd->mtx);
+ }
+
+ return 0;
+}
+
+#endif /* HAVE_GETADDRINFO */
+
+/*
+ * destroy_async_data() cleans up async resolver data and thread handle.
+ */
+static void destroy_async_data (struct Curl_async *async)
+{
+ if(async->os_specific) {
+ struct thread_data *td = (struct thread_data*) async->os_specific;
+ int done;
+
+ /*
+ * if the thread is still blocking in the resolve syscall, detach it and
+ * let the thread do the cleanup...
+ */
+ Curl_mutex_acquire(td->tsd.mtx);
+ done = td->tsd.done;
+ td->tsd.done = 1;
+ Curl_mutex_release(td->tsd.mtx);
+
+ if(!done) {
+ Curl_thread_destroy(td->thread_hnd);
+ }
+ else {
+ if(td->thread_hnd != curl_thread_t_null)
+ Curl_thread_join(&td->thread_hnd);
+
+ destroy_thread_sync_data(&td->tsd);
+
+ free(async->os_specific);
+ }
+ }
+ async->os_specific = NULL;
+
+ if(async->hostname)
+ free(async->hostname);
+
+ async->hostname = NULL;
+}
+
+/*
+ * init_resolve_thread() starts a new thread that performs the actual
+ * resolve. This function returns before the resolve is done.
+ *
+ * Returns FALSE in case of failure, otherwise TRUE.
+ */
+static bool init_resolve_thread (struct connectdata *conn,
+ const char *hostname, int port,
+ const struct addrinfo *hints)
+{
+ struct thread_data *td = calloc(1, sizeof(struct thread_data));
+ int err = RESOLVER_ENOMEM;
+
+ conn->async.os_specific = (void*) td;
+ if(!td)
+ goto err_exit;
+
+ conn->async.port = port;
+ conn->async.done = FALSE;
+ conn->async.status = 0;
+ conn->async.dns = NULL;
+ td->thread_hnd = curl_thread_t_null;
+
+ if(!init_thread_sync_data(td, hostname, port, hints))
+ goto err_exit;
+
+ Curl_safefree(conn->async.hostname);
+ conn->async.hostname = strdup(hostname);
+ if(!conn->async.hostname)
+ goto err_exit;
+
+#ifdef HAVE_GETADDRINFO
+ td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
+#else
+ td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd);
+#endif
+
+ if(!td->thread_hnd) {
+#ifndef _WIN32_WCE
+ err = errno;
+#endif
+ goto err_exit;
+ }
+
+ return TRUE;
+
+ err_exit:
+ destroy_async_data(&conn->async);
+
+ SET_ERRNO(err);
+
+ return FALSE;
+}
+
+/*
+ * resolver_error() calls failf() with the appropriate message after a resolve
+ * error
+ */
+
+static CURLcode resolver_error(struct connectdata *conn)
+{
+ const char *host_or_proxy;
+ CURLcode rc;
+ if(conn->bits.httpproxy) {
+ host_or_proxy = "proxy";
+ rc = CURLE_COULDNT_RESOLVE_PROXY;
+ }
+ else {
+ host_or_proxy = "host";
+ rc = CURLE_COULDNT_RESOLVE_HOST;
+ }
+
+ failf(conn->data, "Could not resolve %s: %s", host_or_proxy,
+ conn->async.hostname);
+ return rc;
+}
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * This is the version for resolves-in-a-thread.
+ */
+CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+ struct Curl_dns_entry **entry)
+{
+ struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ CURLcode rc = CURLE_OK;
+
+ DEBUGASSERT(conn && td);
+
+ /* wait for the thread to resolve the name */
+ if(Curl_thread_join(&td->thread_hnd))
+ rc = getaddrinfo_complete(conn);
+ else
+ DEBUGASSERT(0);
+
+ conn->async.done = TRUE;
+
+ if(entry)
+ *entry = conn->async.dns;
+
+ if(!conn->async.dns)
+ /* a name was not resolved, report error */
+ rc = resolver_error(conn);
+
+ destroy_async_data(&conn->async);
+
+ if(!conn->async.dns)
+ connclose(conn, "asynch resolve failed");
+
+ return (rc);
+}
+
+/*
+ * Curl_resolver_is_resolved() is called repeatedly to check if a previous
+ * name resolve request has completed. It should also make sure to time-out if
+ * the operation seems to take too long.
+ */
+CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **entry)
+{
+ struct SessionHandle *data = conn->data;
+ struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ int done = 0;
+
+ *entry = NULL;
+
+ if(!td) {
+ DEBUGASSERT(td);
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+
+ Curl_mutex_acquire(td->tsd.mtx);
+ done = td->tsd.done;
+ Curl_mutex_release(td->tsd.mtx);
+
+ if(done) {
+ getaddrinfo_complete(conn);
+
+ if(!conn->async.dns) {
+ CURLcode rc = resolver_error(conn);
+ destroy_async_data(&conn->async);
+ return rc;
+ }
+ destroy_async_data(&conn->async);
+ *entry = conn->async.dns;
+ }
+ else {
+ /* poll for name lookup done with exponential backoff up to 250ms */
+ long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
+ if(elapsed < 0)
+ elapsed = 0;
+
+ if(td->poll_interval == 0)
+ /* Start at 1ms poll interval */
+ td->poll_interval = 1;
+ else if(elapsed >= td->interval_end)
+ /* Back-off exponentially if last interval expired */
+ td->poll_interval *= 2;
+
+ if(td->poll_interval > 250)
+ td->poll_interval = 250;
+
+ td->interval_end = elapsed + td->poll_interval;
+ Curl_expire_latest(conn->data, td->poll_interval);
+ }
+
+ return CURLE_OK;
+}
+
+int Curl_resolver_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ (void)conn;
+ (void)socks;
+ (void)numsocks;
+ return 0;
+}
+
+#ifndef HAVE_GETADDRINFO
+/*
+ * Curl_getaddrinfo() - for platforms without getaddrinfo
+ */
+Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ struct in_addr in;
+
+ *waitp = 0; /* default to synchronous response */
+
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+
+ /* fire up a new resolver thread! */
+ if(init_resolve_thread(conn, hostname, port, NULL)) {
+ *waitp = 1; /* expect asynchronous response */
+ return NULL;
+ }
+
+ /* fall-back to blocking version */
+ return Curl_ipv4_resolve_r(hostname, port);
+}
+
+#else /* !HAVE_GETADDRINFO */
+
+/*
+ * Curl_resolver_getaddrinfo() - for getaddrinfo
+ */
+Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ struct addrinfo hints;
+ struct in_addr in;
+ Curl_addrinfo *res;
+ int error;
+ char sbuf[12];
+ int pf = PF_INET;
+#ifdef CURLRES_IPV6
+ struct in6_addr in6;
+#endif /* CURLRES_IPV6 */
+
+ *waitp = 0; /* default to synchronous response */
+
+ /* First check if this is an IPv4 address string */
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+
+#ifdef CURLRES_IPV6
+ /* check if this is an IPv6 address string */
+ if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0)
+ /* This is an IPv6 address literal */
+ return Curl_ip2addr(AF_INET6, &in6, hostname, port);
+
+ /*
+ * Check if a limited name resolve has been requested.
+ */
+ switch(conn->ip_version) {
+ case CURL_IPRESOLVE_V4:
+ pf = PF_INET;
+ break;
+ case CURL_IPRESOLVE_V6:
+ pf = PF_INET6;
+ break;
+ default:
+ pf = PF_UNSPEC;
+ break;
+ }
+
+ if((pf != PF_INET) && !Curl_ipv6works())
+ /* the stack seems to be a non-ipv6 one */
+ pf = PF_INET;
+
+#endif /* CURLRES_IPV6 */
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pf;
+ hints.ai_socktype = conn->socktype;
+
+ snprintf(sbuf, sizeof(sbuf), "%d", port);
+
+ /* fire up a new resolver thread! */
+ if(init_resolve_thread(conn, hostname, port, &hints)) {
+ *waitp = 1; /* expect asynchronous response */
+ return NULL;
+ }
+
+ /* fall-back to blocking version */
+ infof(conn->data, "init_resolve_thread() failed for %s; %s\n",
+ hostname, Curl_strerror(conn, ERRNO));
+
+ error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
+ if(error) {
+ infof(conn->data, "getaddrinfo() failed for %s:%d; %s\n",
+ hostname, port, Curl_strerror(conn, SOCKERRNO));
+ return NULL;
+ }
+ return res;
+}
+
+#endif /* !HAVE_GETADDRINFO */
+
+CURLcode Curl_set_dns_servers(struct SessionHandle *data,
+ char *servers)
+{
+ (void)data;
+ (void)servers;
+ return CURLE_NOT_BUILT_IN;
+
+}
+
+CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+ const char *interf)
+{
+ (void)data;
+ (void)interf;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+ const char *local_ip4)
+{
+ (void)data;
+ (void)local_ip4;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+ const char *local_ip6)
+{
+ (void)data;
+ (void)local_ip6;
+ return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* CURLRES_THREADED */
diff --git a/external/libcurl_android/jni/libcurl/lib/asyn.h b/external/libcurl_android/jni/libcurl/lib/asyn.h
new file mode 100755
index 00000000..1b681ea1
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/asyn.h
@@ -0,0 +1,168 @@
+#ifndef HEADER_CURL_ASYN_H
+#define HEADER_CURL_ASYN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "curl_addrinfo.h"
+
+struct addrinfo;
+struct hostent;
+struct SessionHandle;
+struct connectdata;
+struct Curl_dns_entry;
+
+/*
+ * This header defines all functions in the internal asynch resolver interface.
+ * All asynch resolvers need to provide these functions.
+ * asyn-ares.c and asyn-thread.c are the current implementations of asynch
+ * resolver backends.
+ */
+
+/*
+ * Curl_resolver_global_init()
+ *
+ * Called from curl_global_init() to initialize global resolver environment.
+ * Returning anything else than CURLE_OK fails curl_global_init().
+ */
+int Curl_resolver_global_init(void);
+
+/*
+ * Curl_resolver_global_cleanup()
+ * Called from curl_global_cleanup() to destroy global resolver environment.
+ */
+void Curl_resolver_global_cleanup(void);
+
+/*
+ * Curl_resolver_init()
+ * Called from curl_easy_init() -> Curl_open() to initialize resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Should fill the passed pointer by the initialized handler.
+ * Returning anything else than CURLE_OK fails curl_easy_init() with the
+ * correspondent code.
+ */
+CURLcode Curl_resolver_init(void **resolver);
+
+/*
+ * Curl_resolver_cleanup()
+ * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
+ * URL-state specific environment ('resolver' member of the UrlState
+ * structure). Should destroy the handler and free all resources connected to
+ * it.
+ */
+void Curl_resolver_cleanup(void *resolver);
+
+/*
+ * Curl_resolver_duphandle()
+ * Called from curl_easy_duphandle() to duplicate resolver URL-state specific
+ * environment ('resolver' member of the UrlState structure). Should
+ * duplicate the 'from' handle and pass the resulting handle to the 'to'
+ * pointer. Returning anything else than CURLE_OK causes failed
+ * curl_easy_duphandle() call.
+ */
+int Curl_resolver_duphandle(void **to, void *from);
+
+/*
+ * Curl_resolver_cancel().
+ *
+ * It is called from inside other functions to cancel currently performing
+ * resolver request. Should also free any temporary resources allocated to
+ * perform a request.
+ */
+void Curl_resolver_cancel(struct connectdata *conn);
+
+/* Curl_resolver_getsock()
+ *
+ * This function is called from the multi_getsock() function. 'sock' is a
+ * pointer to an array to hold the file descriptors, with 'numsock' being the
+ * size of that array (in number of entries). This function is supposed to
+ * return bitmask indicating what file descriptors (referring to array indexes
+ * in the 'sock' array) to wait for, read/write.
+ */
+int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock,
+ int numsocks);
+
+/*
+ * Curl_resolver_is_resolved()
+ *
+ * Called repeatedly to check if a previous name resolve request has
+ * completed. It should also make sure to time-out if the operation seems to
+ * take too long.
+ *
+ * Returns normal CURLcode errors.
+ */
+CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dns);
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
+
+ */
+CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+ struct Curl_dns_entry **dnsentry);
+
+/*
+ * Curl_resolver_getaddrinfo() - when using this resolver
+ *
+ * Returns name information about the given hostname and port number. If
+ * successful, the 'hostent' is returned and the forth argument will point to
+ * memory we need to free after use. That memory *MUST* be freed with
+ * Curl_freeaddrinfo(), nothing else.
+ *
+ * Each resolver backend must of course make sure to return data in the
+ * correct format to comply with this.
+ */
+Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
+
+#ifndef CURLRES_ASYNCH
+/* convert these functions if an asynch resolver isn't used */
+#define Curl_resolver_cancel(x) Curl_nop_stmt
+#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
+#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
+#define Curl_resolver_getsock(x,y,z) 0
+#define Curl_resolver_duphandle(x,y) CURLE_OK
+#define Curl_resolver_init(x) CURLE_OK
+#define Curl_resolver_global_init() CURLE_OK
+#define Curl_resolver_global_cleanup() Curl_nop_stmt
+#define Curl_resolver_cleanup(x) Curl_nop_stmt
+#endif
+
+#ifdef CURLRES_ASYNCH
+#define Curl_resolver_asynch() 1
+#else
+#define Curl_resolver_asynch() 0
+#endif
+
+
+/********** end of generic resolver interface functions *****************/
+#endif /* HEADER_CURL_ASYN_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/base64.c b/external/libcurl_android/jni/libcurl/lib/base64.c
new file mode 100755
index 00000000..bd9ba35b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/base64.c
@@ -0,0 +1,314 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Base64 encoding/decoding */
+
+#include "curl_setup.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "urldata.h" /* for the SessionHandle definition */
+#include "warnless.h"
+#include "curl_base64.h"
+#include "curl_memory.h"
+#include "non-ascii.h"
+
+/* include memdebug.h last */
+#include "memdebug.h"
+
+/* ---- Base64 Encoding/Decoding Table --- */
+static const char base64[]=
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648
+ section 5 */
+static const char base64url[]=
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+static size_t decodeQuantum(unsigned char *dest, const char *src)
+{
+ size_t padding = 0;
+ const char *s, *p;
+ unsigned long i, v, x = 0;
+
+ for(i = 0, s = src; i < 4; i++, s++) {
+ v = 0;
+
+ if(*s == '=') {
+ x = (x << 6);
+ padding++;
+ }
+ else {
+ p = base64;
+
+ while(*p && (*p != *s)) {
+ v++;
+ p++;
+ }
+
+ if(*p == *s)
+ x = (x << 6) + v;
+ else
+ return 0;
+ }
+ }
+
+ if(padding < 1)
+ dest[2] = curlx_ultouc(x & 0xFFUL);
+
+ x >>= 8;
+ if(padding < 2)
+ dest[1] = curlx_ultouc(x & 0xFFUL);
+
+ x >>= 8;
+ dest[0] = curlx_ultouc(x & 0xFFUL);
+
+ return 3 - padding;
+}
+
+/*
+ * Curl_base64_decode()
+ *
+ * Given a base64 NUL-terminated string at src, decode it and return a
+ * pointer in *outptr to a newly allocated memory area holding decoded
+ * data. Size of decoded data is returned in variable pointed by outlen.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * When decoded data length is 0, returns NULL in *outptr.
+ *
+ * @unittest: 1302
+ */
+CURLcode Curl_base64_decode(const char *src,
+ unsigned char **outptr, size_t *outlen)
+{
+ size_t srclen = 0;
+ size_t length = 0;
+ size_t padding = 0;
+ size_t i;
+ size_t result;
+ size_t numQuantums;
+ size_t rawlen = 0;
+ unsigned char *pos;
+ unsigned char *newstr;
+
+ *outptr = NULL;
+ *outlen = 0;
+ srclen = strlen(src);
+
+ /* Check the length of the input string is valid */
+ if(!srclen || srclen % 4)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Find the position of any = padding characters */
+ while((src[length] != '=') && src[length])
+ length++;
+
+ /* A maximum of two = padding characters is allowed */
+ if(src[length] == '=') {
+ padding++;
+ if(src[length + 1] == '=')
+ padding++;
+ }
+
+ /* Check the = padding characters weren't part way through the input */
+ if(length + padding != srclen)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Calculate the number of quantums */
+ numQuantums = srclen / 4;
+
+ /* Calculate the size of the decoded string */
+ rawlen = (numQuantums * 3) - padding;
+
+ /* Allocate our buffer including room for a zero terminator */
+ newstr = malloc(rawlen + 1);
+ if(!newstr)
+ return CURLE_OUT_OF_MEMORY;
+
+ pos = newstr;
+
+ /* Decode the quantums */
+ for(i = 0; i < numQuantums; i++) {
+ result = decodeQuantum(pos, src);
+ if(!result) {
+ Curl_safefree(newstr);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ pos += result;
+ src += 4;
+ }
+
+ /* Zero terminate */
+ *pos = '\0';
+
+ /* Return the decoded data */
+ *outptr = newstr;
+ *outlen = rawlen;
+
+ return CURLE_OK;
+}
+
+static CURLcode base64_encode(const char *table64,
+ struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
+{
+ CURLcode error;
+ unsigned char ibuf[3];
+ unsigned char obuf[4];
+ int i;
+ int inputparts;
+ char *output;
+ char *base64data;
+ char *convbuf = NULL;
+
+ const char *indata = inputbuff;
+
+ *outptr = NULL;
+ *outlen = 0;
+
+ if(0 == insize)
+ insize = strlen(indata);
+
+ base64data = output = malloc(insize*4/3+4);
+ if(NULL == output)
+ return CURLE_OUT_OF_MEMORY;
+
+ /*
+ * The base64 data needs to be created using the network encoding
+ * not the host encoding. And we can't change the actual input
+ * so we copy it to a buffer, translate it, and use that instead.
+ */
+ error = Curl_convert_clone(data, indata, insize, &convbuf);
+ if(error) {
+ free(output);
+ return error;
+ }
+
+ if(convbuf)
+ indata = (char *)convbuf;
+
+ while(insize > 0) {
+ for(i = inputparts = 0; i < 3; i++) {
+ if(insize > 0) {
+ inputparts++;
+ ibuf[i] = (unsigned char) *indata;
+ indata++;
+ insize--;
+ }
+ else
+ ibuf[i] = 0;
+ }
+
+ obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
+ obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
+ ((ibuf[1] & 0xF0) >> 4));
+ obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
+ ((ibuf[2] & 0xC0) >> 6));
+ obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
+
+ switch(inputparts) {
+ case 1: /* only one byte read */
+ snprintf(output, 5, "%c%c==",
+ table64[obuf[0]],
+ table64[obuf[1]]);
+ break;
+ case 2: /* two bytes read */
+ snprintf(output, 5, "%c%c%c=",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]]);
+ break;
+ default:
+ snprintf(output, 5, "%c%c%c%c",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]],
+ table64[obuf[3]] );
+ break;
+ }
+ output += 4;
+ }
+ *output = '\0';
+ *outptr = base64data; /* return pointer to new data, allocated memory */
+
+ if(convbuf)
+ free(convbuf);
+
+ *outlen = strlen(base64data); /* return the length of the new data */
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_base64_encode()
+ *
+ * Given a pointer to an input buffer and an input size, encode it and
+ * return a pointer in *outptr to a newly allocated memory area holding
+ * encoded data. Size of encoded data is returned in variable pointed by
+ * outlen.
+ *
+ * Input length of 0 indicates input buffer holds a NUL-terminated string.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * When encoded data length is 0, returns NULL in *outptr.
+ *
+ * @unittest: 1302
+ */
+CURLcode Curl_base64_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
+{
+ return base64_encode(base64, data, inputbuff, insize, outptr, outlen);
+}
+
+/*
+ * Curl_base64url_encode()
+ *
+ * Given a pointer to an input buffer and an input size, encode it and
+ * return a pointer in *outptr to a newly allocated memory area holding
+ * encoded data. Size of encoded data is returned in variable pointed by
+ * outlen.
+ *
+ * Input length of 0 indicates input buffer holds a NUL-terminated string.
+ *
+ * Returns CURLE_OK on success, otherwise specific error code. Function
+ * output shall not be considered valid unless CURLE_OK is returned.
+ *
+ * When encoded data length is 0, returns NULL in *outptr.
+ *
+ * @unittest: 1302
+ */
+CURLcode Curl_base64url_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
+{
+ return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
+}
+/* ---- End of Base64 Encoding ---- */
diff --git a/external/libcurl_android/jni/libcurl/lib/bundles.c b/external/libcurl_android/jni/libcurl/lib/bundles.c
new file mode 100755
index 00000000..aadf0265
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/bundles.c
@@ -0,0 +1,110 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "url.h"
+#include "progress.h"
+#include "multiif.h"
+#include "bundles.h"
+#include "sendf.h"
+#include "rawstr.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static void conn_llist_dtor(void *user, void *element)
+{
+ struct connectdata *data = element;
+ (void)user;
+
+ data->bundle = NULL;
+}
+
+CURLcode Curl_bundle_create(struct SessionHandle *data,
+ struct connectbundle **cb_ptr)
+{
+ (void)data;
+ DEBUGASSERT(*cb_ptr == NULL);
+ *cb_ptr = malloc(sizeof(struct connectbundle));
+ if(!*cb_ptr)
+ return CURLE_OUT_OF_MEMORY;
+
+ (*cb_ptr)->num_connections = 0;
+ (*cb_ptr)->server_supports_pipelining = FALSE;
+
+ (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor);
+ if(!(*cb_ptr)->conn_list) {
+ Curl_safefree(*cb_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
+void Curl_bundle_destroy(struct connectbundle *cb_ptr)
+{
+ if(!cb_ptr)
+ return;
+
+ if(cb_ptr->conn_list) {
+ Curl_llist_destroy(cb_ptr->conn_list, NULL);
+ cb_ptr->conn_list = NULL;
+ }
+ Curl_safefree(cb_ptr);
+}
+
+/* Add a connection to a bundle */
+CURLcode Curl_bundle_add_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn)
+{
+ if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn))
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->bundle = cb_ptr;
+
+ cb_ptr->num_connections++;
+ return CURLE_OK;
+}
+
+/* Remove a connection from a bundle */
+int Curl_bundle_remove_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn)
+{
+ struct curl_llist_element *curr;
+
+ curr = cb_ptr->conn_list->head;
+ while(curr) {
+ if(curr->ptr == conn) {
+ Curl_llist_remove(cb_ptr->conn_list, curr, NULL);
+ cb_ptr->num_connections--;
+ conn->bundle = NULL;
+ return 1; /* we removed a handle */
+ }
+ curr = curr->next;
+ }
+ return 0;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/bundles.h b/external/libcurl_android/jni/libcurl/lib/bundles.h
new file mode 100755
index 00000000..3816c406
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/bundles.h
@@ -0,0 +1,45 @@
+#ifndef HEADER_CURL_BUNDLES_H
+#define HEADER_CURL_BUNDLES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct connectbundle {
+ bool server_supports_pipelining; /* TRUE if server supports pipelining,
+ set after first response */
+ size_t num_connections; /* Number of connections in the bundle */
+ struct curl_llist *conn_list; /* The connectdata members of the bundle */
+};
+
+CURLcode Curl_bundle_create(struct SessionHandle *data,
+ struct connectbundle **cb_ptr);
+
+void Curl_bundle_destroy(struct connectbundle *cb_ptr);
+
+CURLcode Curl_bundle_add_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn);
+
+int Curl_bundle_remove_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn);
+
+
+#endif /* HEADER_CURL_BUNDLES_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/config-amigaos.h b/external/libcurl_android/jni/libcurl/lib/config-amigaos.h
new file mode 100755
index 00000000..76d88775
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-amigaos.h
@@ -0,0 +1,167 @@
+#ifndef HEADER_CURL_CONFIG_AMIGAOS_H
+#define HEADER_CURL_CONFIG_AMIGAOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for AmigaOS */
+/* ================================================================ */
+
+#ifdef __AMIGA__ /* Any AmigaOS flavour */
+
+#define HAVE_ARPA_INET_H 1
+#define HAVE_CLOSESOCKET_CAMEL 1
+#define HAVE_ERRNO_H 1
+#define HAVE_GETHOSTBYADDR 1
+#define HAVE_INET_ADDR 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_IOCTLSOCKET_CAMEL 1
+#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
+#define HAVE_LIBCRYPTO 1
+#define HAVE_LIBSSL 1
+#define HAVE_LIBZ 1
+#define HAVE_LONGLONG 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_NETDB_H 1
+#define HAVE_NETINET_IN_H 1
+#define HAVE_NET_IF_H 1
+#define HAVE_OPENSSL_CRYPTO_H 1
+#define HAVE_OPENSSL_ERR_H 1
+#define HAVE_OPENSSL_PEM_H 1
+#define HAVE_OPENSSL_RSA_H 1
+#define HAVE_OPENSSL_SSL_H 1
+#define HAVE_OPENSSL_X509_H 1
+#define HAVE_PERROR 1
+#define HAVE_PWD_H 1
+#define HAVE_RAND_EGD 1
+#define HAVE_RAND_STATUS 1
+#define HAVE_SELECT 1
+#define HAVE_SETJMP_H 1
+#define HAVE_SGTTY_H 1
+#define HAVE_SIGNAL 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_SIG_ATOMIC_T 1
+#define HAVE_SOCKET 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRDUP 1
+#define HAVE_STRFTIME 1
+#define HAVE_STRICMP 1
+#define HAVE_STRINGS_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRSTR 1
+#define HAVE_STRUCT_TIMEVAL 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_SOCKET_H 1
+#define HAVE_SYS_SOCKIO_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UNAME 1
+#define HAVE_UNISTD_H 1
+#define HAVE_UTIME 1
+#define HAVE_UTIME_H 1
+#define HAVE_WRITABLE_ARGV 1
+#define HAVE_ZLIB_H 1
+#define HAVE_SYS_IOCTL_H 1
+
+#define NEED_MALLOC_H 1
+
+#define SIZEOF_INT 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_SIZE_T 4
+
+#define USE_MANUAL 1
+#define USE_OPENSSL 1
+#define USE_SSLEAY 1
+#define CURL_DISABLE_LDAP 1
+
+#define OS "AmigaOS"
+
+#define PACKAGE "curl"
+#define PACKAGE_BUGREPORT "curl-bug@haxx.se"
+#define PACKAGE_NAME "curl"
+#define PACKAGE_STRING "curl -"
+#define PACKAGE_TARNAME "curl"
+#define PACKAGE_VERSION "-"
+#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt"
+
+#define RETSIGTYPE void
+#define SELECT_TYPE_ARG1 int
+#define SELECT_TYPE_ARG234 (fd_set *)
+#define SELECT_TYPE_ARG5 (struct timeval *)
+
+#define STDC_HEADERS 1
+#define TIME_WITH_SYS_TIME 1
+
+#define in_addr_t int
+
+#ifndef F_OK
+# define F_OK 0
+#endif
+
+#ifndef O_RDONLY
+# define O_RDONLY 0x0000
+#endif
+
+#ifndef LONG_MAX
+# define LONG_MAX 0x7fffffffL
+#endif
+
+#ifndef LONG_MIN
+# define LONG_MIN (-0x7fffffffL-1)
+#endif
+
+#define HAVE_GETNAMEINFO 1
+#define GETNAMEINFO_QUAL_ARG1 const
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+#define GETNAMEINFO_TYPE_ARG2 int
+#define GETNAMEINFO_TYPE_ARG46 size_t
+#define GETNAMEINFO_TYPE_ARG7 int
+
+#define HAVE_RECV 1
+#define RECV_TYPE_ARG1 long
+#define RECV_TYPE_ARG2 char *
+#define RECV_TYPE_ARG3 long
+#define RECV_TYPE_ARG4 long
+#define RECV_TYPE_RETV long
+
+#define HAVE_RECVFROM 1
+#define RECVFROM_TYPE_ARG1 long
+#define RECVFROM_TYPE_ARG2 char
+#define RECVFROM_TYPE_ARG3 long
+#define RECVFROM_TYPE_ARG4 long
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+#define RECVFROM_TYPE_ARG6 long
+#define RECVFROM_TYPE_RETV long
+
+#define HAVE_SEND 1
+#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2 const
+#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_ARG4 int
+#define SEND_TYPE_RETV int
+
+#endif /* __AMIGA__ */
+#endif /* HEADER_CURL_CONFIG_AMIGAOS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/config-dos.h b/external/libcurl_android/jni/libcurl/lib/config-dos.h
new file mode 100755
index 00000000..dd5b06db
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-dos.h
@@ -0,0 +1,187 @@
+#ifndef HEADER_CURL_CONFIG_DOS_H
+#define HEADER_CURL_CONFIG_DOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+
+/* ================================================================ */
+/* lib/config-dos.h - Hand crafted config file for DOS */
+/* ================================================================ */
+
+#if defined(DJGPP)
+ #define OS "MSDOS/djgpp"
+#elif defined(__HIGHC__)
+ #define OS "MSDOS/HighC"
+#elif defined(__WATCOMC__)
+ #define OS "MSDOS/Watcom"
+#else
+ #define OS "MSDOS/?"
+#endif
+
+#define PACKAGE "curl"
+
+#define HAVE_ARPA_INET_H 1
+#define HAVE_ERRNO_H 1
+#define HAVE_FCNTL_H 1
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETNAMEINFO 1
+#define HAVE_GETPROTOBYNAME 1
+#define HAVE_GETTIMEOFDAY 1
+#define HAVE_IO_H 1
+#define HAVE_IOCTL 1
+#define HAVE_IOCTL_FIONBIO 1
+#define HAVE_IOCTLSOCKET 1
+#define HAVE_IOCTLSOCKET_FIONBIO 1
+#define HAVE_LIMITS_H 1
+#define HAVE_LOCALE_H 1
+#define HAVE_LONGLONG 1
+#define HAVE_MEMORY_H 1
+#define HAVE_NETDB_H 1
+#define HAVE_NETINET_IN_H 1
+#define HAVE_NETINET_TCP_H 1
+#define HAVE_NET_IF_H 1
+#define HAVE_PROCESS_H 1
+#define HAVE_RECV 1
+#define HAVE_RECVFROM 1
+#define HAVE_SELECT 1
+#define HAVE_SEND 1
+#define HAVE_SETJMP_H 1
+#define HAVE_SETLOCALE 1
+#define HAVE_SETMODE 1
+#define HAVE_SIGNAL 1
+#define HAVE_SOCKET 1
+#define HAVE_STRDUP 1
+#define HAVE_STRICMP 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRUCT_TIMEVAL 1
+#define HAVE_STRUCT_IN6_ADDR 1
+#define HAVE_SYS_IOCTL_H 1
+#define HAVE_SYS_SOCKET_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UNISTD_H 1
+
+#define NEED_MALLOC_H 1
+
+#define RETSIGTYPE void
+#define SIZEOF_INT 4
+#define SIZEOF_LONG_DOUBLE 16
+#define SIZEOF_SHORT 2
+#define SIZEOF_SIZE_T 4
+#define STDC_HEADERS 1
+#define TIME_WITH_SYS_TIME 1
+
+/* Qualifiers for send(), recv(), recvfrom() and getnameinfo(). */
+
+#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2 const
+#define SEND_TYPE_ARG2 void *
+#define SEND_TYPE_ARG3 int
+#define SEND_TYPE_ARG4 int
+#define SEND_TYPE_RETV int
+
+#define RECV_TYPE_ARG1 int
+#define RECV_TYPE_ARG2 void *
+#define RECV_TYPE_ARG3 int
+#define RECV_TYPE_ARG4 int
+#define RECV_TYPE_RETV int
+
+#define RECVFROM_TYPE_ARG1 int
+#define RECVFROM_TYPE_ARG2 void
+#define RECVFROM_TYPE_ARG3 int
+#define RECVFROM_TYPE_ARG4 int
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+#define RECVFROM_TYPE_ARG6 int
+#define RECVFROM_TYPE_RETV int
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+#define GETNAMEINFO_QUAL_ARG1 const
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+#define GETNAMEINFO_TYPE_ARG2 int
+#define GETNAMEINFO_TYPE_ARG46 int
+#define GETNAMEINFO_TYPE_ARG7 int
+
+#define BSD
+
+/* CURLDEBUG definition enables memory tracking */
+/* #define CURLDEBUG */
+
+/* USE_ZLIB on cmd-line */
+#ifdef USE_ZLIB
+ #define HAVE_ZLIB_H 1
+ #define HAVE_LIBZ 1
+#endif
+
+/* USE_SSLEAY on cmd-line */
+#ifdef USE_SSLEAY
+ #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+ #define HAVE_OPENSSL_ENGINE_H 1
+ #define OPENSSL_NO_KRB5 1
+ #define USE_OPENSSL 1
+#endif
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+#define in_addr_t u_long
+
+#if defined(__HIGHC__) || \
+ (defined(__GNUC__) && (__GNUC__ < 4))
+ #define ssize_t int
+#endif
+
+#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")
+
+/* Target HAVE_x section */
+
+#if defined(DJGPP)
+ #define HAVE_BASENAME 1
+ #define HAVE_STRCASECMP 1
+ #define HAVE_SIGACTION 1
+ #define HAVE_SIGSETJMP 1
+ #define HAVE_SYS_TIME_H 1
+ #define HAVE_TERMIOS_H 1
+ #define HAVE_VARIADIC_MACROS_GCC 1
+
+ /* Because djgpp <= 2.03 doesn't have snprintf() etc. */
+ #if (DJGPP_MINOR < 4)
+ #define _MPRINTF_REPLACE
+ #endif
+
+#elif defined(__WATCOMC__)
+ #define HAVE_STRCASECMP 1
+
+#elif defined(__HIGHC__)
+ #define HAVE_SYS_TIME_H 1
+ #define strerror(e) strerror_s_((e))
+#endif
+
+#ifdef MSDOS /* Watt-32 */
+ #define HAVE_CLOSE_S 1
+#endif
+
+#undef word
+#undef byte
+
+#endif /* HEADER_CURL_CONFIG_DOS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/config-mac.h b/external/libcurl_android/jni/libcurl/lib/config-mac.h
new file mode 100755
index 00000000..d89c3851
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-mac.h
@@ -0,0 +1,126 @@
+#ifndef HEADER_CURL_CONFIG_MAC_H
+#define HEADER_CURL_CONFIG_MAC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* =================================================================== */
+/* Hand crafted config file for Mac OS 9 */
+/* =================================================================== */
+/* On Mac OS X you must run configure to generate curl_config.h file */
+/* =================================================================== */
+
+#define OS "mac"
+
+/* Define if you want the built-in manual */
+#define USE_MANUAL 1
+
+#define HAVE_ERRNO_H 1
+#define HAVE_NETINET_IN_H 1
+#define HAVE_SYS_SOCKET_H 1
+#define HAVE_SYS_SELECT_H 1
+#define HAVE_NETDB_H 1
+#define HAVE_ARPA_INET_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_NET_IF_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_GETTIMEOFDAY 1
+#define HAVE_FCNTL_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_ALLOCA_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UTIME_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_UTIME_H 1
+
+#define TIME_WITH_SYS_TIME 1
+
+#define HAVE_ALARM 1
+#define HAVE_FTRUNCATE 1
+#define HAVE_UTIME 1
+#define HAVE_SETVBUF 1
+#define HAVE_STRFTIME 1
+#define HAVE_INET_ADDR 1
+#define HAVE_MEMCPY 1
+#define HAVE_SELECT 1
+#define HAVE_SOCKET 1
+#define HAVE_STRUCT_TIMEVAL 1
+
+#define HAVE_SIGACTION 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_SIG_ATOMIC_T 1
+
+#ifdef MACOS_SSL_SUPPORT
+# define USE_SSLEAY 1
+# define USE_OPENSSL 1
+#endif
+
+#define CURL_DISABLE_LDAP 1
+
+#define HAVE_RAND_STATUS 1
+#define HAVE_RAND_EGD 1
+
+#define HAVE_IOCTL 1
+#define HAVE_IOCTL_FIONBIO 1
+
+#define RETSIGTYPE void
+
+#define SIZEOF_INT 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_SIZE_T 4
+
+#define HAVE_GETNAMEINFO 1
+#define GETNAMEINFO_QUAL_ARG1 const
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+#define GETNAMEINFO_TYPE_ARG46 size_t
+#define GETNAMEINFO_TYPE_ARG7 int
+
+#define HAVE_RECV 1
+#define RECV_TYPE_ARG1 int
+#define RECV_TYPE_ARG2 void *
+#define RECV_TYPE_ARG3 size_t
+#define RECV_TYPE_ARG4 int
+#define RECV_TYPE_RETV ssize_t
+
+#define HAVE_RECVFROM 1
+#define RECVFROM_TYPE_ARG1 int
+#define RECVFROM_TYPE_ARG2 void
+#define RECVFROM_TYPE_ARG3 size_t
+#define RECVFROM_TYPE_ARG4 int
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+#define RECVFROM_TYPE_ARG6 int
+#define RECVFROM_TYPE_RETV ssize_t
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+#define HAVE_SEND 1
+#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2 const
+#define SEND_TYPE_ARG2 void *
+#define SEND_TYPE_ARG3 size_T
+#define SEND_TYPE_ARG4 int
+#define SEND_TYPE_RETV ssize_t
+
+#define HAVE_EXTRA_STRICMP_H 1
+#define HAVE_EXTRA_STRDUP_H 1
+
+#endif /* HEADER_CURL_CONFIG_MAC_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/config-os400.h b/external/libcurl_android/jni/libcurl/lib/config-os400.h
new file mode 100755
index 00000000..e65e30ac
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-os400.h
@@ -0,0 +1,560 @@
+#ifndef HEADER_CURL_CONFIG_OS400_H
+#define HEADER_CURL_CONFIG_OS400_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for OS/400 */
+/* ================================================================ */
+
+#pragma enum(int)
+
+#undef PACKAGE
+
+/* Version number of this archive. */
+#undef VERSION
+
+/* Define if you have the getpass function. */
+#undef HAVE_GETPASS
+
+/* Define cpu-machine-OS */
+#define OS "OS/400"
+
+/* Define if you have the gethostbyaddr_r() function with 5 arguments */
+#define HAVE_GETHOSTBYADDR_R_5
+
+/* Define if you have the gethostbyaddr_r() function with 7 arguments */
+#undef HAVE_GETHOSTBYADDR_R_7
+
+/* Define if you have the gethostbyaddr_r() function with 8 arguments */
+#undef HAVE_GETHOSTBYADDR_R_8
+
+/* OS400 supports a 3-argument ASCII version of gethostbyaddr_r(), but its
+ * prototype is incompatible with the "standard" one (1st argument is not
+ * const). However, getaddrinfo() is supported (ASCII version defined as
+ * a local wrapper in setup-os400.h) in a threadsafe way: we can then
+ * configure getaddrinfo() as such and get rid of gethostbyname_r() without
+ * loss of threadsafeness. */
+#undef HAVE_GETHOSTBYNAME_R
+#undef HAVE_GETHOSTBYNAME_R_3
+#undef HAVE_GETHOSTBYNAME_R_5
+#undef HAVE_GETHOSTBYNAME_R_6
+#define HAVE_GETADDRINFO
+#define HAVE_GETADDRINFO_THREADSAFE
+
+/* Define if you need the _REENTRANT define for some functions */
+#undef NEED_REENTRANT
+
+/* Define if you have the Kerberos4 libraries (including -ldes) */
+#undef HAVE_KRB4
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define this to 'int' if ssize_t is not an available typedefed type */
+#undef ssize_t
+
+/* Define this as a suitable file to read random data from */
+#undef RANDOM_FILE
+
+/* Define this to your Entropy Gathering Daemon socket pathname */
+#undef EGD_SOCKET
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define if you have the <alloca.h> header file. */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H
+
+/* Define if you have the `closesocket' function. */
+#undef HAVE_CLOSESOCKET
+
+/* Define if you have the <crypto.h> header file. */
+#undef HAVE_CRYPTO_H
+
+/* Define if you have the <des.h> header file. */
+#undef HAVE_DES_H
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H
+
+/* Define if you have the <err.h> header file. */
+#undef HAVE_ERR_H
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H
+
+/* Define if you have the `geteuid' function. */
+#define HAVE_GETEUID
+
+/* Define if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR
+
+/* Define if you have the `gethostbyaddr_r' function. */
+#define HAVE_GETHOSTBYADDR_R
+
+/* Define if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME
+
+/* Define if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define if you have the `getpass_r' function. */
+#undef HAVE_GETPASS_R
+
+/* Define if you have the `getpwuid' function. */
+#define HAVE_GETPWUID
+
+/* Define if you have the `getservbyname' function. */
+#define HAVE_GETSERVBYNAME
+
+/* Define if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY
+
+/* Define if you have the `timeval' struct. */
+#define HAVE_STRUCT_TIMEVAL
+
+/* Define if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H
+
+/* Define if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define if you have the `krb_get_our_ip_for_realm' function. */
+#undef HAVE_KRB_GET_OUR_IP_FOR_REALM
+
+/* Define if you have the <krb.h> header file. */
+#undef HAVE_KRB_H
+
+/* Define if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define if you have the `resolve' library (-lresolve). */
+#undef HAVE_LIBRESOLVE
+
+/* Define if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
+
+/* Define if you have GSS API. */
+#define HAVE_GSSAPI
+
+/* Define if you have the GNU gssapi libraries */
+#undef HAVE_GSSGNU
+
+/* Define if you have the Heimdal gssapi libraries */
+#define HAVE_GSSHEIMDAL
+
+/* Define if you have the MIT gssapi libraries */
+#undef HAVE_GSSMIT
+
+/* Define if you have the `ucb' library (-lucb). */
+#undef HAVE_LIBUCB
+
+/* Define if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R
+
+/* Define if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H
+
+/* Define if you need the malloc.h header file even with stdlib.h */
+/* #define NEED_MALLOC_H 1 */
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H
+
+/* Define if you have the <netinet/if_ether.h> header file. */
+#undef HAVE_NETINET_IF_ETHER_H
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H
+
+/* Define if you have the <openssl/crypto.h> header file. */
+#undef HAVE_OPENSSL_CRYPTO_H
+
+/* Define if you have the <openssl/err.h> header file. */
+#undef HAVE_OPENSSL_ERR_H
+
+/* Define if you have the <openssl/pem.h> header file. */
+#undef HAVE_OPENSSL_PEM_H
+
+/* Define if you have the <openssl/rsa.h> header file. */
+#undef HAVE_OPENSSL_RSA_H
+
+/* Define if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define if you have the <openssl/x509.h> header file. */
+#undef HAVE_OPENSSL_X509_H
+
+/* Define if you have the <pem.h> header file. */
+#undef HAVE_PEM_H
+
+/* Define if you have the `perror' function. */
+#define HAVE_PERROR
+
+/* Define if you have the <pwd.h> header file. */
+#define HAVE_PWD_H
+
+/* Define if you have the `RAND_egd' function. */
+#undef HAVE_RAND_EGD
+
+/* Define if you have the `RAND_screen' function. */
+#undef HAVE_RAND_SCREEN
+
+/* Define if you have the `RAND_status' function. */
+#undef HAVE_RAND_STATUS
+
+/* Define if you have the <rsa.h> header file. */
+#undef HAVE_RSA_H
+
+/* Define if you have the `select' function. */
+#define HAVE_SELECT
+
+/* Define if you have the `setvbuf' function. */
+#define HAVE_SETVBUF
+
+/* Define if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define if you have the `sigaction' function. */
+#define HAVE_SIGACTION
+
+/* Define if you have the `signal' function. */
+#undef HAVE_SIGNAL
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T
+
+/* Define if sig_atomic_t is already defined as volatile. */
+#undef HAVE_SIG_ATOMIC_T_VOLATILE
+
+/* Define if you have the `socket' function. */
+#define HAVE_SOCKET
+
+/* Define if you have the <ssl.h> header file. */
+#undef HAVE_SSL_H
+
+/* Define if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H
+
+
+/* The following define is needed on OS400 to enable strcmpi(), stricmp() and
+ strdup(). */
+#define __cplusplus__strings__
+
+/* Define if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the `strcmpi' function. */
+#define HAVE_STRCMPI
+
+/* Define if you have the `stricmp' function. */
+#define HAVE_STRICMP
+
+/* Define if you have the `strdup' function. */
+#define HAVE_STRDUP
+
+
+/* Define if you have the `strftime' function. */
+#define HAVE_STRFTIME
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H
+
+/* Define if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define if you have the <stropts.h> header file. */
+#undef HAVE_STROPTS_H
+
+/* Define if you have the `strstr' function. */
+#define HAVE_STRSTR
+
+/* Define if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R
+
+/* Define if you have the `strtoll' function. */
+#undef HAVE_STRTOLL /* Allows ASCII compile on V5R1. */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H
+
+/* Define if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H
+
+/* Define if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H
+
+/* Define if you have the `tcgetattr' function. */
+#undef HAVE_TCGETATTR
+
+/* Define if you have the `tcsetattr' function. */
+#undef HAVE_TCSETATTR
+
+/* Define if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H
+
+/* Define if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H
+
+/* Define if you have the <winsock.h> header file. */
+#undef HAVE_WINSOCK_H
+
+/* Define if you have the <x509.h> header file. */
+#undef HAVE_X509_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 8
+
+/* Define if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG
+
+/* The size of a `long long', as computed by sizeof. */
+#define SIZEOF_LONG_LONG 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* Whether long long constants must be suffixed by LL. */
+
+#define HAVE_LL
+
+/* Define this if you have struct sockaddr_storage */
+#define HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#define _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* type to use in place of in_addr_t if not defined */
+#define in_addr_t unsigned long
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define if you have the ioctl function. */
+#define HAVE_IOCTL
+
+/* Define if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO
+
+/* Define if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR
+
+/* To disable LDAP */
+#undef CURL_DISABLE_LDAP
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL
+
+/* Define if you have the ldap_url_parse procedure. */
+/* #define HAVE_LDAP_URL_PARSE */ /* Disabled because of an IBM bug. */
+
+/* Define if you have the getnameinfo function. */
+/* OS400 has no ASCII version of this procedure: wrapped in setup-os400.h. */
+#define HAVE_GETNAMEINFO
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 socklen_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define if you have the recvfrom function. */
+#define HAVE_RECVFROM
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define if you have the send function. */
+#define HAVE_SEND
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* Define to use the QsoSSL package. */
+#undef USE_QSOSSL
+
+/* Define to use the GSKit package. */
+#define USE_GSKIT
+
+/* Use the system keyring as the default CA bundle. */
+#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB"
+
+/* ---------------------------------------------------------------- */
+/* ADDITIONAL DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* The following must be defined BEFORE system header files inclusion. */
+
+#define __ptr128 /* No teraspace. */
+#define qadrt_use_fputc_inline /* Generate fputc() wrapper inline. */
+#define qadrt_use_fread_inline /* Generate fread() wrapper inline. */
+#define qadrt_use_fwrite_inline /* Generate fwrite() wrapper inline. */
+
+#endif /* HEADER_CURL_CONFIG_OS400_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/config-riscos.h b/external/libcurl_android/jni/libcurl/lib/config-riscos.h
new file mode 100755
index 00000000..e4005778
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-riscos.h
@@ -0,0 +1,513 @@
+#ifndef HEADER_CURL_CONFIG_RISCOS_H
+#define HEADER_CURL_CONFIG_RISCOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for RISC OS */
+/* ================================================================ */
+
+/* Name of this package! */
+#undef PACKAGE
+
+/* Version number of this archive. */
+#undef VERSION
+
+/* Define if you have the getpass function. */
+#undef HAVE_GETPASS
+
+/* Define cpu-machine-OS */
+#define OS "ARM-RISC OS"
+
+/* Define if you want the built-in manual */
+#define USE_MANUAL
+
+/* Define if you have the gethostbyaddr_r() function with 5 arguments */
+#undef HAVE_GETHOSTBYADDR_R_5
+
+/* Define if you have the gethostbyaddr_r() function with 7 arguments */
+#undef HAVE_GETHOSTBYADDR_R_7
+
+/* Define if you have the gethostbyaddr_r() function with 8 arguments */
+#undef HAVE_GETHOSTBYADDR_R_8
+
+/* Define if you have the gethostbyname_r() function with 3 arguments */
+#undef HAVE_GETHOSTBYNAME_R_3
+
+/* Define if you have the gethostbyname_r() function with 5 arguments */
+#undef HAVE_GETHOSTBYNAME_R_5
+
+/* Define if you have the gethostbyname_r() function with 6 arguments */
+#undef HAVE_GETHOSTBYNAME_R_6
+
+/* Define if you need the _REENTRANT define for some functions */
+#undef NEED_REENTRANT
+
+/* Define if you have the Kerberos4 libraries (including -ldes) */
+#undef HAVE_KRB4
+
+/* Define if you want to enable IPv6 support */
+#undef ENABLE_IPV6
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define this to 'int' if ssize_t is not an available typedefed type */
+#undef ssize_t
+
+/* Define this as a suitable file to read random data from */
+#undef RANDOM_FILE
+
+/* Define this to your Entropy Gathering Daemon socket pathname */
+#undef EGD_SOCKET
+
+/* Define if you want to enable IPv6 support */
+#undef ENABLE_IPV6
+
+/* Define if you have the alarm function. */
+#define HAVE_ALARM
+
+/* Define if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H
+
+/* Define if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H
+
+/* Define if you have the `closesocket' function. */
+#undef HAVE_CLOSESOCKET
+
+/* Define if you have the <crypto.h> header file. */
+#undef HAVE_CRYPTO_H
+
+/* Define if you have the <des.h> header file. */
+#undef HAVE_DES_H
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H
+
+/* Define if you have the <err.h> header file. */
+#undef HAVE_ERR_H
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H
+
+/* Define if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE
+
+/* Define if getaddrinfo exists and works */
+#define HAVE_GETADDRINFO
+
+/* Define if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR
+
+/* Define if you have the `gethostbyaddr_r' function. */
+#undef HAVE_GETHOSTBYADDR_R
+
+/* Define if you have the `gethostbyname_r' function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME
+
+/* Define if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H
+
+/* Define if you have the `getpass_r' function. */
+#undef HAVE_GETPASS_R
+
+/* Define if you have the `getpwuid' function. */
+#undef HAVE_GETPWUID
+
+/* Define if you have the `getservbyname' function. */
+#undef HAVE_GETSERVBYNAME
+
+/* Define if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY
+
+/* Define if you have the `timeval' struct. */
+#define HAVE_STRUCT_TIMEVAL
+
+/* Define if you have the `inet_addr' function. */
+#undef HAVE_INET_ADDR
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H
+
+/* Define if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define if you have the `krb_get_our_ip_for_realm' function. */
+#undef HAVE_KRB_GET_OUR_IP_FOR_REALM
+
+/* Define if you have the <krb.h> header file. */
+#undef HAVE_KRB_H
+
+/* Define if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define if you have the `resolve' library (-lresolve). */
+#undef HAVE_LIBRESOLVE
+
+/* Define if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
+
+/* Define if you have the `ucb' library (-lucb). */
+#undef HAVE_LIBUCB
+
+/* Define if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H
+
+/* Define if you need the malloc.h header file even with stdlib.h */
+/* #define NEED_MALLOC_H 1 */
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H
+
+/* Define if you have the <netinet/if_ether.h> header file. */
+#undef HAVE_NETINET_IF_ETHER_H
+
+/* Define if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H
+
+/* Define if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H
+
+/* Define if you have the <openssl/crypto.h> header file. */
+#undef HAVE_OPENSSL_CRYPTO_H
+
+/* Define if you have the <openssl/err.h> header file. */
+#undef HAVE_OPENSSL_ERR_H
+
+/* Define if you have the <openssl/pem.h> header file. */
+#undef HAVE_OPENSSL_PEM_H
+
+/* Define if you have the <openssl/rsa.h> header file. */
+#undef HAVE_OPENSSL_RSA_H
+
+/* Define if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define if you have the <openssl/x509.h> header file. */
+#undef HAVE_OPENSSL_X509_H
+
+/* Define if you have the <pem.h> header file. */
+#undef HAVE_PEM_H
+
+/* Define if you have the `perror' function. */
+#undef HAVE_PERROR
+
+/* Define if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define if you have the `RAND_egd' function. */
+#undef HAVE_RAND_EGD
+
+/* Define if you have the `RAND_screen' function. */
+#undef HAVE_RAND_SCREEN
+
+/* Define if you have the `RAND_status' function. */
+#undef HAVE_RAND_STATUS
+
+/* Define if you have the <rsa.h> header file. */
+#undef HAVE_RSA_H
+
+/* Define if you have the `select' function. */
+#define HAVE_SELECT
+
+/* Define if you have the `setvbuf' function. */
+#undef HAVE_SETVBUF
+
+/* Define if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H
+
+/* Define if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
+/* Define if you have the `signal' function. */
+#define HAVE_SIGNAL
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T
+
+/* Define if sig_atomic_t is already defined as volatile. */
+#undef HAVE_SIG_ATOMIC_T_VOLATILE
+
+/* Define if you have the `socket' function. */
+#define HAVE_SOCKET
+
+/* Define if you have the <ssl.h> header file. */
+#undef HAVE_SSL_H
+
+/* Define if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H
+
+/* Define if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the `strcmpi' function. */
+#undef HAVE_STRCMPI
+
+/* Define if you have the `strdup' function. */
+#define HAVE_STRDUP
+
+/* Define if you have the `strftime' function. */
+#define HAVE_STRFTIME
+
+/* Define if you have the `stricmp' function. */
+#define HAVE_STRICMP
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H
+
+/* Define if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define if you have the `strstr' function. */
+#define HAVE_STRSTR
+
+/* Define if you have the `strtok_r' function. */
+#undef HAVE_STRTOK_R
+
+/* Define if you have the `strtoll' function. */
+#undef HAVE_STRTOLL
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H
+
+/* Define if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H
+
+/* Define if you have the `tcgetattr' function. */
+#define HAVE_TCGETATTR
+
+/* Define if you have the `tcsetattr' function. */
+#define HAVE_TCSETATTR
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H
+
+/* Define if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define if you have the `uname' function. */
+#define HAVE_UNAME
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H
+
+/* Define if you have the <winsock.h> header file. */
+#undef HAVE_WINSOCK_H
+
+/* Define if you have the <x509.h> header file. */
+#undef HAVE_X509_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long double', as computed by sizeof. */
+#undef SIZEOF_LONG_DOUBLE
+
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define if you have the ioctl function. */
+#define HAVE_IOCTL
+
+/* Define if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP
+
+/* Define if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV ssize_t
+
+/* Define 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 void
+
+/* Define if the type pointed by arg 2 for recvfrom is void. */
+#define RECVFROM_TYPE_ARG2_IS_VOID
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV ssize_t
+
+/* Define if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV ssize_t
+
+#endif /* HEADER_CURL_CONFIG_RISCOS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/config-symbian.h b/external/libcurl_android/jni/libcurl/lib/config-symbian.h
new file mode 100755
index 00000000..f7eaab92
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-symbian.h
@@ -0,0 +1,817 @@
+#ifndef HEADER_CURL_CONFIG_SYMBIAN_H
+#define HEADER_CURL_CONFIG_SYMBIAN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for Symbian */
+/* ================================================================ */
+
+/* Location of default ca bundle */
+/* #define CURL_CA_BUNDLE "/etc/pki/tls/certs/ca-bundle.crt"*/
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+/* #undef CURL_DISABLE_DICT */
+
+/* to disable FILE */
+/* #undef CURL_DISABLE_FILE */
+
+/* to disable FTP */
+/* #undef CURL_DISABLE_FTP */
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable TELNET */
+/* #undef CURL_DISABLE_TELNET */
+
+/* to disable TFTP */
+/* #undef CURL_DISABLE_TFTP */
+
+/* to disable verbose strings */
+/* #define CURL_DISABLE_VERBOSE_STRINGS 1*/
+
+/* Definition to make a library symbol externally visible. */
+/* #undef CURL_EXTERN_SYMBOL */
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6 1
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define to 1 if you have the <alloca.h> header file. */
+/*#define HAVE_ALLOCA_H 1*/
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/*#define HAVE_ARPA_TFTP_H 1*/
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `basename' function. */
+/*#define HAVE_BASENAME 1*/
+
+/* Define to 1 if bool is an available type. */
+/*#define HAVE_BOOL_T 1*/
+
+/* Define to 1 if you have the `closesocket' function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/*#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1*/
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <des.h> header file. */
+/* #undef HAVE_DES_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/*#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1*/
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+#define HAVE_ERR_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the `fork' function. */
+/*#define HAVE_FORK 1*/
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if getaddrinfo exists and works */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* If you have gethostbyname */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+/*#define HAVE_GETRLIMIT 1*/
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* we have a glibc-style strerror_r() */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the gssapi libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have the GNU gssapi libraries */
+/* #undef HAVE_GSSGNU */
+
+/* if you have the Heimdal gssapi libraries */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have the MIT gssapi libraries */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/*#define HAVE_IDNA_STRERROR 1*/
+
+/* Define to 1 if you have the `idn_free' function. */
+/*#define HAVE_IDN_FREE 1*/
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/*#define HAVE_IDN_FREE_H 1*/
+
+/* Define to 1 if you have the `inet_addr' function. */
+/*#define HAVE_INET_ADDR 1*/
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+/*#define HAVE_INET_NTOP 1*/
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+/*#define HAVE_INET_PTON 1*/
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO
+ function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* if you have the Kerberos4 libraries (including -ldes) */
+/* #undef HAVE_KRB4 */
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
+
+/* Define to 1 if you have the <krb.h> header file. */
+/* #undef HAVE_KRB_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/*#define HAVE_LBER_H 1*/
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/*#define HAVE_LDAP_H 1*/
+
+/* Use LDAPS implementation */
+/*#define HAVE_LDAP_SSL 1*/
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/*#define HAVE_LDAP_URL_PARSE 1*/
+
+/* Define to 1 if you have the <libgen.h> header file. */
+/*#define HAVE_LIBGEN_H 1*/
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/*#define HAVE_LIBIDN 1*/
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/*#define HAVE_LIBSSH2 1*/
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/*#define HAVE_LIBSSH2_H 1*/
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/*#define HAVE_LIBSSL 1*/
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+/*#define HAVE_MALLOC_H 1*/
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+/*#define HAVE_MSG_NOSIGNAL 1*/
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+/*#define HAVE_NETINET_TCP_H 1*/
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/*#define HAVE_NI_WITHSCOPEID 1*/
+
+/* we have no strerror_r() proto */
+/* #undef HAVE_NO_STRERROR_R_DECL */
+
+/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/*#define HAVE_OPENSSL_CRYPTO_H 1*/
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/*#define HAVE_OPENSSL_ENGINE_H 1*/
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/*#define HAVE_OPENSSL_ERR_H 1*/
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/*#define HAVE_OPENSSL_PEM_H 1*/
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/*#define HAVE_OPENSSL_PKCS12_H 1*/
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/*#define HAVE_OPENSSL_RSA_H 1*/
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/*#define HAVE_OPENSSL_SSL_H 1*/
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/*#define HAVE_OPENSSL_X509_H 1*/
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `poll' function. */
+/*#define HAVE_POLL 1*/
+
+/* If you have a fine poll */
+/*#define HAVE_POLL_FINE 1*/
+
+/* Define to 1 if you have the <poll.h> header file. */
+/*#define HAVE_POLL_H 1*/
+
+/* we have a POSIX-style strerror_r() */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+#define HAVE_RAND_EGD 1
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/*#define HAVE_RAND_STATUS 1*/
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+/* #undef HAVE_SETMODE */
+
+/* Define to 1 if you have the `setrlimit' function. */
+/*#define HAVE_SETRLIMIT 1*/
+
+/* Define to 1 if you have the setsockopt function. */
+/* #undef HAVE_SETSOCKOPT */
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+/*#define HAVE_SGTTY_H 1*/
+
+/* Define to 1 if you have the `sigaction' function. */
+/*#define HAVE_SIGACTION 1*/
+
+/* Define to 1 if you have the `siginterrupt' function. */
+/*#define HAVE_SIGINTERRUPT 1*/
+
+/* Define to 1 if you have the `signal' function. */
+/*#define HAVE_SIGNAL 1*/
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* If you have sigsetjmp */
+/*#define HAVE_SIGSETJMP 1*/
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+/*#define HAVE_SIG_ATOMIC_T 1*/
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/*#define HAVE_SSL_GET_SHUTDOWN 1*/
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+/*#define HAVE_SYS_POLL_H 1*/
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+/*#define HAVE_TERMIOS_H 1*/
+
+/* Define to 1 if you have the <termio.h> header file. */
+/*#define HAVE_TERMIO_H 1*/
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/*#define HAVE_TLD_H 1*/
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/*#define HAVE_TLD_STRERROR 1*/
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+/*#define HAVE_VARIADIC_MACROS_GCC 1*/
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+/*#define HAVE_WRITABLE_ARGV 1*/
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* cpu-machine-OS */
+#ifdef __WINS__
+#define OS "i386-pc-epoc32"
+#elif __MARM__
+#define OS "arm-unknown-epoc32"
+#else
+/* This won't happen on any current Symbian version */
+#define OS "unknown-unknown-epoc32"
+#endif
+
+/* Name of package */
+/*#define PACKAGE "curl"*/
+
+/* Define to the address where bug reports for this package should be sent. */
+/*#define PACKAGE_BUGREPORT \
+ "a suitable curl mailing list => http://curl.haxx.se/mail/"*/
+
+/* Define to the full name of this package. */
+/*#define PACKAGE_NAME "curl"*/
+
+/* Define to the full name and version of this package. */
+/*#define PACKAGE_STRING "curl -"*/
+
+/* Define to the one symbol short name of this package. */
+/*#define PACKAGE_TARNAME "curl"*/
+
+/* Define to the version of this package. */
+/*#define PACKAGE_VERSION "-"*/
+
+/* a suitable file to read random data from */
+/*#define RANDOM_FILE "/dev/urandom"*/
+
+#define RECV_TYPE_ARG1 int
+#define RECV_TYPE_ARG2 void*
+#define RECV_TYPE_ARG3 size_t
+#define RECV_TYPE_ARG4 int
+#define RECV_TYPE_RETV ssize_t
+
+#define RECVFROM_TYPE_ARG1 int
+#define RECVFROM_TYPE_ARG2 void
+#define RECVFROM_TYPE_ARG3 size_t
+#define RECVFROM_TYPE_ARG4 int
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+#define RECVFROM_TYPE_ARG6 size_t
+#define RECVFROM_TYPE_RETV ssize_t
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+#define SEND_TYPE_ARG1 int
+#define SEND_QUAL_ARG2 const
+#define SEND_TYPE_ARG2 void*
+#define SEND_TYPE_ARG3 size_t
+#define SEND_TYPE_ARG4 int
+#define SEND_TYPE_RETV ssize_t
+
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+/*#define RETSIGTYPE void*/
+
+/* Define to the type of arg 1 for `select'. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#define SELECT_TYPE_ARG234 (fd_set *)
+
+/* Define to the type of arg 5 for `select'. */
+#define SELECT_TYPE_ARG5 (struct timeval *)
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if you want to enable c-ares support */
+/* #undef USE_ARES */
+
+/* Define to disable non-blocking sockets */
+/* #undef USE_BLOCKING_SOCKETS */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if libSSH2 is in use */
+/*#define USE_LIBSSH2 1*/
+
+/* If you want to build curl with the built-in manual */
+/*#define USE_MANUAL 1*/
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+/*#define VERSION "7.18.2-CVS"*/
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* type to use in place of in_addr_t if not defined */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
+
+/* Enabling curl debug mode when building in Symbian debug mode would work */
+/* except that debug mode introduces new exports that must be frozen. */
+#ifdef _DEBUG
+/* #define CURLDEBUG */
+#endif
+
+/* sys/cdefs.h fails to define this for WINSCW prior to Symbian OS ver. 9.4 */
+#ifndef __LONG_LONG_SUPPORTED
+#define __LONG_LONG_SUPPORTED
+#endif
+
+/* Enable appropriate header only when zlib support is enabled */
+#ifdef HAVE_LIBZ
+#define HAVE_ZLIB_H 1
+#endif
+
+/* Enable appropriate definitions only when OpenSSL support is enabled */
+#ifdef USE_SSLEAY
+/* if OpenSSL is in use */
+#define USE_OPENSSL
+#endif
+
+#endif /* HEADER_CURL_CONFIG_SYMBIAN_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/config-tpf.h b/external/libcurl_android/jni/libcurl/lib/config-tpf.h
new file mode 100755
index 00000000..6ff701a9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-tpf.h
@@ -0,0 +1,772 @@
+#ifndef HEADER_CURL_CONFIG_TPF_H
+#define HEADER_CURL_CONFIG_TPF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for TPF */
+/* ================================================================ */
+
+/* ---------------------------------------------------------------- */
+/* FEATURES, FUNCTIONS, and DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* NOTE: Refer also to the .mak file for some of the flags below */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+/* #undef CURL_DISABLE_DICT */
+
+/* to disable FILE */
+/* #undef CURL_DISABLE_FILE */
+
+/* to disable FTP */
+/* #undef CURL_DISABLE_FTP */
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable LDAP */
+/* #undef CURL_DISABLE_LDAP */
+
+/* to disable TELNET */
+/* #undef CURL_DISABLE_TELNET */
+
+/* to disable TFTP */
+/* #undef CURL_DISABLE_TFTP */
+
+/* to disable verbose strings */
+/* #undef CURL_DISABLE_VERBOSE_STRINGS */
+
+/* lber dynamic library file */
+/* #undef DL_LBER_FILE */
+
+/* ldap dynamic library file */
+/* #undef DL_LDAP_FILE */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+/* #undef ENABLE_IPV6 */
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member */
+/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */
+
+/* Define to the type of arg 1 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG1 */
+
+/* Define to the type of arg 2 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG2 */
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG46 */
+
+/* Define to the type of arg 7 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG7 */
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/* #undef HAVE_ARPA_TFTP_H */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `basename' function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if you have the `closesocket' function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+#define HAVE_CRYPTO_H 1
+
+/* Define to 1 if you have the <des.h> header file. */
+/* #undef HAVE_DES_H */
+#define HAVE_DES_H 1
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+#define HAVE_ERR_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the `fork' function. */
+/* #undef HAVE_FORK */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if getaddrinfo exists and works */
+/* #undef HAVE_GETADDRINFO */
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* If you have gethostbyname */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 1 */
+
+/* Define to 1 if you have the getnameinfo function. */
+/* #undef HAVE_GETNAMEINFO */
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getprotobyname' function. */
+/* #undef HAVE_GETPROTOBYNAME */
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+/* #undef HAVE_GETRLIMIT */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* we have a glibc-style strerror_r() */
+/* #undef HAVE_GLIBC_STRERROR_R */
+#define HAVE_GLIBC_STRERROR_R 1
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the gssapi libraries */
+/* #undef HAVE_GSSAPI */
+
+/* if you have the GNU gssapi libraries */
+/* #undef HAVE_GSSGNU */
+
+/* if you have the Heimdal gssapi libraries */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have the MIT gssapi libraries */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `iconv' functions. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+/* #undef HAVE_INET_NTOP */
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+/* #undef HAVE_INET_PTON */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO
+ function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* if you have the Kerberos4 libraries (including -ldes) */
+/* #undef HAVE_KRB4 */
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
+
+/* Define to 1 if you have the <krb.h> header file. */
+/* #undef HAVE_KRB_H */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+/* #undef HAVE_LIBGEN_H 1 */
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+#define HAVE_LIBSSL 1
+
+/* if zlib is available */
+/* #undef HAVE_LIBZ */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+/* undef HAVE_NETINET_TCP_H */
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if NI_WITHSCOPEID exists and works */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* we have no strerror_r() proto */
+/* #undef HAVE_NO_STRERROR_R_DECL */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+#define HAVE_OPENSSL_CRYPTO_H 1
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+#define HAVE_OPENSSL_ENGINE_H 1
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+#define HAVE_OPENSSL_ERR_H 1
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+#define HAVE_OPENSSL_PEM_H 1
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+#define HAVE_OPENSSL_PKCS12_H 1
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+#define HAVE_OPENSSL_RSA_H 1
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+#define HAVE_OPENSSL_SSL_H 1
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+#define HAVE_OPENSSL_X509_H 1
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+#define HAVE_PEM_H 1
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `poll' function. */
+/* #undef HAVE_POLL */
+
+/* If you have a fine poll */
+/* #undef HAVE_POLL_FINE */
+
+/* we have a POSIX-style strerror_r() */
+/* #undef HAVE_POSIX_STRERROR_R */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+#define HAVE_RAND_EGD 1
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+#define HAVE_RAND_STATUS 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+#define HAVE_RSA_H 1
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+/* #undef HAVE_SETSOCKOPT */
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+/* #undef HAVE_SGTTY_H 1 */
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the `siginterrupt' function. */
+/* #undef HAVE_SIGINTERRUPT */
+
+/* Define to 1 if you have the `signal' function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* If you have sigsetjmp */
+/* #undef HAVE_SIGSETJMP */
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+#define HAVE_SSL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+#define HAVE_STRICMP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+/* #undef HAVE_STRLCPY */
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+/* #undef HAVE_STRUCT_SOCKADDR_STORAGE */
+
+/* Define this if you have struct timeval */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+/* #undef HAVE_SYS_POLL_H */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+/* #undef HAVE_TERMIOS_H */
+
+/* Define to 1 if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if you have the <winsock2.h> header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the <winsock.h> header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+/* #undef HAVE_WRITABLE_ARGV */
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+/* #undef HAVE_ZLIB_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* cpu-machine-OS */
+#define OS "s390x-ibm-tpf"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT \
+ "a suitable curl mailing list => http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type of arg 1 for `select'. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#define SELECT_TYPE_ARG234 (fd_set *)
+
+/* Define to the type of arg 5 for `select'. */
+#define SELECT_TYPE_ARG5 (struct timeval *)
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 8
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if you want to enable ares support */
+/* #undef USE_ARES */
+
+/* Define to disable non-blocking sockets */
+/* #undef USE_BLOCKING_SOCKETS */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* If you want to build curl with the built-in manual */
+/* #undef USE_MANUAL */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if SSL is enabled */
+/* #undef USE_SSLEAY */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Version number of package */
+#define VERSION "not-used"
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* type to use in place of in_addr_t if not defined */
+/* #undef in_addr_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
+
+/* Define to 1 if you have the getnameinfo function. */
+/* #undef HAVE_GETNAMEINFO 1 */
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+/* #undef GETNAMEINFO_QUAL_ARG1 const */
+
+/* Define to the type of arg 1 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG1 struct sockaddr * */
+
+/* Define to the type of arg 2 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG2 socklen_t */
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG46 size_t */
+
+/* Define to the type of arg 7 for getnameinfo. */
+/* #undef GETNAMEINFO_TYPE_ARG7 int */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define to 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+#define CURL_DOES_CONVERSIONS
+#ifndef CURL_ICONV_CODESET_OF_HOST
+#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
+#endif
+
+
+#endif /* HEADER_CURL_CONFIG_TPF_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/config-vxworks.h b/external/libcurl_android/jni/libcurl/lib/config-vxworks.h
new file mode 100755
index 00000000..05220b58
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-vxworks.h
@@ -0,0 +1,931 @@
+#ifndef HEADER_CURL_CONFIG_VXWORKS_H
+#define HEADER_CURL_CONFIG_VXWORKS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* =============================================================== */
+/* Hand crafted config file for VxWorks */
+/* =============================================================== */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+/* #undef CURL_DISABLE_DICT */
+
+/* to disable FILE */
+/* #undef CURL_DISABLE_FILE */
+
+/* to disable FTP */
+#define CURL_DISABLE_FTP 1
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable NTLM authentication */
+#define CURL_DISABLE_NTLM 1
+
+/* to disable proxies */
+/* #undef CURL_DISABLE_PROXY */
+
+/* to disable TELNET */
+#define CURL_DISABLE_TELNET 1
+
+/* to disable TFTP */
+#define CURL_DISABLE_TFTP 1
+
+/* to disable verbose strings */
+/* #undef CURL_DISABLE_VERBOSE_STRINGS */
+
+/* Definition to make a library symbol externally visible. */
+/* #undef CURL_EXTERN_SYMBOL */
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+#define ENABLE_IPV6 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 unsigned int
+
+/* Specifies the number of arguments to getservbyport_r */
+#define GETSERVBYPORT_R_ARGS 6
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+#define GETSERVBYPORT_R_BUFSIZE 4096
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/* #undef HAVE_ARPA_TFTP_H */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `basename' function. */
+/* #undef HAVE_BASENAME */
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */
+
+/* Define to 1 if you have the `closesocket' function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <des.h> header file. */
+/* #undef HAVE_DES_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+#define HAVE_FREEIFADDRS 1
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `geteuid' function. */
+/* #undef HAVE_GETEUID */
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+#define HAVE_GETHOSTBYADDR_R 1
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+#define HAVE_GETHOSTBYADDR_R_8 1
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+/* #undef HAVE_GETHOSTBYNAME_R */
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+/* #undef HAVE_GETHOSTBYNAME_R_6 */
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+/* #undef HAVE_GETIFADDRS */
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+/* #undef HAVE_GETPWUID */
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+/* #undef HAVE_GETSERVBYPORT_R */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+/* #undef HAVE_GETTIMEOFDAY */
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the gssapi libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have the GNU gssapi libraries */
+/* #undef HAVE_GSSGNU */
+
+/* if you have the Heimdal gssapi libraries */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have the MIT gssapi libraries */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+/* #undef HAVE_IFADDRS_H */
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+/* #undef HAVE_INET_NTOP */
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+/* #undef HAVE_INET_PTON */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* if you have the Kerberos4 libraries (including -ldes) */
+/* #undef HAVE_KRB4 */
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
+
+/* Define to 1 if you have the <krb.h> header file. */
+/* #undef HAVE_KRB_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Use LDAPS implementation */
+/* #undef HAVE_LDAP_SSL */
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+/* #undef HAVE_LIBGEN_H */
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `libssh2_version' function. */
+/* #undef HAVE_LIBSSH2_VERSION */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#define HAVE_LIBSSL 1
+
+/* if zlib is available */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+/* #undef HAVE_MSG_NOSIGNAL */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+#define HAVE_OPENSSL_CRYPTO_H 1
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+#define HAVE_OPENSSL_ENGINE_H 1
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+#define HAVE_OPENSSL_ERR_H 1
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+#define HAVE_OPENSSL_PEM_H 1
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+#define HAVE_OPENSSL_PKCS12_H 1
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#define HAVE_OPENSSL_RSA_H 1
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#define HAVE_OPENSSL_SSL_H 1
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+#define HAVE_OPENSSL_X509_H 1
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+/* #undef HAVE_POLL */
+
+/* If you have a fine poll */
+/* #undef HAVE_POLL_FINE */
+
+/* Define to 1 if you have the <poll.h> header file. */
+/* #undef HAVE_POLL_H */
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+/* #undef HAVE_POSIX_STRERROR_R */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+/* #undef HAVE_PWD_H */
+
+/* Define to 1 if you have the `RAND_egd' function. */
+#define HAVE_RAND_EGD 1
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+#define HAVE_RAND_STATUS 1
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+#define HAVE_SETMODE 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+/* #undef HAVE_SGTTY_H */
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+#define HAVE_SIGNAL 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+/* #undef HAVE_SIGSETJMP */
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+#define HAVE_SSL_GET_SHUTDOWN 1
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+/* #undef HAVE_STRLCPY */
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+/* #undef HAVE_STRTOLL */
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+/* #undef HAVE_SYS_FILIO_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+/* #undef HAVE_SYS_PARAM_H */
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+/* #undef HAVE_SYS_POLL_H */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+/* #undef HAVE_SYS_SELECT_H */
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/* #undef HAVE_SYS_TIME_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+#define HAVE_TERMIO_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have a working vxworks-style strerror_r function. */
+#define HAVE_VXWORKS_STRERROR_R 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#define HAVE_WRITABLE_ARGV 1
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+#define HAVE_ZLIB_H 1
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to 1 if the open function requires three arguments. */
+#define OPEN_NEEDS_ARG3 1
+
+/* cpu-machine-OS */
+#define OS "unknown-unknown-vxworks"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* a suitable file to read random data from */
+#define RANDOM_FILE "/dev/urandom"
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 void
+
+/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
+/* #undef RECVFROM_TYPE_ARG5_IS_VOID */
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 socklen_t
+
+/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
+/* #undef RECVFROM_TYPE_ARG6_IS_VOID */
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 4
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+/* #undef STRERROR_R_TYPE_ARG3 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* #undef TIME_WITH_SYS_TIME */
+
+/* Define if you want to enable c-ares support */
+/* #undef USE_ARES */
+
+/* Define to disable non-blocking sockets. */
+/* #undef USE_BLOCKING_SOCKETS */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* if OpenSSL is in use */
+#define USE_OPENSSL 1
+
+/* if SSL is enabled */
+#define USE_SSLEAY 1
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
+
+#endif /* HEADER_CURL_CONFIG_VXWORKS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/config-win32.h b/external/libcurl_android/jni/libcurl/lib/config-win32.h
new file mode 100755
index 00000000..62bbedca
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-win32.h
@@ -0,0 +1,698 @@
+#ifndef HEADER_CURL_CONFIG_WIN32_H
+#define HEADER_CURL_CONFIG_WIN32_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* Hand crafted config file for Windows */
+/* ================================================================ */
+
+/* ---------------------------------------------------------------- */
+/* HEADER FILES */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the <arpa/inet.h> header file. */
+/* #define HAVE_ARPA_INET_H 1 */
+
+/* Define if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define if you have the <crypto.h> header file. */
+/* #define HAVE_CRYPTO_H 1 */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <err.h> header file. */
+/* #define HAVE_ERR_H 1 */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <getopt.h> header file. */
+#if defined(__MINGW32__) || defined(__POCC__)
+#define HAVE_GETOPT_H 1
+#endif
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+#define HAVE_INTTYPES_H 1
+#endif
+
+/* Define if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you need <malloc.h> header even with <stdlib.h> header file. */
+#if !defined(__SALFORDC__) && !defined(__POCC__)
+#define NEED_MALLOC_H 1
+#endif
+
+/* Define if you have the <netdb.h> header file. */
+/* #define HAVE_NETDB_H 1 */
+
+/* Define if you have the <netinet/in.h> header file. */
+/* #define HAVE_NETINET_IN_H 1 */
+
+/* Define if you have the <process.h> header file. */
+#ifndef __SALFORDC__
+#define HAVE_PROCESS_H 1
+#endif
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define if you have the <sgtty.h> header file. */
+/* #define HAVE_SGTTY_H 1 */
+
+/* Define if you have the <ssl.h> header file. */
+/* #define HAVE_SSL_H 1 */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+#define HAVE_STDBOOL_H 1
+#endif
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+/* #define HAVE_SYS_PARAM_H 1 */
+
+/* Define if you have the <sys/select.h> header file. */
+/* #define HAVE_SYS_SELECT_H 1 */
+
+/* Define if you have the <sys/socket.h> header file. */
+/* #define HAVE_SYS_SOCKET_H 1 */
+
+/* Define if you have the <sys/sockio.h> header file. */
+/* #define HAVE_SYS_SOCKIO_H 1 */
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+/* #define HAVE_SYS_TIME_H 1 */
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <sys/utime.h> header file. */
+#ifndef __BORLANDC__
+#define HAVE_SYS_UTIME_H 1
+#endif
+
+/* Define if you have the <termio.h> header file. */
+/* #define HAVE_TERMIO_H 1 */
+
+/* Define if you have the <termios.h> header file. */
+/* #define HAVE_TERMIOS_H 1 */
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) || \
+ defined(__POCC__)
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define if you have the <windows.h> header file. */
+#define HAVE_WINDOWS_H 1
+
+/* Define if you have the <winsock.h> header file. */
+#define HAVE_WINSOCK_H 1
+
+/* Define if you have the <winsock2.h> header file. */
+#ifndef __SALFORDC__
+#define HAVE_WINSOCK2_H 1
+#endif
+
+/* Define if you have the <ws2tcpip.h> header file. */
+#ifndef __SALFORDC__
+#define HAVE_WS2TCPIP_H 1
+#endif
+
+/* ---------------------------------------------------------------- */
+/* OTHER HEADER INFO */
+/* ---------------------------------------------------------------- */
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* Define to 1 if bool is an available type. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+#define HAVE_BOOL_T 1
+#endif
+
+/* ---------------------------------------------------------------- */
+/* FUNCTIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the closesocket function. */
+#define HAVE_CLOSESOCKET 1
+
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #define HAVE_DOPRNT 1 */
+
+/* Define if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the getpass function. */
+/* #define HAVE_GETPASS 1 */
+
+/* Define if you have the getservbyname function. */
+#define HAVE_GETSERVBYNAME 1
+
+/* Define if you have the getprotobyname function. */
+#define HAVE_GETPROTOBYNAME
+
+/* Define if you have the gettimeofday function. */
+/* #define HAVE_GETTIMEOFDAY 1 */
+
+/* Define if you have the inet_addr function. */
+#define HAVE_INET_ADDR 1
+
+/* Define if you have the ioctlsocket function. */
+#define HAVE_IOCTLSOCKET 1
+
+/* Define if you have a working ioctlsocket FIONBIO function. */
+#define HAVE_IOCTLSOCKET_FIONBIO 1
+
+/* Define if you have the perror function. */
+#define HAVE_PERROR 1
+
+/* Define if you have the RAND_screen function when using SSL. */
+#define HAVE_RAND_SCREEN 1
+
+/* Define if you have the `RAND_status' function when using SSL. */
+#define HAVE_RAND_STATUS 1
+
+/* Define if you have the `CRYPTO_cleanup_all_ex_data' function.
+ This is present in OpenSSL versions after 0.9.6b */
+#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
+/* Define if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setmode function. */
+#define HAVE_SETMODE 1
+
+/* Define if you have the setvbuf function. */
+#define HAVE_SETVBUF 1
+
+/* Define if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strcasecmp function. */
+/* #define HAVE_STRCASECMP 1 */
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the stricmp function. */
+#define HAVE_STRICMP 1
+
+/* Define if you have the strncasecmp function. */
+/* #define HAVE_STRNCASECMP 1 */
+
+/* Define if you have the strnicmp function. */
+#define HAVE_STRNICMP 1
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtoll function. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__POCC__) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1800))
+#define HAVE_STRTOLL 1
+#endif
+
+/* Define if you have the tcgetattr function. */
+/* #define HAVE_TCGETATTR 1 */
+
+/* Define if you have the tcsetattr function. */
+/* #define HAVE_TCSETATTR 1 */
+
+/* Define if you have the utime function. */
+#ifndef __BORLANDC__
+#define HAVE_UTIME 1
+#endif
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 DWORD
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 SOCKET
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 SOCKET
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 SOCKET
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* ---------------------------------------------------------------- */
+/* TYPEDEF REPLACEMENTS */
+/* ---------------------------------------------------------------- */
+
+/* Define if in_addr_t is not an available 'typedefed' type. */
+#define in_addr_t unsigned long
+
+/* Define to the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define if ssize_t is not an available 'typedefed' type. */
+#ifndef _SSIZE_T_DEFINED
+# if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || \
+ defined(__POCC__) || \
+ defined(__MINGW32__)
+# elif defined(_WIN64)
+# define _SSIZE_T_DEFINED
+# define ssize_t __int64
+# else
+# define _SSIZE_T_DEFINED
+# define ssize_t int
+# endif
+#endif
+
+/* ---------------------------------------------------------------- */
+/* TYPE SIZES */
+/* ---------------------------------------------------------------- */
+
+/* Define to the size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* Define to the size of `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 16
+
+/* Define to the size of `long long', as computed by sizeof. */
+/* #define SIZEOF_LONG_LONG 8 */
+
+/* Define to the size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* Define to the size of `size_t', as computed by sizeof. */
+#if defined(_WIN64)
+# define SIZEOF_SIZE_T 8
+#else
+# define SIZEOF_SIZE_T 4
+#endif
+
+/* ---------------------------------------------------------------- */
+/* BSD-style lwIP TCP/IP stack SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+/* Define to use BSD-style lwIP TCP/IP stack. */
+/* #define USE_LWIPSOCK 1 */
+
+#ifdef USE_LWIPSOCK
+# undef USE_WINSOCK
+# undef HAVE_WINSOCK_H
+# undef HAVE_WINSOCK2_H
+# undef HAVE_WS2TCPIP_H
+# undef HAVE_ERRNO_H
+# undef HAVE_GETHOSTNAME
+# undef HAVE_GETNAMEINFO
+# undef LWIP_POSIX_SOCKETS_IO_NAMES
+# undef RECV_TYPE_ARG1
+# undef RECV_TYPE_ARG3
+# undef SEND_TYPE_ARG1
+# undef SEND_TYPE_ARG3
+# define HAVE_FREEADDRINFO
+# define HAVE_GETADDRINFO
+# define HAVE_GETHOSTBYNAME
+# define HAVE_GETHOSTBYNAME_R
+# define HAVE_GETHOSTBYNAME_R_6
+# define LWIP_POSIX_SOCKETS_IO_NAMES 0
+# define RECV_TYPE_ARG1 int
+# define RECV_TYPE_ARG3 size_t
+# define SEND_TYPE_ARG1 int
+# define SEND_TYPE_ARG3 size_t
+#endif
+
+/* ---------------------------------------------------------------- */
+/* Watt-32 tcp/ip SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+#ifdef USE_WATT32
+ #include <tcp.h>
+ #undef byte
+ #undef word
+ #undef USE_WINSOCK
+ #undef HAVE_WINSOCK_H
+ #undef HAVE_WINSOCK2_H
+ #undef HAVE_WS2TCPIP_H
+ #define HAVE_GETADDRINFO
+ #define HAVE_GETNAMEINFO
+ #define HAVE_SYS_IOCTL_H
+ #define HAVE_SYS_SOCKET_H
+ #define HAVE_NETINET_IN_H
+ #define HAVE_NETDB_H
+ #define HAVE_ARPA_INET_H
+ #define HAVE_FREEADDRINFO
+ #define SOCKET int
+#endif
+
+
+/* ---------------------------------------------------------------- */
+/* COMPILER SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+/* Define to nothing if compiler does not support 'const' qualifier. */
+/* #define const */
+
+/* Define to nothing if compiler does not support 'volatile' qualifier. */
+/* #define volatile */
+
+/* Windows should not have HAVE_GMTIME_R defined */
+/* #undef HAVE_GMTIME_R */
+
+/* Define if the compiler supports C99 variadic macro style. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define HAVE_VARIADIC_MACROS_C99 1
+#endif
+
+/* Define if the compiler supports the 'long long' data type. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1310))
+#define HAVE_LONGLONG 1
+#endif
+
+/* Define to avoid VS2005 complaining about portable C functions. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+
+/* VS2005 and later dafault size for time_t is 64-bit, unless
+ _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+# ifndef _USE_32BIT_TIME_T
+# define SIZEOF_TIME_T 8
+# else
+# define SIZEOF_TIME_T 4
+# endif
+#endif
+
+/* Officially, Microsoft's Windows SDK versions 6.X do not support Windows
+ 2000 as a supported build target. VS2008 default installations provide
+ an embedded Windows SDK v6.0A along with the claim that Windows 2000 is
+ a valid build target for VS2008. Popular belief is that binaries built
+ with VS2008 using Windows SDK versions 6.X and Windows 2000 as a build
+ target are functional. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+# define VS2008_MIN_TARGET 0x0500
+#endif
+
+/* When no build target is specified VS2008 default build target is Windows
+ Vista, which leaves out even Winsows XP. If no build target has been given
+ for VS2008 we will target the minimum Officially supported build target,
+ which happens to be Windows XP. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+# define VS2008_DEF_TARGET 0x0501
+#endif
+
+/* VS2008 default target settings and minimum build target check. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT VS2008_DEF_TARGET
+# endif
+# ifndef WINVER
+# define WINVER VS2008_DEF_TARGET
+# endif
+# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET)
+# error VS2008 does not support Windows build targets prior to Windows 2000
+# endif
+#endif
+
+/* When no build target is specified Pelles C 5.00 and later default build
+ target is Windows Vista. We override default target to be Windows 2000. */
+#if defined(__POCC__) && (__POCC__ >= 500)
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0500
+# endif
+# ifndef WINVER
+# define WINVER 0x0500
+# endif
+#endif
+
+/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is
+ quite convoluted, compiler dependent and even build target dependent. */
+#if defined(HAVE_WS2TCPIP_H)
+# if defined(__POCC__)
+# define HAVE_FREEADDRINFO 1
+# define HAVE_GETADDRINFO 1
+# define HAVE_GETADDRINFO_THREADSAFE 1
+# define HAVE_GETNAMEINFO 1
+# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
+# define HAVE_FREEADDRINFO 1
+# define HAVE_GETADDRINFO 1
+# define HAVE_GETADDRINFO_THREADSAFE 1
+# define HAVE_GETNAMEINFO 1
+# elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+# define HAVE_FREEADDRINFO 1
+# define HAVE_GETADDRINFO 1
+# define HAVE_GETADDRINFO_THREADSAFE 1
+# define HAVE_GETNAMEINFO 1
+# endif
+#endif
+
+#if defined(__POCC__)
+# ifndef _MSC_VER
+# error Microsoft extensions /Ze compiler option is required
+# endif
+# ifndef __POCC__OLDNAMES
+# error Compatibility names /Go compiler option is required
+# endif
+#endif
+
+/* ---------------------------------------------------------------- */
+/* STRUCT RELATED */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have struct sockaddr_storage. */
+#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+#endif
+
+/* Define if you have struct timeval. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+#if HAVE_WINSOCK2_H && defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+#define HAVE_STRUCT_POLLFD 1
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LARGE FILE SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#if defined(_MSC_VER) && !defined(_WIN32_WCE)
+# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define USE_WIN32_LARGE_FILES
+# else
+# define USE_WIN32_SMALL_FILES
+# endif
+#endif
+
+#if defined(__MINGW32__) && !defined(USE_WIN32_LARGE_FILES)
+# define USE_WIN32_LARGE_FILES
+#endif
+
+#if defined(__WATCOMC__) && !defined(USE_WIN32_LARGE_FILES)
+# define USE_WIN32_LARGE_FILES
+#endif
+
+#if defined(__POCC__)
+# undef USE_WIN32_LARGE_FILES
+#endif
+
+#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
+# define USE_WIN32_SMALL_FILES
+#endif
+
+/* ---------------------------------------------------------------- */
+/* DNS RESOLVER SPECIALTY */
+/* ---------------------------------------------------------------- */
+
+/*
+ * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS.
+ */
+
+/* Define to enable c-ares asynchronous DNS lookups. */
+/* #define USE_ARES 1 */
+
+/* Default define to enable threaded asynchronous DNS lookups. */
+#if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \
+ !defined(USE_THREADS_WIN32)
+# define USE_THREADS_WIN32 1
+#endif
+
+#if defined(USE_ARES) && defined(USE_THREADS_WIN32)
+# error "Only one DNS lookup specialty may be defined at most"
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LDAP SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#if defined(CURL_HAS_NOVELL_LDAPSDK) || defined(CURL_HAS_MOZILLA_LDAPSDK)
+#undef CURL_LDAP_WIN
+#define HAVE_LDAP_SSL_H 1
+#define HAVE_LDAP_URL_PARSE 1
+#elif defined(CURL_HAS_OPENLDAP_LDAPSDK)
+#undef CURL_LDAP_WIN
+#define HAVE_LDAP_URL_PARSE 1
+#else
+#undef HAVE_LDAP_URL_PARSE
+#define CURL_LDAP_WIN 1
+#endif
+
+#if defined(__WATCOMC__) && defined(CURL_LDAP_WIN)
+#if __WATCOMC__ < 1280
+#define WINBERAPI __declspec(cdecl)
+#define WINLDAPAPI __declspec(cdecl)
+#endif
+#endif
+
+#if defined(__POCC__) && defined(CURL_LDAP_WIN)
+# define CURL_DISABLE_LDAP 1
+#endif
+
+/* ---------------------------------------------------------------- */
+/* ADDITIONAL DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define cpu-machine-OS */
+#undef OS
+#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */
+#define OS "i386-pc-win32"
+#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */
+#define OS "x86_64-pc-win32"
+#elif defined(_M_IA64) /* Itanium */
+#define OS "ia64-pc-win32"
+#else
+#define OS "unknown-pc-win32"
+#endif
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
+#if defined(__POCC__) || (USE_IPV6)
+# define ENABLE_IPV6 1
+#endif
+
+#endif /* HEADER_CURL_CONFIG_WIN32_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/config-win32ce.h b/external/libcurl_android/jni/libcurl/lib/config-win32ce.h
new file mode 100755
index 00000000..a8ab0d34
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/config-win32ce.h
@@ -0,0 +1,448 @@
+#ifndef HEADER_CURL_CONFIG_WIN32CE_H
+#define HEADER_CURL_CONFIG_WIN32CE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* ================================================================ */
+/* lib/config-win32ce.h - Hand crafted config file for windows ce */
+/* ================================================================ */
+
+/* ---------------------------------------------------------------- */
+/* HEADER FILES */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the <arpa/inet.h> header file. */
+/* #define HAVE_ARPA_INET_H 1 */
+
+/* Define if you have the <assert.h> header file. */
+/* #define HAVE_ASSERT_H 1 */
+
+/* Define if you have the <crypto.h> header file. */
+/* #define HAVE_CRYPTO_H 1 */
+
+/* Define if you have the <errno.h> header file. */
+/* #define HAVE_ERRNO_H 1 */
+
+/* Define if you have the <err.h> header file. */
+/* #define HAVE_ERR_H 1 */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <getopt.h> header file. */
+/* #define HAVE_GETOPT_H 1 */
+
+/* Define if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you need the malloc.h header header file even with stdlib.h */
+#define NEED_MALLOC_H 1
+
+/* Define if you have the <netdb.h> header file. */
+/* #define HAVE_NETDB_H 1 */
+
+/* Define if you have the <netinet/in.h> header file. */
+/* #define HAVE_NETINET_IN_H 1 */
+
+/* Define if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define if you have the <sgtty.h> header file. */
+/* #define HAVE_SGTTY_H 1 */
+
+/* Define if you have the <ssl.h> header file. */
+/* #define HAVE_SSL_H 1 */
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <process.h> header file. */
+/* #define HAVE_PROCESS_H 1 */
+
+/* Define if you have the <sys/param.h> header file. */
+/* #define HAVE_SYS_PARAM_H 1 */
+
+/* Define if you have the <sys/select.h> header file. */
+/* #define HAVE_SYS_SELECT_H 1 */
+
+/* Define if you have the <sys/socket.h> header file. */
+/* #define HAVE_SYS_SOCKET_H 1 */
+
+/* Define if you have the <sys/sockio.h> header file. */
+/* #define HAVE_SYS_SOCKIO_H 1 */
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/time.h> header file */
+/* #define HAVE_SYS_TIME_H 1 */
+
+/* Define if you have the <sys/types.h> header file. */
+/* #define HAVE_SYS_TYPES_H 1 */
+
+/* Define if you have the <sys/utime.h> header file */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define if you have the <termio.h> header file. */
+/* #define HAVE_TERMIO_H 1 */
+
+/* Define if you have the <termios.h> header file. */
+/* #define HAVE_TERMIOS_H 1 */
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__)
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define if you have the <windows.h> header file. */
+#define HAVE_WINDOWS_H 1
+
+/* Define if you have the <winsock.h> header file. */
+#define HAVE_WINSOCK_H 1
+
+/* Define if you have the <winsock2.h> header file. */
+/* #define HAVE_WINSOCK2_H 1 */
+
+/* Define if you have the <ws2tcpip.h> header file. */
+/* #define HAVE_WS2TCPIP_H 1 */
+
+/* ---------------------------------------------------------------- */
+/* OTHER HEADER INFO */
+/* ---------------------------------------------------------------- */
+
+/* Define if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* ---------------------------------------------------------------- */
+/* FUNCTIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define if you have the closesocket function. */
+#define HAVE_CLOSESOCKET 1
+
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #define HAVE_DOPRNT 1 */
+
+/* Define if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the getpass function. */
+/* #define HAVE_GETPASS 1 */
+
+/* Define if you have the getservbyname function. */
+#define HAVE_GETSERVBYNAME 1
+
+/* Define if you have the gettimeofday function. */
+/* #define HAVE_GETTIMEOFDAY 1 */
+
+/* Define if you have the inet_addr function. */
+#define HAVE_INET_ADDR 1
+
+/* Define if you have the ioctlsocket function. */
+#define HAVE_IOCTLSOCKET 1
+
+/* Define if you have a working ioctlsocket FIONBIO function. */
+#define HAVE_IOCTLSOCKET_FIONBIO 1
+
+/* Define if you have the perror function. */
+#define HAVE_PERROR 1
+
+/* Define if you have the RAND_screen function when using SSL */
+#define HAVE_RAND_SCREEN 1
+
+/* Define if you have the `RAND_status' function when using SSL. */
+#define HAVE_RAND_STATUS 1
+
+/* Define if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the setvbuf function. */
+#define HAVE_SETVBUF 1
+
+/* Define if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define if you have the strcasecmp function. */
+/* #define HAVE_STRCASECMP 1 */
+
+/* Define if you have the strdup function. */
+/* #define HAVE_STRDUP 1 */
+
+/* Define if you have the strftime function. */
+/* #define HAVE_STRFTIME 1 */
+
+/* Define if you have the stricmp function. */
+/* #define HAVE_STRICMP 1 */
+
+/* Define if you have the strncasecmp function. */
+/* #define HAVE_STRNCASECMP 1 */
+
+/* Define if you have the strnicmp function. */
+/* #define HAVE_STRNICMP 1 */
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtoll function. */
+#if defined(__MINGW32__) || defined(__WATCOMC__)
+#define HAVE_STRTOLL 1
+#endif
+
+/* Define if you have the tcgetattr function. */
+/* #define HAVE_TCGETATTR 1 */
+
+/* Define if you have the tcsetattr function. */
+/* #define HAVE_TCSETATTR 1 */
+
+/* Define if you have the utime function */
+#define HAVE_UTIME 1
+
+/* Define if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 DWORD
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Define if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 SOCKET
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 SOCKET
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 char
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 int
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV int
+
+/* Define if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 SOCKET
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 char *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 int
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* ---------------------------------------------------------------- */
+/* TYPEDEF REPLACEMENTS */
+/* ---------------------------------------------------------------- */
+
+/* Define this if in_addr_t is not an available 'typedefed' type */
+#define in_addr_t unsigned long
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define ssize_t if it is not an available 'typedefed' type */
+#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__)
+#elif defined(_WIN64)
+#define ssize_t __int64
+#else
+#define ssize_t int
+#endif
+
+/* ---------------------------------------------------------------- */
+/* TYPE SIZES */
+/* ---------------------------------------------------------------- */
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 16
+
+/* The size of `long long', as computed by sizeof. */
+/* #define SIZEOF_LONG_LONG 8 */
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#if defined(_WIN64)
+# define SIZEOF_SIZE_T 8
+#else
+# define SIZEOF_SIZE_T 4
+#endif
+
+/* ---------------------------------------------------------------- */
+/* STRUCT RELATED */
+/* ---------------------------------------------------------------- */
+
+/* Define this if you have struct sockaddr_storage */
+/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */
+
+/* Define this if you have struct timeval */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define this if struct sockaddr_in6 has the sin6_scope_id member */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* ---------------------------------------------------------------- */
+/* COMPILER SPECIFIC */
+/* ---------------------------------------------------------------- */
+
+/* Undef keyword 'const' if it does not work. */
+/* #undef const */
+
+/* Define to avoid VS2005 complaining about portable C functions */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+
+/* VS2005 and later dafault size for time_t is 64-bit, unless */
+/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+# ifndef _USE_32BIT_TIME_T
+# define SIZEOF_TIME_T 8
+# else
+# define SIZEOF_TIME_T 4
+# endif
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LARGE FILE SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#if defined(_MSC_VER) && !defined(_WIN32_WCE)
+# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define USE_WIN32_LARGE_FILES
+# else
+# define USE_WIN32_SMALL_FILES
+# endif
+#endif
+
+#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
+# define USE_WIN32_SMALL_FILES
+#endif
+
+/* ---------------------------------------------------------------- */
+/* LDAP SUPPORT */
+/* ---------------------------------------------------------------- */
+
+#define CURL_LDAP_WIN 1
+#undef HAVE_LDAP_URL_PARSE
+
+/* ---------------------------------------------------------------- */
+/* ADDITIONAL DEFINITIONS */
+/* ---------------------------------------------------------------- */
+
+/* Define cpu-machine-OS */
+#undef OS
+#define OS "i386-pc-win32ce"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* ---------------------------------------------------------------- */
+/* WinCE */
+/* ---------------------------------------------------------------- */
+
+#ifndef UNICODE
+# define UNICODE
+#endif
+
+#ifndef _UNICODE
+# define _UNICODE
+#endif
+
+#define CURL_DISABLE_FILE 1
+#define CURL_DISABLE_TELNET 1
+#define CURL_DISABLE_LDAP 1
+
+#define ENOSPC 1
+#define ENOMEM 2
+#define EAGAIN 3
+
+extern int stat(const char *path,struct stat *buffer );
+
+#endif /* HEADER_CURL_CONFIG_WIN32CE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/conncache.c b/external/libcurl_android/jni/libcurl/lib/conncache.c
new file mode 100755
index 00000000..5bbcf3c8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/conncache.c
@@ -0,0 +1,283 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "url.h"
+#include "progress.h"
+#include "multiif.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "bundles.h"
+#include "conncache.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static void free_bundle_hash_entry(void *freethis)
+{
+ struct connectbundle *b = (struct connectbundle *) freethis;
+
+ Curl_bundle_destroy(b);
+}
+
+struct conncache *Curl_conncache_init(int size)
+{
+ struct conncache *connc;
+
+ connc = calloc(1, sizeof(struct conncache));
+ if(!connc)
+ return NULL;
+
+ connc->hash = Curl_hash_alloc(size, Curl_hash_str,
+ Curl_str_key_compare, free_bundle_hash_entry);
+
+ if(!connc->hash) {
+ free(connc);
+ return NULL;
+ }
+
+ return connc;
+}
+
+void Curl_conncache_destroy(struct conncache *connc)
+{
+ if(connc) {
+ Curl_hash_destroy(connc->hash);
+ connc->hash = NULL;
+ free(connc);
+ }
+}
+
+struct connectbundle *Curl_conncache_find_bundle(struct conncache *connc,
+ char *hostname)
+{
+ struct connectbundle *bundle = NULL;
+
+ if(connc)
+ bundle = Curl_hash_pick(connc->hash, hostname, strlen(hostname)+1);
+
+ return bundle;
+}
+
+static bool conncache_add_bundle(struct conncache *connc,
+ char *hostname,
+ struct connectbundle *bundle)
+{
+ void *p;
+
+ p = Curl_hash_add(connc->hash, hostname, strlen(hostname)+1, bundle);
+
+ return p?TRUE:FALSE;
+}
+
+static void conncache_remove_bundle(struct conncache *connc,
+ struct connectbundle *bundle)
+{
+ struct curl_hash_iterator iter;
+ struct curl_hash_element *he;
+
+ if(!connc)
+ return;
+
+ Curl_hash_start_iterate(connc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ if(he->ptr == bundle) {
+ /* The bundle is destroyed by the hash destructor function,
+ free_bundle_hash_entry() */
+ Curl_hash_delete(connc->hash, he->key, he->key_len);
+ return;
+ }
+
+ he = Curl_hash_next_element(&iter);
+ }
+}
+
+CURLcode Curl_conncache_add_conn(struct conncache *connc,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ struct connectbundle *bundle;
+ struct connectbundle *new_bundle = NULL;
+ struct SessionHandle *data = conn->data;
+
+ bundle = Curl_conncache_find_bundle(data->state.conn_cache,
+ conn->host.name);
+ if(!bundle) {
+ result = Curl_bundle_create(data, &new_bundle);
+ if(result != CURLE_OK)
+ return result;
+
+ if(!conncache_add_bundle(data->state.conn_cache,
+ conn->host.name, new_bundle)) {
+ Curl_bundle_destroy(new_bundle);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ bundle = new_bundle;
+ }
+
+ result = Curl_bundle_add_conn(bundle, conn);
+ if(result != CURLE_OK) {
+ if(new_bundle)
+ conncache_remove_bundle(data->state.conn_cache, new_bundle);
+ return result;
+ }
+
+ conn->connection_id = connc->next_connection_id++;
+ connc->num_connections++;
+
+ return CURLE_OK;
+}
+
+void Curl_conncache_remove_conn(struct conncache *connc,
+ struct connectdata *conn)
+{
+ struct connectbundle *bundle = conn->bundle;
+
+ /* The bundle pointer can be NULL, since this function can be called
+ due to a failed connection attempt, before being added to a bundle */
+ if(bundle) {
+ Curl_bundle_remove_conn(bundle, conn);
+ if(bundle->num_connections == 0) {
+ conncache_remove_bundle(connc, bundle);
+ }
+
+ if(connc) {
+ connc->num_connections--;
+
+ DEBUGF(infof(conn->data, "The cache now contains %d members\n",
+ connc->num_connections));
+ }
+ }
+}
+
+/* This function iterates the entire connection cache and calls the
+ function func() with the connection pointer as the first argument
+ and the supplied 'param' argument as the other,
+
+ Return 0 from func() to continue the loop, return 1 to abort it.
+ */
+void Curl_conncache_foreach(struct conncache *connc,
+ void *param,
+ int (*func)(struct connectdata *conn, void *param))
+{
+ struct curl_hash_iterator iter;
+ struct curl_llist_element *curr;
+ struct curl_hash_element *he;
+
+ if(!connc)
+ return;
+
+ Curl_hash_start_iterate(connc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ struct connectbundle *bundle;
+ struct connectdata *conn;
+
+ bundle = he->ptr;
+ he = Curl_hash_next_element(&iter);
+
+ curr = bundle->conn_list->head;
+ while(curr) {
+ /* Yes, we need to update curr before calling func(), because func()
+ might decide to remove the connection */
+ conn = curr->ptr;
+ curr = curr->next;
+
+ if(1 == func(conn, param))
+ return;
+ }
+ }
+}
+
+/* Return the first connection found in the cache. Used when closing all
+ connections */
+struct connectdata *
+Curl_conncache_find_first_connection(struct conncache *connc)
+{
+ struct curl_hash_iterator iter;
+ struct curl_llist_element *curr;
+ struct curl_hash_element *he;
+ struct connectbundle *bundle;
+
+ Curl_hash_start_iterate(connc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ bundle = he->ptr;
+
+ curr = bundle->conn_list->head;
+ if(curr) {
+ return curr->ptr;
+ }
+
+ he = Curl_hash_next_element(&iter);
+ }
+
+ return NULL;
+}
+
+
+#if 0
+/* Useful for debugging the connection cache */
+void Curl_conncache_print(struct conncache *connc)
+{
+ struct curl_hash_iterator iter;
+ struct curl_llist_element *curr;
+ struct curl_hash_element *he;
+
+ if(!connc)
+ return;
+
+ fprintf(stderr, "=Bundle cache=\n");
+
+ Curl_hash_start_iterate(connc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ struct connectbundle *bundle;
+ struct connectdata *conn;
+
+ bundle = he->ptr;
+
+ fprintf(stderr, "%s -", he->key);
+ curr = bundle->conn_list->head;
+ while(curr) {
+ conn = curr->ptr;
+
+ fprintf(stderr, " [%p %d]", (void *)conn, conn->inuse);
+ curr = curr->next;
+ }
+ fprintf(stderr, "\n");
+
+ he = Curl_hash_next_element(&iter);
+ }
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/conncache.h b/external/libcurl_android/jni/libcurl/lib/conncache.h
new file mode 100755
index 00000000..d793f248
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/conncache.h
@@ -0,0 +1,55 @@
+#ifndef HEADER_CURL_CONNCACHE_H
+#define HEADER_CURL_CONNCACHE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct conncache {
+ struct curl_hash *hash;
+ size_t num_connections;
+ long next_connection_id;
+ struct timeval last_cleanup;
+};
+
+struct conncache *Curl_conncache_init(int size);
+
+void Curl_conncache_destroy(struct conncache *connc);
+
+struct connectbundle *Curl_conncache_find_bundle(struct conncache *connc,
+ char *hostname);
+
+CURLcode Curl_conncache_add_conn(struct conncache *connc,
+ struct connectdata *conn);
+
+void Curl_conncache_remove_conn(struct conncache *connc,
+ struct connectdata *conn);
+
+void Curl_conncache_foreach(struct conncache *connc,
+ void *param,
+ int (*func)(struct connectdata *conn,
+ void *param));
+
+struct connectdata *
+Curl_conncache_find_first_connection(struct conncache *connc);
+
+void Curl_conncache_print(struct conncache *connc);
+
+#endif /* HEADER_CURL_CONNCACHE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/connect.c b/external/libcurl_android/jni/libcurl/lib/connect.c
new file mode 100755
index 00000000..fb315fc8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/connect.c
@@ -0,0 +1,1340 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h> /* <netinet/tcp.h> may need it */
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h> /* for sockaddr_un */
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h> /* for TCP_NODELAY */
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
+#include <sys/filio.h>
+#endif
+#ifdef NETWARE
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "if2ip.h"
+#include "strerror.h"
+#include "connect.h"
+#include "curl_memory.h"
+#include "select.h"
+#include "url.h" /* for Curl_safefree() */
+#include "multiif.h"
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "inet_ntop.h"
+#include "inet_pton.h"
+#include "vtls/vtls.h" /* for Curl_ssl_check_cxn() */
+#include "progress.h"
+#include "warnless.h"
+#include "conncache.h"
+#include "multihandle.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef __SYMBIAN32__
+/* This isn't actually supported under Symbian OS */
+#undef SO_NOSIGPIPE
+#endif
+
+static bool verifyconnect(curl_socket_t sockfd, int *error);
+
+#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
+/* DragonFlyBSD and Windows use millisecond units */
+#define KEEPALIVE_FACTOR(x) (x *= 1000)
+#else
+#define KEEPALIVE_FACTOR(x)
+#endif
+
+#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
+#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
+
+struct tcp_keepalive {
+ u_long onoff;
+ u_long keepalivetime;
+ u_long keepaliveinterval;
+};
+#endif
+
+static void
+tcpkeepalive(struct SessionHandle *data,
+ curl_socket_t sockfd)
+{
+ int optval = data->set.tcp_keepalive?1:0;
+
+ /* only set IDLE and INTVL if setting KEEPALIVE is successful */
+ if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
+ }
+ else {
+#if defined(SIO_KEEPALIVE_VALS)
+ struct tcp_keepalive vals;
+ DWORD dummy;
+ vals.onoff = 1;
+ optval = curlx_sltosi(data->set.tcp_keepidle);
+ KEEPALIVE_FACTOR(optval);
+ vals.keepalivetime = optval;
+ optval = curlx_sltosi(data->set.tcp_keepintvl);
+ KEEPALIVE_FACTOR(optval);
+ vals.keepaliveinterval = optval;
+ if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
+ NULL, 0, &dummy, NULL, NULL) != 0) {
+ infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
+ (int)sockfd, WSAGetLastError());
+ }
+#else
+#ifdef TCP_KEEPIDLE
+ optval = curlx_sltosi(data->set.tcp_keepidle);
+ KEEPALIVE_FACTOR(optval);
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
+ }
+#endif
+#ifdef TCP_KEEPINTVL
+ optval = curlx_sltosi(data->set.tcp_keepintvl);
+ KEEPALIVE_FACTOR(optval);
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
+ }
+#endif
+#ifdef TCP_KEEPALIVE
+ /* Mac OS X style */
+ optval = curlx_sltosi(data->set.tcp_keepidle);
+ KEEPALIVE_FACTOR(optval);
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
+ (void *)&optval, sizeof(optval)) < 0) {
+ infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
+ }
+#endif
+#endif
+ }
+}
+
+static CURLcode
+singleipconnect(struct connectdata *conn,
+ const Curl_addrinfo *ai, /* start connecting to this */
+ curl_socket_t *sock);
+
+/*
+ * Curl_timeleft() returns the amount of milliseconds left allowed for the
+ * transfer/connection. If the value is negative, the timeout time has already
+ * elapsed.
+ *
+ * The start time is stored in progress.t_startsingle - as set with
+ * Curl_pgrsTime(..., TIMER_STARTSINGLE);
+ *
+ * If 'nowp' is non-NULL, it points to the current time.
+ * 'duringconnect' is FALSE if not during a connect, as then of course the
+ * connect timeout is not taken into account!
+ *
+ * @unittest: 1303
+ */
+long Curl_timeleft(struct SessionHandle *data,
+ struct timeval *nowp,
+ bool duringconnect)
+{
+ int timeout_set = 0;
+ long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
+ struct timeval now;
+
+ /* if a timeout is set, use the most restrictive one */
+
+ if(data->set.timeout > 0)
+ timeout_set |= 1;
+ if(duringconnect && (data->set.connecttimeout > 0))
+ timeout_set |= 2;
+
+ switch (timeout_set) {
+ case 1:
+ timeout_ms = data->set.timeout;
+ break;
+ case 2:
+ timeout_ms = data->set.connecttimeout;
+ break;
+ case 3:
+ if(data->set.timeout < data->set.connecttimeout)
+ timeout_ms = data->set.timeout;
+ else
+ timeout_ms = data->set.connecttimeout;
+ break;
+ default:
+ /* use the default */
+ if(!duringconnect)
+ /* if we're not during connect, there's no default timeout so if we're
+ at zero we better just return zero and not make it a negative number
+ by the math below */
+ return 0;
+ break;
+ }
+
+ if(!nowp) {
+ now = Curl_tvnow();
+ nowp = &now;
+ }
+
+ /* subtract elapsed time */
+ if(duringconnect)
+ /* since this most recent connect started */
+ timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
+ else
+ /* since the entire operation started */
+ timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
+ if(!timeout_ms)
+ /* avoid returning 0 as that means no timeout! */
+ return -1;
+
+ return timeout_ms;
+}
+
+static CURLcode bindlocal(struct connectdata *conn,
+ curl_socket_t sockfd, int af)
+{
+ struct SessionHandle *data = conn->data;
+
+ struct Curl_sockaddr_storage sa;
+ struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
+ curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
+ struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
+#endif
+
+ struct Curl_dns_entry *h=NULL;
+ unsigned short port = data->set.localport; /* use this port number, 0 for
+ "random" */
+ /* how many port numbers to try to bind to, increasing one at a time */
+ int portnum = data->set.localportrange;
+ const char *dev = data->set.str[STRING_DEVICE];
+ int error;
+ char myhost[256] = "";
+ int done = 0; /* -1 for error, 1 for address found */
+ bool is_interface = FALSE;
+ bool is_host = FALSE;
+ static const char *if_prefix = "if!";
+ static const char *host_prefix = "host!";
+
+ /*************************************************************
+ * Select device to bind socket to
+ *************************************************************/
+ if(!dev && !port)
+ /* no local kind of binding was requested */
+ return CURLE_OK;
+
+ memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
+
+ if(dev && (strlen(dev)<255) ) {
+ if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
+ dev += strlen(if_prefix);
+ is_interface = TRUE;
+ }
+ else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
+ dev += strlen(host_prefix);
+ is_host = TRUE;
+ }
+
+ /* interface */
+ if(!is_host) {
+ switch(Curl_if2ip(af, conn->scope, dev, myhost, sizeof(myhost))) {
+ case IF2IP_NOT_FOUND:
+ if(is_interface) {
+ /* Do not fall back to treating it as a host name */
+ failf(data, "Couldn't bind to interface '%s'", dev);
+ return CURLE_INTERFACE_FAILED;
+ }
+ break;
+ case IF2IP_AF_NOT_SUPPORTED:
+ /* Signal the caller to try another address family if available */
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ case IF2IP_FOUND:
+ is_interface = TRUE;
+ /*
+ * We now have the numerical IP address in the 'myhost' buffer
+ */
+ infof(data, "Local Interface %s is ip %s using address family %i\n",
+ dev, myhost, af);
+ done = 1;
+
+#ifdef SO_BINDTODEVICE
+ /* I am not sure any other OSs than Linux that provide this feature,
+ * and at the least I cannot test. --Ben
+ *
+ * This feature allows one to tightly bind the local socket to a
+ * particular interface. This will force even requests to other
+ * local interfaces to go out the external interface.
+ *
+ *
+ * Only bind to the interface when specified as interface, not just
+ * as a hostname or ip address.
+ */
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+ dev, (curl_socklen_t)strlen(dev)+1) != 0) {
+ error = SOCKERRNO;
+ infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
+ " will do regular bind\n",
+ dev, error, Curl_strerror(conn, error));
+ /* This is typically "errno 1, error: Operation not permitted" if
+ you're not running as root or another suitable privileged
+ user */
+ }
+#endif
+ break;
+ }
+ }
+ if(!is_interface) {
+ /*
+ * This was not an interface, resolve the name as a host name
+ * or IP number
+ *
+ * Temporarily force name resolution to use only the address type
+ * of the connection. The resolve functions should really be changed
+ * to take a type parameter instead.
+ */
+ long ipver = conn->ip_version;
+ int rc;
+
+ if(af == AF_INET)
+ conn->ip_version = CURL_IPRESOLVE_V4;
+#ifdef ENABLE_IPV6
+ else if(af == AF_INET6)
+ conn->ip_version = CURL_IPRESOLVE_V6;
+#endif
+
+ rc = Curl_resolv(conn, dev, 0, &h);
+ if(rc == CURLRESOLV_PENDING)
+ (void)Curl_resolver_wait_resolv(conn, &h);
+ conn->ip_version = ipver;
+
+ if(h) {
+ /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
+ Curl_printable_address(h->addr, myhost, sizeof(myhost));
+ infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
+ dev, af, myhost, h->addr->ai_family);
+ Curl_resolv_unlock(data, h);
+ done = 1;
+ }
+ else {
+ /*
+ * provided dev was no interface (or interfaces are not supported
+ * e.g. solaris) no ip address and no domain we fail here
+ */
+ done = -1;
+ }
+ }
+
+ if(done > 0) {
+#ifdef ENABLE_IPV6
+ /* ipv6 address */
+ if(af == AF_INET6) {
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ char *scope_ptr = strchr(myhost, '%');
+ if(scope_ptr)
+ *(scope_ptr++) = 0;
+#endif
+ if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
+ si6->sin6_family = AF_INET6;
+ si6->sin6_port = htons(port);
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ if(scope_ptr)
+ /* The "myhost" string either comes from Curl_if2ip or from
+ Curl_printable_address. The latter returns only numeric scope
+ IDs and the former returns none at all. So the scope ID, if
+ present, is known to be numeric */
+ si6->sin6_scope_id = atoi(scope_ptr);
+#endif
+ }
+ sizeof_sa = sizeof(struct sockaddr_in6);
+ }
+ else
+#endif
+ /* ipv4 address */
+ if((af == AF_INET) &&
+ (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
+ si4->sin_family = AF_INET;
+ si4->sin_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in);
+ }
+ }
+
+ if(done < 1) {
+ failf(data, "Couldn't bind to '%s'", dev);
+ return CURLE_INTERFACE_FAILED;
+ }
+ }
+ else {
+ /* no device was given, prepare sa to match af's needs */
+#ifdef ENABLE_IPV6
+ if(af == AF_INET6) {
+ si6->sin6_family = AF_INET6;
+ si6->sin6_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in6);
+ }
+ else
+#endif
+ if(af == AF_INET) {
+ si4->sin_family = AF_INET;
+ si4->sin_port = htons(port);
+ sizeof_sa = sizeof(struct sockaddr_in);
+ }
+ }
+
+ for(;;) {
+ if(bind(sockfd, sock, sizeof_sa) >= 0) {
+ /* we succeeded to bind */
+ struct Curl_sockaddr_storage add;
+ curl_socklen_t size = sizeof(add);
+ memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
+ if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
+ data->state.os_errno = error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return CURLE_INTERFACE_FAILED;
+ }
+ infof(data, "Local port: %hu\n", port);
+ conn->bits.bound = TRUE;
+ return CURLE_OK;
+ }
+
+ if(--portnum > 0) {
+ infof(data, "Bind to local port %hu failed, trying next\n", port);
+ port++; /* try next port */
+ /* We re-use/clobber the port variable here below */
+ if(sock->sa_family == AF_INET)
+ si4->sin_port = ntohs(port);
+#ifdef ENABLE_IPV6
+ else
+ si6->sin6_port = ntohs(port);
+#endif
+ }
+ else
+ break;
+ }
+
+ data->state.os_errno = error = SOCKERRNO;
+ failf(data, "bind failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+
+ return CURLE_INTERFACE_FAILED;
+}
+
+/*
+ * verifyconnect() returns TRUE if the connect really has happened.
+ */
+static bool verifyconnect(curl_socket_t sockfd, int *error)
+{
+ bool rc = TRUE;
+#ifdef SO_ERROR
+ int err = 0;
+ curl_socklen_t errSize = sizeof(err);
+
+#ifdef WIN32
+ /*
+ * In October 2003 we effectively nullified this function on Windows due to
+ * problems with it using all CPU in multi-threaded cases.
+ *
+ * In May 2004, we bring it back to offer more info back on connect failures.
+ * Gisle Vanem could reproduce the former problems with this function, but
+ * could avoid them by adding this SleepEx() call below:
+ *
+ * "I don't have Rational Quantify, but the hint from his post was
+ * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
+ * just Sleep(0) would be enough?) would release whatever
+ * mutex/critical-section the ntdll call is waiting on.
+ *
+ * Someone got to verify this on Win-NT 4.0, 2000."
+ */
+
+#ifdef _WIN32_WCE
+ Sleep(0);
+#else
+ SleepEx(0, FALSE);
+#endif
+
+#endif
+
+ if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
+ err = SOCKERRNO;
+#ifdef _WIN32_WCE
+ /* Old WinCE versions don't support SO_ERROR */
+ if(WSAENOPROTOOPT == err) {
+ SET_SOCKERRNO(0);
+ err = 0;
+ }
+#endif
+#ifdef __minix
+ /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
+ if(EBADIOCTL == err) {
+ SET_SOCKERRNO(0);
+ err = 0;
+ }
+#endif
+ if((0 == err) || (EISCONN == err))
+ /* we are connected, awesome! */
+ rc = TRUE;
+ else
+ /* This wasn't a successful connect */
+ rc = FALSE;
+ if(error)
+ *error = err;
+#else
+ (void)sockfd;
+ if(error)
+ *error = SOCKERRNO;
+#endif
+ return rc;
+}
+
+/* Used within the multi interface. Try next IP address, return TRUE if no
+ more address exists or error */
+static CURLcode trynextip(struct connectdata *conn,
+ int sockindex,
+ int tempindex)
+{
+ CURLcode rc = CURLE_COULDNT_CONNECT;
+
+ /* First clean up after the failed socket.
+ Don't close it yet to ensure that the next IP's socket gets a different
+ file descriptor, which can prevent bugs when the curl_multi_socket_action
+ interface is used with certain select() replacements such as kqueue. */
+ curl_socket_t fd_to_close = conn->tempsock[tempindex];
+ conn->tempsock[tempindex] = CURL_SOCKET_BAD;
+
+ if(sockindex == FIRSTSOCKET) {
+ Curl_addrinfo *ai = NULL;
+ int family = AF_UNSPEC;
+
+ if(conn->tempaddr[tempindex]) {
+ /* find next address in the same protocol family */
+ family = conn->tempaddr[tempindex]->ai_family;
+ ai = conn->tempaddr[tempindex]->ai_next;
+ }
+ else if(conn->tempaddr[0]) {
+ /* happy eyeballs - try the other protocol family */
+ int firstfamily = conn->tempaddr[0]->ai_family;
+#ifdef ENABLE_IPV6
+ family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
+#else
+ family = firstfamily;
+#endif
+ ai = conn->tempaddr[0]->ai_next;
+ }
+
+ while(ai) {
+ while(ai && ai->ai_family != family)
+ ai = ai->ai_next;
+
+ if(ai) {
+ rc = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
+ if(rc == CURLE_COULDNT_CONNECT) {
+ ai = ai->ai_next;
+ continue;
+ }
+ conn->tempaddr[tempindex] = ai;
+ }
+ break;
+ }
+ }
+
+ if(fd_to_close != CURL_SOCKET_BAD)
+ Curl_closesocket(conn, fd_to_close);
+
+ return rc;
+}
+
+/* Copies connection info into the session handle to make it available
+ when the session handle is no longer associated with a connection. */
+void Curl_persistconninfo(struct connectdata *conn)
+{
+ memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
+ memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
+ conn->data->info.conn_primary_port = conn->primary_port;
+ conn->data->info.conn_local_port = conn->local_port;
+}
+
+/* retrieves ip address and port from a sockaddr structure */
+static bool getaddressinfo(struct sockaddr* sa, char* addr,
+ long* port)
+{
+ unsigned short us_port;
+ struct sockaddr_in* si = NULL;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6* si6 = NULL;
+#endif
+#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
+ struct sockaddr_un* su = NULL;
+#endif
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ si = (struct sockaddr_in*) sa;
+ if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
+ addr, MAX_IPADR_LEN)) {
+ us_port = ntohs(si->sin_port);
+ *port = us_port;
+ return TRUE;
+ }
+ break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ si6 = (struct sockaddr_in6*)sa;
+ if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
+ addr, MAX_IPADR_LEN)) {
+ us_port = ntohs(si6->sin6_port);
+ *port = us_port;
+ return TRUE;
+ }
+ break;
+#endif
+#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
+ case AF_UNIX:
+ su = (struct sockaddr_un*)sa;
+ snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
+ *port = 0;
+ return TRUE;
+#endif
+ default:
+ break;
+ }
+
+ addr[0] = '\0';
+ *port = 0;
+
+ return FALSE;
+}
+
+/* retrieves the start/end point information of a socket of an established
+ connection */
+void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
+{
+ int error;
+ curl_socklen_t len;
+ struct Curl_sockaddr_storage ssrem;
+ struct Curl_sockaddr_storage ssloc;
+ struct SessionHandle *data = conn->data;
+
+ if(conn->socktype == SOCK_DGRAM)
+ /* there's no connection! */
+ return;
+
+ if(!conn->bits.reuse) {
+
+ len = sizeof(struct Curl_sockaddr_storage);
+ if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
+ error = SOCKERRNO;
+ failf(data, "getpeername() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return;
+ }
+
+ len = sizeof(struct Curl_sockaddr_storage);
+ if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
+ error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return;
+ }
+
+ if(!getaddressinfo((struct sockaddr*)&ssrem,
+ conn->primary_ip, &conn->primary_port)) {
+ error = ERRNO;
+ failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return;
+ }
+ memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
+
+ if(!getaddressinfo((struct sockaddr*)&ssloc,
+ conn->local_ip, &conn->local_port)) {
+ error = ERRNO;
+ failf(data, "ssloc inet_ntop() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ return;
+ }
+
+ }
+
+ /* persist connection info in session handle */
+ Curl_persistconninfo(conn);
+}
+
+/*
+ * Curl_is_connected() checks if the socket has connected.
+ */
+
+CURLcode Curl_is_connected(struct connectdata *conn,
+ int sockindex,
+ bool *connected)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode code = CURLE_OK;
+ long allow;
+ int error = 0;
+ struct timeval now;
+ int result;
+ int i;
+
+ DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
+
+ *connected = FALSE; /* a very negative world view is best */
+
+ if(conn->bits.tcpconnect[sockindex]) {
+ /* we are connected already! */
+ *connected = TRUE;
+ return CURLE_OK;
+ }
+
+ now = Curl_tvnow();
+
+ /* figure out how long time we have left to connect */
+ allow = Curl_timeleft(data, &now, TRUE);
+
+ if(allow < 0) {
+ /* time-out, bail out, go home */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ for(i=0; i<2; i++) {
+ if(conn->tempsock[i] == CURL_SOCKET_BAD)
+ continue;
+
+#ifdef mpeix
+ /* Call this function once now, and ignore the results. We do this to
+ "clear" the error state on the socket so that we can later read it
+ reliably. This is reported necessary on the MPE/iX operating system. */
+ (void)verifyconnect(conn->tempsock[i], NULL);
+#endif
+
+ /* check socket for connect */
+ result = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
+
+ if(result == 0) { /* no connection yet */
+ if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
+ infof(data, "After %ldms connect time, move on!\n",
+ conn->timeoutms_per_addr);
+ error = ETIMEDOUT;
+ }
+
+ /* should we try another protocol family? */
+ if(i == 0 && conn->tempaddr[1] == NULL &&
+ curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
+ trynextip(conn, sockindex, 1);
+ }
+ }
+ else if(result == CURL_CSELECT_OUT) {
+ if(verifyconnect(conn->tempsock[i], &error)) {
+ /* we are connected with TCP, awesome! */
+ int other = i ^ 1;
+
+ /* use this socket from now on */
+ conn->sock[sockindex] = conn->tempsock[i];
+ conn->ip_addr = conn->tempaddr[i];
+ conn->tempsock[i] = CURL_SOCKET_BAD;
+
+ /* close the other socket, if open */
+ if(conn->tempsock[other] != CURL_SOCKET_BAD) {
+ Curl_closesocket(conn, conn->tempsock[other]);
+ conn->tempsock[other] = CURL_SOCKET_BAD;
+ }
+
+ /* see if we need to do any proxy magic first once we connected */
+ code = Curl_connected_proxy(conn, sockindex);
+ if(code)
+ return code;
+
+ conn->bits.tcpconnect[sockindex] = TRUE;
+
+ *connected = TRUE;
+ if(sockindex == FIRSTSOCKET)
+ Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
+ Curl_updateconninfo(conn, conn->sock[sockindex]);
+ Curl_verboseconnect(conn);
+
+ return CURLE_OK;
+ }
+ else
+ infof(data, "Connection failed\n");
+ }
+ else if(result & CURL_CSELECT_ERR)
+ (void)verifyconnect(conn->tempsock[i], &error);
+
+ /*
+ * The connection failed here, we should attempt to connect to the "next
+ * address" for the given host. But first remember the latest error.
+ */
+ if(error) {
+ char ipaddress[MAX_IPADR_LEN];
+ data->state.os_errno = error;
+ SET_SOCKERRNO(error);
+ if(conn->tempaddr[i]) {
+ Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
+ infof(data, "connect to %s port %ld failed: %s\n",
+ ipaddress, conn->port, Curl_strerror(conn, error));
+
+ conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
+ allow : allow / 2;
+
+ code = trynextip(conn, sockindex, i);
+ }
+ }
+ }
+
+ if(code) {
+ /* no more addresses to try */
+
+ /* if the first address family runs out of addresses to try before
+ the happy eyeball timeout, go ahead and try the next family now */
+ if(conn->tempaddr[1] == NULL) {
+ int rc;
+ rc = trynextip(conn, sockindex, 1);
+ if(rc == CURLE_OK)
+ return CURLE_OK;
+ }
+
+ failf(data, "Failed to connect to %s port %ld: %s",
+ conn->bits.proxy?conn->proxy.name:conn->host.name,
+ conn->port, Curl_strerror(conn, error));
+ }
+
+ return code;
+}
+
+static void tcpnodelay(struct connectdata *conn,
+ curl_socket_t sockfd)
+{
+#ifdef TCP_NODELAY
+ struct SessionHandle *data= conn->data;
+ curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
+ int level = IPPROTO_TCP;
+
+#if 0
+ /* The use of getprotobyname() is disabled since it isn't thread-safe on
+ numerous systems. On these getprotobyname_r() should be used instead, but
+ that exists in at least one 4 arg version and one 5 arg version, and
+ since the proto number rarely changes anyway we now just use the hard
+ coded number. The "proper" fix would need a configure check for the
+ correct function much in the same style the gethostbyname_r versions are
+ detected. */
+ struct protoent *pe = getprotobyname("tcp");
+ if(pe)
+ level = pe->p_proto;
+#endif
+
+ if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
+ sizeof(onoff)) < 0)
+ infof(data, "Could not set TCP_NODELAY: %s\n",
+ Curl_strerror(conn, SOCKERRNO));
+ else
+ infof(data,"TCP_NODELAY set\n");
+#else
+ (void)conn;
+ (void)sockfd;
+#endif
+}
+
+#ifdef SO_NOSIGPIPE
+/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
+ sending data to a dead peer (instead of relying on the 4th argument to send
+ being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
+ systems? */
+static void nosigpipe(struct connectdata *conn,
+ curl_socket_t sockfd)
+{
+ struct SessionHandle *data= conn->data;
+ int onoff = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
+ sizeof(onoff)) < 0)
+ infof(data, "Could not set SO_NOSIGPIPE: %s\n",
+ Curl_strerror(conn, SOCKERRNO));
+}
+#else
+#define nosigpipe(x,y) Curl_nop_stmt
+#endif
+
+#ifdef USE_WINSOCK
+/* When you run a program that uses the Windows Sockets API, you may
+ experience slow performance when you copy data to a TCP server.
+
+ http://support.microsoft.com/kb/823764
+
+ Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
+ Buffer Size
+
+ The problem described in this knowledge-base is applied only to pre-Vista
+ Windows. Following function trying to detect OS version and skips
+ SO_SNDBUF adjustment for Windows Vista and above.
+*/
+#define DETECT_OS_NONE 0
+#define DETECT_OS_PREVISTA 1
+#define DETECT_OS_VISTA_OR_LATER 2
+
+void Curl_sndbufset(curl_socket_t sockfd)
+{
+ int val = CURL_MAX_WRITE_SIZE + 32;
+ int curval = 0;
+ int curlen = sizeof(curval);
+ DWORD majorVersion = 6;
+
+ static int detectOsState = DETECT_OS_NONE;
+
+ if(detectOsState == DETECT_OS_NONE) {
+#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
+ (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
+ OSVERSIONINFO osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+
+ detectOsState = DETECT_OS_PREVISTA;
+ if(GetVersionEx(&osver)) {
+ if(osver.dwMajorVersion >= majorVersion)
+ detectOsState = DETECT_OS_VISTA_OR_LATER;
+ }
+#else
+ ULONGLONG majorVersionMask;
+ OSVERSIONINFOEX osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ osver.dwMajorVersion = majorVersion;
+ majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION,
+ VER_GREATER_EQUAL);
+
+ if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask))
+ detectOsState = DETECT_OS_VISTA_OR_LATER;
+ else
+ detectOsState = DETECT_OS_PREVISTA;
+#endif
+ }
+
+ if(detectOsState == DETECT_OS_VISTA_OR_LATER)
+ return;
+
+ if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
+ if(curval > val)
+ return;
+
+ setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
+}
+#endif
+
+/*
+ * singleipconnect()
+ *
+ * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
+ * CURL_SOCKET_BAD. Other errors will however return proper errors.
+ *
+ * singleipconnect() connects to the given IP only, and it may return without
+ * having connected.
+ */
+static CURLcode
+singleipconnect(struct connectdata *conn,
+ const Curl_addrinfo *ai,
+ curl_socket_t *sockp)
+{
+ struct Curl_sockaddr_ex addr;
+ int rc;
+ int error = 0;
+ bool isconnected = FALSE;
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sockfd;
+ CURLcode res = CURLE_OK;
+ char ipaddress[MAX_IPADR_LEN];
+ long port;
+
+ *sockp = CURL_SOCKET_BAD;
+
+ res = Curl_socket(conn, ai, &addr, &sockfd);
+ if(res)
+ /* Failed to create the socket, but still return OK since we signal the
+ lack of socket as well. This allows the parent function to keep looping
+ over alternative addresses/socket families etc. */
+ return CURLE_OK;
+
+ /* store remote address and port used in this connection attempt */
+ if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
+ ipaddress, &port)) {
+ /* malformed address or bug in inet_ntop, try next address */
+ error = ERRNO;
+ failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
+ error, Curl_strerror(conn, error));
+ Curl_closesocket(conn, sockfd);
+ return CURLE_OK;
+ }
+ infof(data, " Trying %s...\n", ipaddress);
+
+ if(data->set.tcp_nodelay)
+ tcpnodelay(conn, sockfd);
+
+ nosigpipe(conn, sockfd);
+
+ Curl_sndbufset(sockfd);
+
+ if(data->set.tcp_keepalive)
+ tcpkeepalive(data, sockfd);
+
+ if(data->set.fsockopt) {
+ /* activate callback for setting socket options */
+ error = data->set.fsockopt(data->set.sockopt_client,
+ sockfd,
+ CURLSOCKTYPE_IPCXN);
+
+ if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
+ isconnected = TRUE;
+ else if(error) {
+ Curl_closesocket(conn, sockfd); /* close the socket and bail out */
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+ }
+
+ /* possibly bind the local end to an IP, interface or port */
+ res = bindlocal(conn, sockfd, addr.family);
+ if(res) {
+ Curl_closesocket(conn, sockfd); /* close socket and bail out */
+ if(res == CURLE_UNSUPPORTED_PROTOCOL) {
+ /* The address family is not supported on this interface.
+ We can continue trying addresses */
+ return CURLE_OK;
+ }
+ return res;
+ }
+
+ /* set socket non-blocking */
+ curlx_nonblock(sockfd, TRUE);
+
+ conn->connecttime = Curl_tvnow();
+ if(conn->num_addr > 1)
+ Curl_expire_latest(data, conn->timeoutms_per_addr);
+
+ /* Connect TCP sockets, bind UDP */
+ if(!isconnected && (conn->socktype == SOCK_STREAM)) {
+ rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+ if(-1 == rc)
+ error = SOCKERRNO;
+ }
+ else {
+ *sockp = sockfd;
+ return CURLE_OK;
+ }
+
+#ifdef ENABLE_IPV6
+ conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
+#endif
+
+ if(-1 == rc) {
+ switch(error) {
+ case EINPROGRESS:
+ case EWOULDBLOCK:
+#if defined(EAGAIN)
+#if (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
+#endif
+ res = CURLE_OK;
+ break;
+
+ default:
+ /* unknown error, fallthrough and try another address! */
+ infof(data, "Immediate connect fail for %s: %s\n",
+ ipaddress, Curl_strerror(conn,error));
+ data->state.os_errno = error;
+
+ /* connect failed */
+ Curl_closesocket(conn, sockfd);
+ res = CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ if(!res)
+ *sockp = sockfd;
+
+ return res;
+}
+
+/*
+ * 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 */
+ const struct Curl_dns_entry *remotehost)
+{
+ struct SessionHandle *data = conn->data;
+ struct timeval before = Curl_tvnow();
+ CURLcode res = CURLE_COULDNT_CONNECT;
+
+ long timeout_ms = Curl_timeleft(data, &before, TRUE);
+
+ if(timeout_ms < 0) {
+ /* a precaution, no need to continue if time already is up */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ conn->num_addr = Curl_num_addresses(remotehost->addr);
+ conn->tempaddr[0] = remotehost->addr;
+ conn->tempaddr[1] = NULL;
+ conn->tempsock[0] = CURL_SOCKET_BAD;
+ conn->tempsock[1] = CURL_SOCKET_BAD;
+ Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
+
+ /* Max time for the next connection attempt */
+ conn->timeoutms_per_addr =
+ conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
+
+ /* start connecting to first IP */
+ while(conn->tempaddr[0]) {
+ res = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
+ if(res == CURLE_OK)
+ break;
+ conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
+ }
+
+ if(conn->tempsock[0] == CURL_SOCKET_BAD)
+ return res;
+
+ data->info.numconnects++; /* to track the number of connections made */
+
+ return CURLE_OK;
+}
+
+struct connfind {
+ struct connectdata *tofind;
+ bool found;
+};
+
+static int conn_is_conn(struct connectdata *conn, void *param)
+{
+ struct connfind *f = (struct connfind *)param;
+ if(conn == f->tofind) {
+ f->found = TRUE;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Used to extract socket and connectdata struct for the most recent
+ * transfer on the given SessionHandle.
+ *
+ * The returned socket will be CURL_SOCKET_BAD in case of failure!
+ */
+curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
+ struct connectdata **connp)
+{
+ curl_socket_t sockfd;
+
+ DEBUGASSERT(data);
+
+ /* this only works for an easy handle that has been used for
+ curl_easy_perform()! */
+ if(data->state.lastconnect && data->multi_easy) {
+ struct connectdata *c = data->state.lastconnect;
+ struct connfind find;
+ find.tofind = data->state.lastconnect;
+ find.found = FALSE;
+
+ Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn);
+
+ if(!find.found) {
+ data->state.lastconnect = NULL;
+ return CURL_SOCKET_BAD;
+ }
+
+ if(connp)
+ /* only store this if the caller cares for it */
+ *connp = c;
+ sockfd = c->sock[FIRSTSOCKET];
+ /* we have a socket connected, let's determine if the server shut down */
+ /* determine if ssl */
+ if(c->ssl[FIRSTSOCKET].use) {
+ /* use the SSL context */
+ if(!Curl_ssl_check_cxn(c))
+ return CURL_SOCKET_BAD; /* FIN received */
+ }
+/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
+#ifdef MSG_PEEK
+ else {
+ /* use the socket */
+ char buf;
+ if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
+ (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
+ return CURL_SOCKET_BAD; /* FIN received */
+ }
+ }
+#endif
+ }
+ else
+ return CURL_SOCKET_BAD;
+
+ return sockfd;
+}
+
+/*
+ * Close a socket.
+ *
+ * 'conn' can be NULL, beware!
+ */
+int Curl_closesocket(struct connectdata *conn,
+ curl_socket_t sock)
+{
+ if(conn && conn->fclosesocket) {
+ if((sock == conn->sock[SECONDARYSOCKET]) &&
+ conn->sock_accepted[SECONDARYSOCKET])
+ /* if this socket matches the second socket, and that was created with
+ accept, then we MUST NOT call the callback but clear the accepted
+ status */
+ conn->sock_accepted[SECONDARYSOCKET] = FALSE;
+ else
+ return conn->fclosesocket(conn->closesocket_client, sock);
+ }
+ sclose(sock);
+
+ if(conn)
+ /* tell the multi-socket code about this */
+ Curl_multi_closed(conn, sock);
+
+ return 0;
+}
+
+/*
+ * Create a socket based on info from 'conn' and 'ai'.
+ *
+ * 'addr' should be a pointer to the correct struct to get data back, or NULL.
+ * 'sockfd' must be a pointer to a socket descriptor.
+ *
+ * If the open socket callback is set, used that!
+ *
+ */
+CURLcode Curl_socket(struct connectdata *conn,
+ const Curl_addrinfo *ai,
+ struct Curl_sockaddr_ex *addr,
+ curl_socket_t *sockfd)
+{
+ struct SessionHandle *data = conn->data;
+ struct Curl_sockaddr_ex dummy;
+
+ if(!addr)
+ /* if the caller doesn't want info back, use a local temp copy */
+ addr = &dummy;
+
+ /*
+ * The Curl_sockaddr_ex structure is basically libcurl's external API
+ * curl_sockaddr structure with enough space available to directly hold
+ * any protocol-specific address structures. The variable declared here
+ * will be used to pass / receive data to/from the fopensocket callback
+ * if this has been set, before that, it is initialized from parameters.
+ */
+
+ addr->family = ai->ai_family;
+ addr->socktype = conn->socktype;
+ addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
+ addr->addrlen = ai->ai_addrlen;
+
+ if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
+ addr->addrlen = sizeof(struct Curl_sockaddr_storage);
+ memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
+
+ if(data->set.fopensocket)
+ /*
+ * If the opensocket callback is set, all the destination address
+ * information is passed to the callback. Depending on this information the
+ * callback may opt to abort the connection, this is indicated returning
+ * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
+ * the callback returns a valid socket the destination address information
+ * might have been changed and this 'new' address will actually be used
+ * here to connect.
+ */
+ *sockfd = data->set.fopensocket(data->set.opensocket_client,
+ CURLSOCKTYPE_IPCXN,
+ (struct curl_sockaddr *)addr);
+ else
+ /* opensocket callback not set, so simply create the socket now */
+ *sockfd = socket(addr->family, addr->socktype, addr->protocol);
+
+ if(*sockfd == CURL_SOCKET_BAD)
+ /* no socket, no connection */
+ return CURLE_COULDNT_CONNECT;
+
+#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
+ if(conn->scope && (addr->family == AF_INET6)) {
+ struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
+ sa6->sin6_scope_id = conn->scope;
+ }
+#endif
+
+ return CURLE_OK;
+
+}
+
+#ifdef CURLDEBUG
+/*
+ * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
+ * MUST be called with the connclose() or connclose() macros with a stated
+ * reason. The reason is only shown in debug builds but helps to figure out
+ * decision paths when connections are or aren't re-used as expected.
+ */
+void Curl_conncontrol(struct connectdata *conn, bool closeit,
+ const char *reason)
+{
+ infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
+ reason);
+ conn->bits.close = closeit; /* the only place in the source code that should
+ assign this bit */
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/connect.h b/external/libcurl_android/jni/libcurl/lib/connect.h
new file mode 100755
index 00000000..7bc391be
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/connect.h
@@ -0,0 +1,122 @@
+#ifndef HEADER_CURL_CONNECT_H
+#define HEADER_CURL_CONNECT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
+#include "sockaddr.h"
+
+CURLcode Curl_is_connected(struct connectdata *conn,
+ int sockindex,
+ bool *connected);
+
+CURLcode Curl_connecthost(struct connectdata *conn,
+ const struct Curl_dns_entry *host);
+
+/* generic function that returns how much time there's left to run, according
+ to the timeouts set */
+long Curl_timeleft(struct SessionHandle *data,
+ struct timeval *nowp,
+ bool duringconnect);
+
+#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
+#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between
+ ipv4/ipv6 connection attempts */
+
+/*
+ * Used to extract socket and connectdata struct for the most recent
+ * transfer on the given SessionHandle.
+ *
+ * The returned socket will be CURL_SOCKET_BAD in case of failure!
+ */
+curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
+ struct connectdata **connp);
+
+#ifdef USE_WINSOCK
+/* When you run a program that uses the Windows Sockets API, you may
+ experience slow performance when you copy data to a TCP server.
+
+ http://support.microsoft.com/kb/823764
+
+ Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
+ Buffer Size
+
+*/
+void Curl_sndbufset(curl_socket_t sockfd);
+#else
+#define Curl_sndbufset(y) Curl_nop_stmt
+#endif
+
+void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
+void Curl_persistconninfo(struct connectdata *conn);
+int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
+
+/*
+ * The Curl_sockaddr_ex structure is basically libcurl's external API
+ * curl_sockaddr structure with enough space available to directly hold any
+ * protocol-specific address structures. The variable declared here will be
+ * used to pass / receive data to/from the fopensocket callback if this has
+ * been set, before that, it is initialized from parameters.
+ */
+struct Curl_sockaddr_ex {
+ int family;
+ int socktype;
+ int protocol;
+ unsigned int addrlen;
+ union {
+ struct sockaddr addr;
+ struct Curl_sockaddr_storage buff;
+ } _sa_ex_u;
+};
+#define sa_addr _sa_ex_u.addr
+
+/*
+ * Create a socket based on info from 'conn' and 'ai'.
+ *
+ * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
+ * socket callback is set, used that!
+ *
+ */
+CURLcode Curl_socket(struct connectdata *conn,
+ const Curl_addrinfo *ai,
+ struct Curl_sockaddr_ex *addr,
+ curl_socket_t *sockfd);
+
+#ifdef CURLDEBUG
+/*
+ * Curl_connclose() sets the bit.close bit to TRUE with an explanation.
+ * Nothing else.
+ */
+void Curl_conncontrol(struct connectdata *conn,
+ bool closeit,
+ const char *reason);
+#define connclose(x,y) Curl_conncontrol(x,TRUE, y)
+#define connkeep(x,y) Curl_conncontrol(x, FALSE, y)
+#else /* if !CURLDEBUG */
+
+#define connclose(x,y) (x)->bits.close = TRUE
+#define connkeep(x,y) (x)->bits.close = FALSE
+
+#endif
+
+#endif /* HEADER_CURL_CONNECT_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/content_encoding.c b/external/libcurl_android/jni/libcurl/lib/content_encoding.c
new file mode 100755
index 00000000..c68e6e5f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/content_encoding.c
@@ -0,0 +1,435 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIBZ
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "sendf.h"
+#include "content_encoding.h"
+#include "curl_memory.h"
+
+#include "memdebug.h"
+
+/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
+ (doing so will reduce code size slightly). */
+#define OLD_ZLIB_SUPPORT 1
+
+#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
+
+#define GZIP_MAGIC_0 0x1f
+#define GZIP_MAGIC_1 0x8b
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+static voidpf
+zalloc_cb(voidpf opaque, unsigned int items, unsigned int size)
+{
+ (void) opaque;
+ /* not a typo, keep it calloc() */
+ return (voidpf) calloc(items, size);
+}
+
+static void
+zfree_cb(voidpf opaque, voidpf ptr)
+{
+ (void) opaque;
+ free(ptr);
+}
+
+static CURLcode
+process_zlib_error(struct connectdata *conn, z_stream *z)
+{
+ struct SessionHandle *data = conn->data;
+ if(z->msg)
+ failf (data, "Error while processing content unencoding: %s",
+ z->msg);
+ else
+ failf (data, "Error while processing content unencoding: "
+ "Unknown failure within decompression software.");
+
+ return CURLE_BAD_CONTENT_ENCODING;
+}
+
+static CURLcode
+exit_zlib(z_stream *z, zlibInitState *zlib_init, CURLcode result)
+{
+ inflateEnd(z);
+ *zlib_init = ZLIB_UNINIT;
+ return result;
+}
+
+static CURLcode
+inflate_stream(struct connectdata *conn,
+ struct SingleRequest *k)
+{
+ int allow_restart = 1;
+ z_stream *z = &k->z; /* zlib state structure */
+ uInt nread = z->avail_in;
+ Bytef *orig_in = z->next_in;
+ int status; /* zlib status */
+ CURLcode result = CURLE_OK; /* Curl_client_write status */
+ char *decomp; /* Put the decompressed data here. */
+
+ /* Dynamically allocate a buffer for decompression because it's uncommonly
+ large to hold on the stack */
+ decomp = malloc(DSIZ);
+ if(decomp == NULL) {
+ return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
+ }
+
+ /* because the buffer size is fixed, iteratively decompress and transfer to
+ the client via client_write. */
+ for(;;) {
+ /* (re)set buffer for decompressed output for every iteration */
+ z->next_out = (Bytef *)decomp;
+ z->avail_out = DSIZ;
+
+ status = inflate(z, Z_SYNC_FLUSH);
+ if(status == Z_OK || status == Z_STREAM_END) {
+ allow_restart = 0;
+ if((DSIZ - z->avail_out) && (!k->ignorebody)) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp,
+ DSIZ - z->avail_out);
+ /* if !CURLE_OK, clean up, return */
+ if(result) {
+ free(decomp);
+ return exit_zlib(z, &k->zlib_init, result);
+ }
+ }
+
+ /* Done? clean up, return */
+ if(status == Z_STREAM_END) {
+ free(decomp);
+ if(inflateEnd(z) == Z_OK)
+ return exit_zlib(z, &k->zlib_init, result);
+ else
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+
+ /* Done with these bytes, exit */
+
+ /* status is always Z_OK at this point! */
+ if(z->avail_in == 0) {
+ free(decomp);
+ return result;
+ }
+ }
+ else if(allow_restart && status == Z_DATA_ERROR) {
+ /* some servers seem to not generate zlib headers, so this is an attempt
+ to fix and continue anyway */
+
+ (void) inflateEnd(z); /* don't care about the return code */
+ if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
+ free(decomp);
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+ z->next_in = orig_in;
+ z->avail_in = nread;
+ allow_restart = 0;
+ continue;
+ }
+ else { /* Error; exit loop, handle below */
+ free(decomp);
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+ }
+ /* Will never get here */
+}
+
+CURLcode
+Curl_unencode_deflate_write(struct connectdata *conn,
+ struct SingleRequest *k,
+ ssize_t nread)
+{
+ z_stream *z = &k->z; /* zlib state structure */
+
+ /* Initialize zlib? */
+ if(k->zlib_init == ZLIB_UNINIT) {
+ memset(z, 0, sizeof(z_stream));
+ z->zalloc = (alloc_func)zalloc_cb;
+ z->zfree = (free_func)zfree_cb;
+
+ if(inflateInit(z) != Z_OK)
+ return process_zlib_error(conn, z);
+ k->zlib_init = ZLIB_INIT;
+ }
+
+ /* Set the compressed input when this function is called */
+ z->next_in = (Bytef *)k->str;
+ z->avail_in = (uInt)nread;
+
+ /* Now uncompress the data */
+ return inflate_stream(conn, k);
+}
+
+#ifdef OLD_ZLIB_SUPPORT
+/* Skip over the gzip header */
+static enum {
+ GZIP_OK,
+ GZIP_BAD,
+ GZIP_UNDERFLOW
+} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
+{
+ int method, flags;
+ const ssize_t totallen = len;
+
+ /* The shortest header is 10 bytes */
+ if(len < 10)
+ return GZIP_UNDERFLOW;
+
+ if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
+ return GZIP_BAD;
+
+ method = data[2];
+ flags = data[3];
+
+ if(method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ /* Can't handle this compression method or unknown flag */
+ return GZIP_BAD;
+ }
+
+ /* Skip over time, xflags, OS code and all previous bytes */
+ len -= 10;
+ data += 10;
+
+ if(flags & EXTRA_FIELD) {
+ ssize_t extra_len;
+
+ if(len < 2)
+ return GZIP_UNDERFLOW;
+
+ extra_len = (data[1] << 8) | data[0];
+
+ if(len < (extra_len+2))
+ return GZIP_UNDERFLOW;
+
+ len -= (extra_len + 2);
+ data += (extra_len + 2);
+ }
+
+ if(flags & ORIG_NAME) {
+ /* Skip over NUL-terminated file name */
+ while(len && *data) {
+ --len;
+ ++data;
+ }
+ if(!len || *data)
+ return GZIP_UNDERFLOW;
+
+ /* Skip over the NUL */
+ --len;
+ ++data;
+ }
+
+ if(flags & COMMENT) {
+ /* Skip over NUL-terminated comment */
+ while(len && *data) {
+ --len;
+ ++data;
+ }
+ if(!len || *data)
+ return GZIP_UNDERFLOW;
+
+ /* Skip over the NUL */
+ --len;
+ }
+
+ if(flags & HEAD_CRC) {
+ if(len < 2)
+ return GZIP_UNDERFLOW;
+
+ len -= 2;
+ }
+
+ *headerlen = totallen - len;
+ return GZIP_OK;
+}
+#endif
+
+CURLcode
+Curl_unencode_gzip_write(struct connectdata *conn,
+ struct SingleRequest *k,
+ ssize_t nread)
+{
+ z_stream *z = &k->z; /* zlib state structure */
+
+ /* Initialize zlib? */
+ if(k->zlib_init == ZLIB_UNINIT) {
+ memset(z, 0, sizeof(z_stream));
+ z->zalloc = (alloc_func)zalloc_cb;
+ z->zfree = (free_func)zfree_cb;
+
+ if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
+ /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
+ if(inflateInit2(z, MAX_WBITS+32) != Z_OK) {
+ return process_zlib_error(conn, z);
+ }
+ k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
+ }
+ else {
+ /* we must parse the gzip header ourselves */
+ if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
+ return process_zlib_error(conn, z);
+ }
+ k->zlib_init = ZLIB_INIT; /* Initial call state */
+ }
+ }
+
+ if(k->zlib_init == ZLIB_INIT_GZIP) {
+ /* Let zlib handle the gzip decompression entirely */
+ z->next_in = (Bytef *)k->str;
+ z->avail_in = (uInt)nread;
+ /* Now uncompress the data */
+ return inflate_stream(conn, k);
+ }
+
+#ifndef OLD_ZLIB_SUPPORT
+ /* Support for old zlib versions is compiled away and we are running with
+ an old version, so return an error. */
+ return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND);
+
+#else
+ /* This next mess is to get around the potential case where there isn't
+ * enough data passed in to skip over the gzip header. If that happens, we
+ * malloc a block and copy what we have then wait for the next call. If
+ * there still isn't enough (this is definitely a worst-case scenario), we
+ * make the block bigger, copy the next part in and keep waiting.
+ *
+ * This is only required with zlib versions < 1.2.0.4 as newer versions
+ * can handle the gzip header themselves.
+ */
+
+ switch (k->zlib_init) {
+ /* Skip over gzip header? */
+ case ZLIB_INIT:
+ {
+ /* Initial call state */
+ ssize_t hlen;
+
+ switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
+ case GZIP_OK:
+ z->next_in = (Bytef *)k->str + hlen;
+ z->avail_in = (uInt)(nread - hlen);
+ k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
+ break;
+
+ case GZIP_UNDERFLOW:
+ /* We need more data so we can find the end of the gzip header. It's
+ * possible that the memory block we malloc here will never be freed if
+ * the transfer abruptly aborts after this point. Since it's unlikely
+ * that circumstances will be right for this code path to be followed in
+ * the first place, and it's even more unlikely for a transfer to fail
+ * immediately afterwards, it should seldom be a problem.
+ */
+ z->avail_in = (uInt)nread;
+ z->next_in = malloc(z->avail_in);
+ if(z->next_in == NULL) {
+ return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
+ }
+ memcpy(z->next_in, k->str, z->avail_in);
+ k->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
+ /* We don't have any data to inflate yet */
+ return CURLE_OK;
+
+ case GZIP_BAD:
+ default:
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+
+ }
+ break;
+
+ case ZLIB_GZIP_HEADER:
+ {
+ /* Need more gzip header data state */
+ ssize_t hlen;
+ unsigned char *oldblock = z->next_in;
+
+ z->avail_in += (uInt)nread;
+ z->next_in = realloc(z->next_in, z->avail_in);
+ if(z->next_in == NULL) {
+ free(oldblock);
+ return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
+ }
+ /* Append the new block of data to the previous one */
+ memcpy(z->next_in + z->avail_in - nread, k->str, nread);
+
+ switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) {
+ case GZIP_OK:
+ /* This is the zlib stream data */
+ free(z->next_in);
+ /* Don't point into the malloced block since we just freed it */
+ z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in;
+ z->avail_in = (uInt)(z->avail_in - hlen);
+ k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
+ break;
+
+ case GZIP_UNDERFLOW:
+ /* We still don't have any data to inflate! */
+ return CURLE_OK;
+
+ case GZIP_BAD:
+ default:
+ free(z->next_in);
+ return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+ }
+
+ }
+ break;
+
+ case ZLIB_GZIP_INFLATING:
+ default:
+ /* Inflating stream state */
+ z->next_in = (Bytef *)k->str;
+ z->avail_in = (uInt)nread;
+ break;
+ }
+
+ if(z->avail_in == 0) {
+ /* We don't have any data to inflate; wait until next time */
+ return CURLE_OK;
+ }
+
+ /* We've parsed the header, now uncompress the data */
+ return inflate_stream(conn, k);
+#endif
+}
+
+void Curl_unencode_cleanup(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ struct SingleRequest *k = &data->req;
+ z_stream *z = &k->z;
+ if(k->zlib_init != ZLIB_UNINIT)
+ (void) exit_zlib(z, &k->zlib_init, CURLE_OK);
+}
+
+#endif /* HAVE_LIBZ */
diff --git a/external/libcurl_android/jni/libcurl/lib/content_encoding.h b/external/libcurl_android/jni/libcurl/lib/content_encoding.h
new file mode 100755
index 00000000..501f6c8c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/content_encoding.h
@@ -0,0 +1,48 @@
+#ifndef HEADER_CURL_CONTENT_ENCODING_H
+#define HEADER_CURL_CONTENT_ENCODING_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/*
+ * Comma-separated list all supported Content-Encodings ('identity' is implied)
+ */
+#ifdef HAVE_LIBZ
+#define ALL_CONTENT_ENCODINGS "deflate, gzip"
+/* force a cleanup */
+void Curl_unencode_cleanup(struct connectdata *conn);
+#else
+#define ALL_CONTENT_ENCODINGS "identity"
+#define Curl_unencode_cleanup(x) Curl_nop_stmt
+#endif
+
+CURLcode Curl_unencode_deflate_write(struct connectdata *conn,
+ struct SingleRequest *req,
+ ssize_t nread);
+
+CURLcode
+Curl_unencode_gzip_write(struct connectdata *conn,
+ struct SingleRequest *k,
+ ssize_t nread);
+
+
+#endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/cookie.c b/external/libcurl_android/jni/libcurl/lib/cookie.c
new file mode 100755
index 00000000..375485f5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/cookie.c
@@ -0,0 +1,1365 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/***
+
+
+RECEIVING COOKIE INFORMATION
+============================
+
+struct CookieInfo *cookie_init(char *file);
+
+ Inits a cookie struct to store data in a local file. This is always
+ called before any cookies are set.
+
+int cookies_set(struct CookieInfo *cookie, char *cookie_line);
+
+ The 'cookie_line' parameter is a full "Set-cookie:" line as
+ received from a server.
+
+ The function need to replace previously stored lines that this new
+ line superceeds.
+
+ It may remove lines that are expired.
+
+ It should return an indication of success/error.
+
+
+SENDING COOKIE INFORMATION
+==========================
+
+struct Cookies *cookie_getlist(struct CookieInfo *cookie,
+ char *host, char *path, bool secure);
+
+ For a given host and path, return a linked list of cookies that
+ the client should send to the server if used now. The secure
+ boolean informs the cookie if a secure connection is achieved or
+ not.
+
+ It shall only return cookies that haven't expired.
+
+
+Example set of cookies:
+
+ Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
+ Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/ftgw; secure
+ Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/; secure
+ Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/; secure
+ Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/; secure
+ Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
+ domain=.fidelity.com; path=/; secure
+ Set-cookie:
+ Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday,
+ 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure
+****/
+
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+
+#define _MPRINTF_REPLACE
+#include <curl/mprintf.h>
+
+#include "urldata.h"
+#include "cookie.h"
+#include "strequal.h"
+#include "strtok.h"
+#include "sendf.h"
+#include "slist.h"
+#include "curl_memory.h"
+#include "share.h"
+#include "strtoofft.h"
+#include "rawstr.h"
+#include "curl_memrchr.h"
+#include "inet_pton.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static void freecookie(struct Cookie *co)
+{
+ if(co->expirestr)
+ free(co->expirestr);
+ if(co->domain)
+ free(co->domain);
+ if(co->path)
+ free(co->path);
+ if(co->spath)
+ free(co->spath);
+ if(co->name)
+ free(co->name);
+ if(co->value)
+ free(co->value);
+ if(co->maxage)
+ free(co->maxage);
+ if(co->version)
+ free(co->version);
+
+ free(co);
+}
+
+static bool tailmatch(const char *cooke_domain, const char *hostname)
+{
+ size_t cookie_domain_len = strlen(cooke_domain);
+ size_t hostname_len = strlen(hostname);
+
+ if(hostname_len < cookie_domain_len)
+ return FALSE;
+
+ if(!Curl_raw_equal(cooke_domain, hostname+hostname_len-cookie_domain_len))
+ return FALSE;
+
+ /* A lead char of cookie_domain is not '.'.
+ RFC6265 4.1.2.3. The Domain Attribute says:
+ For example, if the value of the Domain attribute is
+ "example.com", the user agent will include the cookie in the Cookie
+ header when making HTTP requests to example.com, www.example.com, and
+ www.corp.example.com.
+ */
+ if(hostname_len == cookie_domain_len)
+ return TRUE;
+ if('.' == *(hostname + hostname_len - cookie_domain_len - 1))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * matching cookie path and url path
+ * RFC6265 5.1.4 Paths and Path-Match
+ */
+static bool pathmatch(const char* cookie_path, const char* request_uri)
+{
+ size_t cookie_path_len;
+ size_t uri_path_len;
+ char* uri_path = NULL;
+ char* pos;
+ bool ret = FALSE;
+
+ /* cookie_path must not have last '/' separator. ex: /sample */
+ cookie_path_len = strlen(cookie_path);
+ if(1 == cookie_path_len) {
+ /* cookie_path must be '/' */
+ return TRUE;
+ }
+
+ uri_path = strdup(request_uri);
+ if(!uri_path)
+ return FALSE;
+ pos = strchr(uri_path, '?');
+ if(pos)
+ *pos = 0x0;
+
+ /* #-fragments are already cut off! */
+ if(0 == strlen(uri_path) || uri_path[0] != '/') {
+ free(uri_path);
+ uri_path = strdup("/");
+ if(!uri_path)
+ return FALSE;
+ }
+
+ /* here, RFC6265 5.1.4 says
+ 4. Output the characters of the uri-path from the first character up
+ to, but not including, the right-most %x2F ("/").
+ but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
+ without redirect.
+ Ignore this algorithm because /hoge is uri path for this case
+ (uri path is not /).
+ */
+
+ uri_path_len = strlen(uri_path);
+
+ if(uri_path_len < cookie_path_len) {
+ ret = FALSE;
+ goto pathmatched;
+ }
+
+ /* not using checkprefix() because matching should be case-sensitive */
+ if(strncmp(cookie_path, uri_path, cookie_path_len)) {
+ ret = FALSE;
+ goto pathmatched;
+ }
+
+ /* The cookie-path and the uri-path are identical. */
+ if(cookie_path_len == uri_path_len) {
+ ret = TRUE;
+ goto pathmatched;
+ }
+
+ /* here, cookie_path_len < url_path_len */
+ if(uri_path[cookie_path_len] == '/') {
+ ret = TRUE;
+ goto pathmatched;
+ }
+
+ ret = FALSE;
+
+pathmatched:
+ free(uri_path);
+ return ret;
+}
+
+/*
+ * cookie path sanitize
+ */
+static char *sanitize_cookie_path(const char *cookie_path)
+{
+ size_t len;
+ char *new_path = strdup(cookie_path);
+ if(!new_path)
+ return NULL;
+
+ /* some stupid site sends path attribute with '"'. */
+ if(new_path[0] == '\"') {
+ memmove((void *)new_path, (const void *)(new_path + 1), strlen(new_path));
+ }
+ if(new_path[strlen(new_path) - 1] == '\"') {
+ new_path[strlen(new_path) - 1] = 0x0;
+ }
+
+ /* RFC6265 5.2.4 The Path Attribute */
+ if(new_path[0] != '/') {
+ /* Let cookie-path be the default-path. */
+ free(new_path);
+ new_path = strdup("/");
+ return new_path;
+ }
+
+ /* convert /hoge/ to /hoge */
+ len = strlen(new_path);
+ if(1 < len && new_path[len - 1] == '/') {
+ new_path[len - 1] = 0x0;
+ }
+
+ return new_path;
+}
+
+/*
+ * Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
+ */
+void Curl_cookie_loadfiles(struct SessionHandle *data)
+{
+ struct curl_slist *list = data->change.cookielist;
+ if(list) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ while(list) {
+ data->cookies = Curl_cookie_init(data,
+ list->data,
+ data->cookies,
+ data->set.cookiesession);
+ list = list->next;
+ }
+ curl_slist_free_all(data->change.cookielist); /* clean up list */
+ data->change.cookielist = NULL; /* don't do this again! */
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+}
+
+/*
+ * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL
+ * that will be freed before the allocated string is stored there.
+ *
+ * It is meant to easily replace strdup()
+ */
+static void strstore(char **str, const char *newstr)
+{
+ if(*str)
+ free(*str);
+ *str = strdup(newstr);
+}
+
+/*
+ * remove_expired() removes expired cookies.
+ */
+static void remove_expired(struct CookieInfo *cookies)
+{
+ struct Cookie *co, *nx, *pv;
+ curl_off_t now = (curl_off_t)time(NULL);
+
+ co = cookies->cookies;
+ pv = NULL;
+ while(co) {
+ nx = co->next;
+ if((co->expirestr || co->maxage) && co->expires < now) {
+ if(co == cookies->cookies) {
+ cookies->cookies = co->next;
+ }
+ else {
+ pv->next = co->next;
+ }
+ cookies->numcookies--;
+ freecookie(co);
+ }
+ else {
+ pv = co;
+ }
+ co = nx;
+ }
+}
+
+/*
+ * Return true if the given string is an IP(v4|v6) address.
+ */
+static bool isip(const char *domain)
+{
+ struct in_addr addr;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+
+ if(Curl_inet_pton(AF_INET, domain, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, domain, &addr6)
+#endif
+ ) {
+ /* domain name given as IP address */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/****************************************************************************
+ *
+ * Curl_cookie_add()
+ *
+ * Add a single cookie line to the cookie keeping object.
+ *
+ * Be aware that sometimes we get an IP-only host name, and that might also be
+ * a numerical IPv6 address.
+ *
+ ***************************************************************************/
+
+struct Cookie *
+Curl_cookie_add(struct SessionHandle *data,
+ /* The 'data' pointer here may be NULL at times, and thus
+ must only be used very carefully for things that can deal
+ with data being NULL. Such as infof() and similar */
+
+ struct CookieInfo *c,
+ bool httpheader, /* TRUE if HTTP header-style line */
+ char *lineptr, /* first character of the line */
+ const char *domain, /* default domain */
+ const char *path) /* full path used when this cookie is set,
+ used to get default path for the cookie
+ unless set */
+{
+ struct Cookie *clist;
+ char name[MAX_NAME];
+ struct Cookie *co;
+ struct Cookie *lastc=NULL;
+ time_t now = time(NULL);
+ bool replace_old = FALSE;
+ bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
+
+ /* First, alloc and init a new struct for it */
+ co = calloc(1, sizeof(struct Cookie));
+ if(!co)
+ return NULL; /* bail out if we're this low on memory */
+
+ if(httpheader) {
+ /* This line was read off a HTTP-header */
+ const char *ptr;
+ const char *semiptr;
+ char *what;
+
+ what = malloc(MAX_COOKIE_LINE);
+ if(!what) {
+ free(co);
+ return NULL;
+ }
+
+ semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
+
+ while(*lineptr && ISBLANK(*lineptr))
+ lineptr++;
+
+ ptr = lineptr;
+ do {
+ /* we have a <what>=<this> pair or a stand-alone word here */
+ name[0]=what[0]=0; /* init the buffers */
+ if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n =]=%"
+ MAX_COOKIE_LINE_TXT "[^;\r\n]",
+ name, what)) {
+ /* Use strstore() below to properly deal with received cookie
+ headers that have the same string property set more than once,
+ and then we use the last one. */
+ const char *whatptr;
+ bool done = FALSE;
+ bool sep;
+ size_t len=strlen(what);
+ const char *endofn = &ptr[ strlen(name) ];
+
+ /* skip trailing spaces in name */
+ while(*endofn && ISBLANK(*endofn))
+ endofn++;
+
+ /* name ends with a '=' ? */
+ sep = (*endofn == '=')?TRUE:FALSE;
+
+ /* Strip off trailing whitespace from the 'what' */
+ while(len && ISBLANK(what[len-1])) {
+ what[len-1]=0;
+ len--;
+ }
+
+ /* Skip leading whitespace from the 'what' */
+ whatptr=what;
+ while(*whatptr && ISBLANK(*whatptr))
+ whatptr++;
+
+ if(!len) {
+ /* this was a "<name>=" with no content, and we must allow
+ 'secure' and 'httponly' specified this weirdly */
+ done = TRUE;
+ if(Curl_raw_equal("secure", name))
+ co->secure = TRUE;
+ else if(Curl_raw_equal("httponly", name))
+ co->httponly = TRUE;
+ else if(sep)
+ /* there was a '=' so we're not done parsing this field */
+ done = FALSE;
+ }
+ if(done)
+ ;
+ else if(Curl_raw_equal("path", name)) {
+ strstore(&co->path, whatptr);
+ if(!co->path) {
+ badcookie = TRUE; /* out of memory bad */
+ break;
+ }
+ co->spath = sanitize_cookie_path(co->path);
+ if(!co->spath) {
+ badcookie = TRUE; /* out of memory bad */
+ break;
+ }
+ }
+ else if(Curl_raw_equal("domain", name)) {
+ bool is_ip;
+ const char *dotp;
+
+ /* Now, we make sure that our host is within the given domain,
+ or the given domain is not valid and thus cannot be set. */
+
+ if('.' == whatptr[0])
+ whatptr++; /* ignore preceding dot */
+
+ is_ip = isip(domain ? domain : whatptr);
+
+ /* check for more dots */
+ dotp = strchr(whatptr, '.');
+ if(!dotp)
+ domain=":";
+
+ if(!domain
+ || (is_ip && !strcmp(whatptr, domain))
+ || (!is_ip && tailmatch(whatptr, domain))) {
+ strstore(&co->domain, whatptr);
+ if(!co->domain) {
+ badcookie = TRUE;
+ break;
+ }
+ if(!is_ip)
+ co->tailmatch=TRUE; /* we always do that if the domain name was
+ given */
+ }
+ else {
+ /* we did not get a tailmatch and then the attempted set domain
+ is not a domain to which the current host belongs. Mark as
+ bad. */
+ badcookie=TRUE;
+ infof(data, "skipped cookie with bad tailmatch domain: %s\n",
+ whatptr);
+ }
+ }
+ else if(Curl_raw_equal("version", name)) {
+ strstore(&co->version, whatptr);
+ if(!co->version) {
+ badcookie = TRUE;
+ break;
+ }
+ }
+ else if(Curl_raw_equal("max-age", name)) {
+ /* Defined in RFC2109:
+
+ Optional. The Max-Age attribute defines the lifetime of the
+ cookie, in seconds. The delta-seconds value is a decimal non-
+ negative integer. After delta-seconds seconds elapse, the
+ client should discard the cookie. A value of zero means the
+ cookie should be discarded immediately.
+
+ */
+ strstore(&co->maxage, whatptr);
+ if(!co->maxage) {
+ badcookie = TRUE;
+ break;
+ }
+ }
+ else if(Curl_raw_equal("expires", name)) {
+ strstore(&co->expirestr, whatptr);
+ if(!co->expirestr) {
+ badcookie = TRUE;
+ break;
+ }
+ }
+ else if(!co->name) {
+ co->name = strdup(name);
+ co->value = strdup(whatptr);
+ if(!co->name || !co->value) {
+ badcookie = TRUE;
+ break;
+ }
+ }
+ /*
+ else this is the second (or more) name we don't know
+ about! */
+ }
+ else {
+ /* this is an "illegal" <what>=<this> pair */
+ }
+
+ if(!semiptr || !*semiptr) {
+ /* we already know there are no more cookies */
+ semiptr = NULL;
+ continue;
+ }
+
+ ptr=semiptr+1;
+ while(*ptr && ISBLANK(*ptr))
+ ptr++;
+ semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
+
+ if(!semiptr && *ptr)
+ /* There are no more semicolons, but there's a final name=value pair
+ coming up */
+ semiptr=strchr(ptr, '\0');
+ } while(semiptr);
+
+ if(co->maxage) {
+ co->expires =
+ curlx_strtoofft((*co->maxage=='\"')?
+ &co->maxage[1]:&co->maxage[0], NULL, 10);
+ if(CURL_OFF_T_MAX - now < co->expires)
+ /* avoid overflow */
+ co->expires = CURL_OFF_T_MAX;
+ else
+ co->expires += now;
+ }
+ else if(co->expirestr) {
+ /* Note that if the date couldn't get parsed for whatever reason,
+ the cookie will be treated as a session cookie */
+ co->expires = curl_getdate(co->expirestr, NULL);
+
+ /* Session cookies have expires set to 0 so if we get that back
+ from the date parser let's add a second to make it a
+ non-session cookie */
+ if(co->expires == 0)
+ co->expires = 1;
+ else if(co->expires < 0)
+ co->expires = 0;
+ }
+
+ if(!badcookie && !co->domain) {
+ if(domain) {
+ /* no domain was given in the header line, set the default */
+ co->domain=strdup(domain);
+ if(!co->domain)
+ badcookie = TRUE;
+ }
+ }
+
+ if(!badcookie && !co->path && path) {
+ /* No path was given in the header line, set the default.
+ Note that the passed-in path to this function MAY have a '?' and
+ following part that MUST not be stored as part of the path. */
+ char *queryp = strchr(path, '?');
+
+ /* queryp is where the interesting part of the path ends, so now we
+ want to the find the last */
+ char *endslash;
+ if(!queryp)
+ endslash = strrchr(path, '/');
+ else
+ endslash = memrchr(path, '/', (size_t)(queryp - path));
+ if(endslash) {
+ size_t pathlen = (size_t)(endslash-path+1); /* include ending slash */
+ co->path=malloc(pathlen+1); /* one extra for the zero byte */
+ if(co->path) {
+ memcpy(co->path, path, pathlen);
+ co->path[pathlen]=0; /* zero terminate */
+ co->spath = sanitize_cookie_path(co->path);
+ if(!co->spath)
+ badcookie = TRUE; /* out of memory bad */
+ }
+ else
+ badcookie = TRUE;
+ }
+ }
+
+ free(what);
+
+ if(badcookie || !co->name) {
+ /* we didn't get a cookie name or a bad one,
+ this is an illegal line, bail out */
+ freecookie(co);
+ return NULL;
+ }
+
+ }
+ else {
+ /* This line is NOT a HTTP header style line, we do offer support for
+ reading the odd netscape cookies-file format here */
+ char *ptr;
+ char *firstptr;
+ char *tok_buf=NULL;
+ int fields;
+
+ /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
+ marked with httpOnly after the domain name are not accessible
+ from javascripts, but since curl does not operate at javascript
+ level, we include them anyway. In Firefox's cookie files, these
+ lines are preceded with #HttpOnly_ and then everything is
+ as usual, so we skip 10 characters of the line..
+ */
+ if(strncmp(lineptr, "#HttpOnly_", 10) == 0) {
+ lineptr += 10;
+ co->httponly = TRUE;
+ }
+
+ if(lineptr[0]=='#') {
+ /* don't even try the comments */
+ free(co);
+ return NULL;
+ }
+ /* strip off the possible end-of-line characters */
+ ptr=strchr(lineptr, '\r');
+ if(ptr)
+ *ptr=0; /* clear it */
+ ptr=strchr(lineptr, '\n');
+ if(ptr)
+ *ptr=0; /* clear it */
+
+ firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
+
+ /* Now loop through the fields and init the struct we already have
+ allocated */
+ for(ptr=firstptr, fields=0; ptr && !badcookie;
+ ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
+ switch(fields) {
+ case 0:
+ if(ptr[0]=='.') /* skip preceding dots */
+ ptr++;
+ co->domain = strdup(ptr);
+ if(!co->domain)
+ badcookie = TRUE;
+ break;
+ case 1:
+ /* This field got its explanation on the 23rd of May 2001 by
+ Andrés García:
+
+ flag: A TRUE/FALSE value indicating if all machines within a given
+ domain can access the variable. This value is set automatically by
+ the browser, depending on the value you set for the domain.
+
+ As far as I can see, it is set to true when the cookie says
+ .domain.com and to false when the domain is complete www.domain.com
+ */
+ co->tailmatch = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
+ break;
+ case 2:
+ /* It turns out, that sometimes the file format allows the path
+ field to remain not filled in, we try to detect this and work
+ around it! Andrés García made us aware of this... */
+ if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
+ /* only if the path doesn't look like a boolean option! */
+ co->path = strdup(ptr);
+ if(!co->path)
+ badcookie = TRUE;
+ else {
+ co->spath = sanitize_cookie_path(co->path);
+ if(!co->spath) {
+ badcookie = TRUE; /* out of memory bad */
+ }
+ }
+ break;
+ }
+ /* this doesn't look like a path, make one up! */
+ co->path = strdup("/");
+ if(!co->path)
+ badcookie = TRUE;
+ co->spath = strdup("/");
+ if(!co->spath)
+ badcookie = TRUE;
+ fields++; /* add a field and fall down to secure */
+ /* FALLTHROUGH */
+ case 3:
+ co->secure = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
+ break;
+ case 4:
+ co->expires = curlx_strtoofft(ptr, NULL, 10);
+ break;
+ case 5:
+ co->name = strdup(ptr);
+ if(!co->name)
+ badcookie = TRUE;
+ break;
+ case 6:
+ co->value = strdup(ptr);
+ if(!co->value)
+ badcookie = TRUE;
+ break;
+ }
+ }
+ if(6 == fields) {
+ /* we got a cookie with blank contents, fix it */
+ co->value = strdup("");
+ if(!co->value)
+ badcookie = TRUE;
+ else
+ fields++;
+ }
+
+ if(!badcookie && (7 != fields))
+ /* we did not find the sufficient number of fields */
+ badcookie = TRUE;
+
+ if(badcookie) {
+ freecookie(co);
+ return NULL;
+ }
+
+ }
+
+ if(!c->running && /* read from a file */
+ c->newsession && /* clean session cookies */
+ !co->expires) { /* this is a session cookie since it doesn't expire! */
+ freecookie(co);
+ return NULL;
+ }
+
+ co->livecookie = c->running;
+
+ /* now, we have parsed the incoming line, we must now check if this
+ superceeds an already existing cookie, which it may if the previous have
+ the same domain and path as this */
+
+ /* at first, remove expired cookies */
+ remove_expired(c);
+
+ clist = c->cookies;
+ replace_old = FALSE;
+ while(clist) {
+ if(Curl_raw_equal(clist->name, co->name)) {
+ /* the names are identical */
+
+ if(clist->domain && co->domain) {
+ if(Curl_raw_equal(clist->domain, co->domain))
+ /* The domains are identical */
+ replace_old=TRUE;
+ }
+ else if(!clist->domain && !co->domain)
+ replace_old = TRUE;
+
+ if(replace_old) {
+ /* the domains were identical */
+
+ if(clist->spath && co->spath) {
+ if(Curl_raw_equal(clist->spath, co->spath)) {
+ replace_old = TRUE;
+ }
+ else
+ replace_old = FALSE;
+ }
+ else if(!clist->spath && !co->spath)
+ replace_old = TRUE;
+ else
+ replace_old = FALSE;
+
+ }
+
+ if(replace_old && !co->livecookie && clist->livecookie) {
+ /* Both cookies matched fine, except that the already present
+ cookie is "live", which means it was set from a header, while
+ the new one isn't "live" and thus only read from a file. We let
+ live cookies stay alive */
+
+ /* Free the newcomer and get out of here! */
+ freecookie(co);
+ return NULL;
+ }
+
+ if(replace_old) {
+ co->next = clist->next; /* get the next-pointer first */
+
+ /* then free all the old pointers */
+ free(clist->name);
+ if(clist->value)
+ free(clist->value);
+ if(clist->domain)
+ free(clist->domain);
+ if(clist->path)
+ free(clist->path);
+ if(clist->spath)
+ free(clist->spath);
+ if(clist->expirestr)
+ free(clist->expirestr);
+
+ if(clist->version)
+ free(clist->version);
+ if(clist->maxage)
+ free(clist->maxage);
+
+ *clist = *co; /* then store all the new data */
+
+ free(co); /* free the newly alloced memory */
+ co = clist; /* point to the previous struct instead */
+
+ /* We have replaced a cookie, now skip the rest of the list but
+ make sure the 'lastc' pointer is properly set */
+ do {
+ lastc = clist;
+ clist = clist->next;
+ } while(clist);
+ break;
+ }
+ }
+ lastc = clist;
+ clist = clist->next;
+ }
+
+ if(c->running)
+ /* Only show this when NOT reading the cookies from a file */
+ infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, "
+ "expire %" CURL_FORMAT_CURL_OFF_T "\n",
+ replace_old?"Replaced":"Added", co->name, co->value,
+ co->domain, co->path, co->expires);
+
+ if(!replace_old) {
+ /* then make the last item point on this new one */
+ if(lastc)
+ lastc->next = co;
+ else
+ c->cookies = co;
+ c->numcookies++; /* one more cookie in the jar */
+ }
+
+ return co;
+}
+
+/*****************************************************************************
+ *
+ * Curl_cookie_init()
+ *
+ * Inits a cookie struct to read data from a local file. This is always
+ * called before any cookies are set. File may be NULL.
+ *
+ * If 'newsession' is TRUE, discard all "session cookies" on read from file.
+ *
+ ****************************************************************************/
+struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
+ const char *file,
+ struct CookieInfo *inc,
+ bool newsession)
+{
+ struct CookieInfo *c;
+ FILE *fp;
+ bool fromfile=TRUE;
+
+ if(NULL == inc) {
+ /* we didn't get a struct, create one */
+ c = calloc(1, sizeof(struct CookieInfo));
+ if(!c)
+ return NULL; /* failed to get memory */
+ c->filename = strdup(file?file:"none"); /* copy the name just in case */
+ }
+ else {
+ /* we got an already existing one, use that */
+ c = inc;
+ }
+ c->running = FALSE; /* this is not running, this is init */
+
+ if(file && strequal(file, "-")) {
+ fp = stdin;
+ fromfile=FALSE;
+ }
+ else if(file && !*file) {
+ /* points to a "" string */
+ fp = NULL;
+ }
+ else
+ fp = file?fopen(file, "r"):NULL;
+
+ c->newsession = newsession; /* new session? */
+
+ if(fp) {
+ char *lineptr;
+ bool headerline;
+
+ char *line = malloc(MAX_COOKIE_LINE);
+ if(line) {
+ while(fgets(line, MAX_COOKIE_LINE, fp)) {
+ if(checkprefix("Set-Cookie:", line)) {
+ /* This is a cookie line, get it! */
+ lineptr=&line[11];
+ headerline=TRUE;
+ }
+ else {
+ lineptr=line;
+ headerline=FALSE;
+ }
+ while(*lineptr && ISBLANK(*lineptr))
+ lineptr++;
+
+ Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
+ }
+ free(line); /* free the line buffer */
+ }
+ if(fromfile)
+ fclose(fp);
+ }
+
+ c->running = TRUE; /* now, we're running */
+
+ return c;
+}
+
+/* sort this so that the longest path gets before the shorter path */
+static int cookie_sort(const void *p1, const void *p2)
+{
+ struct Cookie *c1 = *(struct Cookie **)p1;
+ struct Cookie *c2 = *(struct Cookie **)p2;
+ size_t l1, l2;
+
+ /* 1 - compare cookie path lengths */
+ l1 = c1->path ? strlen(c1->path) : 0;
+ l2 = c2->path ? strlen(c2->path) : 0;
+
+ if(l1 != l2)
+ return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
+
+ /* 2 - compare cookie domain lengths */
+ l1 = c1->domain ? strlen(c1->domain) : 0;
+ l2 = c2->domain ? strlen(c2->domain) : 0;
+
+ if(l1 != l2)
+ return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
+
+ /* 3 - compare cookie names */
+ if(c1->name && c2->name)
+ return strcmp(c1->name, c2->name);
+
+ /* sorry, can't be more deterministic */
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ * Curl_cookie_getlist()
+ *
+ * For a given host and path, return a linked list of cookies that the
+ * client should send to the server if used now. The secure boolean informs
+ * the cookie if a secure connection is achieved or not.
+ *
+ * It shall only return cookies that haven't expired.
+ *
+ ****************************************************************************/
+
+struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
+ const char *host, const char *path,
+ bool secure)
+{
+ struct Cookie *newco;
+ struct Cookie *co;
+ time_t now = time(NULL);
+ struct Cookie *mainco=NULL;
+ size_t matches = 0;
+ bool is_ip;
+
+ if(!c || !c->cookies)
+ return NULL; /* no cookie struct or no cookies in the struct */
+
+ /* at first, remove expired cookies */
+ remove_expired(c);
+
+ /* check if host is an IP(v4|v6) address */
+ is_ip = isip(host);
+
+ co = c->cookies;
+
+ while(co) {
+ /* only process this cookie if it is not expired or had no expire
+ date AND that if the cookie requires we're secure we must only
+ continue if we are! */
+ if((!co->expires || (co->expires > now)) &&
+ (co->secure?secure:TRUE)) {
+
+ /* now check if the domain is correct */
+ if(!co->domain ||
+ (co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
+ ((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) {
+ /* the right part of the host matches the domain stuff in the
+ cookie data */
+
+ /* now check the left part of the path with the cookies path
+ requirement */
+ if(!co->spath || pathmatch(co->spath, path) ) {
+
+ /* and now, we know this is a match and we should create an
+ entry for the return-linked-list */
+
+ newco = malloc(sizeof(struct Cookie));
+ if(newco) {
+ /* first, copy the whole source cookie: */
+ memcpy(newco, co, sizeof(struct Cookie));
+
+ /* then modify our next */
+ newco->next = mainco;
+
+ /* point the main to us */
+ mainco = newco;
+
+ matches++;
+ }
+ else {
+ fail:
+ /* failure, clear up the allocated chain and return NULL */
+ while(mainco) {
+ co = mainco->next;
+ free(mainco);
+ mainco = co;
+ }
+
+ return NULL;
+ }
+ }
+ }
+ }
+ co = co->next;
+ }
+
+ if(matches) {
+ /* Now we need to make sure that if there is a name appearing more than
+ once, the longest specified path version comes first. To make this
+ the swiftest way, we just sort them all based on path length. */
+ struct Cookie **array;
+ size_t i;
+
+ /* alloc an array and store all cookie pointers */
+ array = malloc(sizeof(struct Cookie *) * matches);
+ if(!array)
+ goto fail;
+
+ co = mainco;
+
+ for(i=0; co; co = co->next)
+ array[i++] = co;
+
+ /* now sort the cookie pointers in path length order */
+ qsort(array, matches, sizeof(struct Cookie *), cookie_sort);
+
+ /* remake the linked list order according to the new order */
+
+ mainco = array[0]; /* start here */
+ for(i=0; i<matches-1; i++)
+ array[i]->next = array[i+1];
+ array[matches-1]->next = NULL; /* terminate the list */
+
+ free(array); /* remove the temporary data again */
+ }
+
+ return mainco; /* return the new list */
+}
+
+/*****************************************************************************
+ *
+ * Curl_cookie_clearall()
+ *
+ * Clear all existing cookies and reset the counter.
+ *
+ ****************************************************************************/
+void Curl_cookie_clearall(struct CookieInfo *cookies)
+{
+ if(cookies) {
+ Curl_cookie_freelist(cookies->cookies, TRUE);
+ cookies->cookies = NULL;
+ cookies->numcookies = 0;
+ }
+}
+
+/*****************************************************************************
+ *
+ * Curl_cookie_freelist()
+ *
+ * Free a list of cookies previously returned by Curl_cookie_getlist();
+ *
+ * The 'cookiestoo' argument tells this function whether to just free the
+ * list or actually also free all cookies within the list as well.
+ *
+ ****************************************************************************/
+
+void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo)
+{
+ struct Cookie *next;
+ if(co) {
+ while(co) {
+ next = co->next;
+ if(cookiestoo)
+ freecookie(co);
+ else
+ free(co); /* we only free the struct since the "members" are all just
+ pointed out in the main cookie list! */
+ co = next;
+ }
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * Curl_cookie_clearsess()
+ *
+ * Free all session cookies in the cookies list.
+ *
+ ****************************************************************************/
+void Curl_cookie_clearsess(struct CookieInfo *cookies)
+{
+ struct Cookie *first, *curr, *next, *prev = NULL;
+
+ if(!cookies || !cookies->cookies)
+ return;
+
+ first = curr = prev = cookies->cookies;
+
+ for(; curr; curr = next) {
+ next = curr->next;
+ if(!curr->expires) {
+ if(first == curr)
+ first = next;
+
+ if(prev == curr)
+ prev = next;
+ else
+ prev->next = next;
+
+ freecookie(curr);
+ cookies->numcookies--;
+ }
+ else
+ prev = curr;
+ }
+
+ cookies->cookies = first;
+}
+
+
+/*****************************************************************************
+ *
+ * Curl_cookie_cleanup()
+ *
+ * Free a "cookie object" previous created with cookie_init().
+ *
+ ****************************************************************************/
+void Curl_cookie_cleanup(struct CookieInfo *c)
+{
+ struct Cookie *co;
+ struct Cookie *next;
+ if(c) {
+ if(c->filename)
+ free(c->filename);
+ co = c->cookies;
+
+ while(co) {
+ next = co->next;
+ freecookie(co);
+ co = next;
+ }
+ free(c); /* free the base struct as well */
+ }
+}
+
+/* get_netscape_format()
+ *
+ * Formats a string for Netscape output file, w/o a newline at the end.
+ *
+ * Function returns a char * to a formatted line. Has to be free()d
+*/
+static char *get_netscape_format(const struct Cookie *co)
+{
+ return aprintf(
+ "%s" /* httponly preamble */
+ "%s%s\t" /* domain */
+ "%s\t" /* tailmatch */
+ "%s\t" /* path */
+ "%s\t" /* secure */
+ "%" CURL_FORMAT_CURL_OFF_T "\t" /* expires */
+ "%s\t" /* name */
+ "%s", /* value */
+ co->httponly?"#HttpOnly_":"",
+ /* Make sure all domains are prefixed with a dot if they allow
+ tailmatching. This is Mozilla-style. */
+ (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
+ co->domain?co->domain:"unknown",
+ co->tailmatch?"TRUE":"FALSE",
+ co->path?co->path:"/",
+ co->secure?"TRUE":"FALSE",
+ co->expires,
+ co->name,
+ co->value?co->value:"");
+}
+
+/*
+ * cookie_output()
+ *
+ * Writes all internally known cookies to the specified file. Specify
+ * "-" as file name to write to stdout.
+ *
+ * The function returns non-zero on write failure.
+ */
+static int cookie_output(struct CookieInfo *c, const char *dumphere)
+{
+ struct Cookie *co;
+ FILE *out;
+ bool use_stdout=FALSE;
+
+ if((NULL == c) || (0 == c->numcookies))
+ /* If there are no known cookies, we don't write or even create any
+ destination file */
+ return 0;
+
+ /* at first, remove expired cookies */
+ remove_expired(c);
+
+ if(strequal("-", dumphere)) {
+ /* use stdout */
+ out = stdout;
+ use_stdout=TRUE;
+ }
+ else {
+ out = fopen(dumphere, "w");
+ if(!out)
+ return 1; /* failure */
+ }
+
+ if(c) {
+ char *format_ptr;
+
+ fputs("# Netscape HTTP Cookie File\n"
+ "# http://curl.haxx.se/docs/http-cookies.html\n"
+ "# This file was generated by libcurl! Edit at your own risk.\n\n",
+ out);
+ co = c->cookies;
+
+ while(co) {
+ format_ptr = get_netscape_format(co);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
+ co=co->next;
+ }
+ }
+
+ if(!use_stdout)
+ fclose(out);
+
+ return 0;
+}
+
+struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
+{
+ struct curl_slist *list = NULL;
+ struct curl_slist *beg;
+ struct Cookie *c;
+ char *line;
+
+ if((data->cookies == NULL) ||
+ (data->cookies->numcookies == 0))
+ return NULL;
+
+ c = data->cookies->cookies;
+
+ while(c) {
+ /* fill the list with _all_ the cookies we know */
+ line = get_netscape_format(c);
+ if(!line) {
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ beg = Curl_slist_append_nodup(list, line);
+ if(!beg) {
+ free(line);
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ list = beg;
+ c = c->next;
+ }
+
+ return list;
+}
+
+void Curl_flush_cookies(struct SessionHandle *data, int cleanup)
+{
+ if(data->set.str[STRING_COOKIEJAR]) {
+ if(data->change.cookielist) {
+ /* If there is a list of cookie files to read, do it first so that
+ we have all the told files read before we write the new jar.
+ Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
+ Curl_cookie_loadfiles(data);
+ }
+
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+
+ /* if we have a destination file for all the cookies to get dumped to */
+ if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
+ infof(data, "WARNING: failed to save cookies in %s\n",
+ data->set.str[STRING_COOKIEJAR]);
+ }
+ else {
+ if(cleanup && data->change.cookielist) {
+ /* since nothing is written, we can just free the list of cookie file
+ names */
+ curl_slist_free_all(data->change.cookielist); /* clean up list */
+ data->change.cookielist = NULL;
+ }
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ }
+
+ if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {
+ Curl_cookie_cleanup(data->cookies);
+ }
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+}
+
+#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */
diff --git a/external/libcurl_android/jni/libcurl/lib/cookie.h b/external/libcurl_android/jni/libcurl/lib/cookie.h
new file mode 100755
index 00000000..bd890827
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/cookie.h
@@ -0,0 +1,104 @@
+#ifndef HEADER_CURL_COOKIE_H
+#define HEADER_CURL_COOKIE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+struct Cookie {
+ struct Cookie *next; /* next in the chain */
+ char *name; /* <this> = value */
+ char *value; /* name = <this> */
+ char *path; /* path = <this> which is in Set-Cookie: */
+ char *spath; /* sanitized cookie path */
+ char *domain; /* domain = <this> */
+ curl_off_t expires; /* expires = <this> */
+ char *expirestr; /* the plain text version */
+ bool tailmatch; /* weather we do tail-matchning of the domain name */
+
+ /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
+ char *version; /* Version = <value> */
+ char *maxage; /* Max-Age = <value> */
+
+ bool secure; /* whether the 'secure' keyword was used */
+ bool livecookie; /* updated from a server, not a stored file */
+ bool httponly; /* true if the httponly directive is present */
+};
+
+struct CookieInfo {
+ /* linked list of cookies we know of */
+ struct Cookie *cookies;
+
+ char *filename; /* file we read from/write to */
+ bool running; /* state info, for cookie adding information */
+ long numcookies; /* number of cookies in the "jar" */
+ bool newsession; /* new session, discard session cookies on load */
+};
+
+/* This is the maximum line length we accept for a cookie line. RFC 2109
+ section 6.3 says:
+
+ "at least 4096 bytes per cookie (as measured by the size of the characters
+ that comprise the cookie non-terminal in the syntax description of the
+ Set-Cookie header)"
+
+*/
+#define MAX_COOKIE_LINE 5000
+#define MAX_COOKIE_LINE_TXT "4999"
+
+/* This is the maximum length of a cookie name we deal with: */
+#define MAX_NAME 1024
+#define MAX_NAME_TXT "1023"
+
+struct SessionHandle;
+/*
+ * Add a cookie to the internal list of cookies. The domain and path arguments
+ * are only used if the header boolean is TRUE.
+ */
+
+struct Cookie *Curl_cookie_add(struct SessionHandle *data,
+ struct CookieInfo *, bool header, char *lineptr,
+ const char *domain, const char *path);
+
+struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
+ const char *, bool);
+void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo);
+void Curl_cookie_clearall(struct CookieInfo *cookies);
+void Curl_cookie_clearsess(struct CookieInfo *cookies);
+
+#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES)
+#define Curl_cookie_list(x) NULL
+#define Curl_cookie_loadfiles(x) Curl_nop_stmt
+#define Curl_cookie_init(x,y,z,w) NULL
+#define Curl_cookie_cleanup(x) Curl_nop_stmt
+#define Curl_flush_cookies(x,y) Curl_nop_stmt
+#else
+void Curl_flush_cookies(struct SessionHandle *data, int cleanup);
+void Curl_cookie_cleanup(struct CookieInfo *);
+struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
+ const char *, struct CookieInfo *, bool);
+struct curl_slist *Curl_cookie_list(struct SessionHandle *data);
+void Curl_cookie_loadfiles(struct SessionHandle *data);
+#endif
+
+#endif /* HEADER_CURL_COOKIE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_addrinfo.c b/external/libcurl_android/jni/libcurl/lib/curl_addrinfo.c
new file mode 100755
index 00000000..10652c64
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_addrinfo.c
@@ -0,0 +1,527 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#ifdef __VMS
+# include <in.h>
+# include <inet.h>
+#endif
+
+#if defined(NETWARE) && defined(__NOVELL_LIBC__)
+# undef in_addr_t
+# define in_addr_t unsigned long
+#endif
+
+#include "curl_addrinfo.h"
+#include "inet_pton.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+
+/*
+ * Curl_freeaddrinfo()
+ *
+ * This is used to free a linked list of Curl_addrinfo structs along
+ * with all its associated allocated storage. This function should be
+ * called once for each successful call to Curl_getaddrinfo_ex() or to
+ * any function call which actually allocates a Curl_addrinfo struct.
+ */
+
+#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
+ defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
+ /* workaround icc 9.1 optimizer issue */
+# define vqualifier volatile
+#else
+# define vqualifier
+#endif
+
+void
+Curl_freeaddrinfo(Curl_addrinfo *cahead)
+{
+ Curl_addrinfo *vqualifier canext;
+ Curl_addrinfo *ca;
+
+ for(ca = cahead; ca != NULL; ca = canext) {
+
+ if(ca->ai_addr)
+ free(ca->ai_addr);
+
+ if(ca->ai_canonname)
+ free(ca->ai_canonname);
+
+ canext = ca->ai_next;
+
+ free(ca);
+ }
+}
+
+
+#ifdef HAVE_GETADDRINFO
+/*
+ * Curl_getaddrinfo_ex()
+ *
+ * This is a wrapper function around system's getaddrinfo(), with
+ * the only difference that instead of returning a linked list of
+ * addrinfo structs this one returns a linked list of Curl_addrinfo
+ * ones. The memory allocated by this function *MUST* be free'd with
+ * Curl_freeaddrinfo(). For each successful call to this function
+ * there must be an associated call later to Curl_freeaddrinfo().
+ *
+ * There should be no single call to system's getaddrinfo() in the
+ * whole library, any such call should be 'routed' through this one.
+ */
+
+int
+Curl_getaddrinfo_ex(const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ Curl_addrinfo **result)
+{
+ const struct addrinfo *ai;
+ struct addrinfo *aihead;
+ Curl_addrinfo *cafirst = NULL;
+ Curl_addrinfo *calast = NULL;
+ Curl_addrinfo *ca;
+ size_t ss_size;
+ int error;
+
+ *result = NULL; /* assume failure */
+
+ error = getaddrinfo(nodename, servname, hints, &aihead);
+ if(error)
+ return error;
+
+ /* traverse the addrinfo list */
+
+ for(ai = aihead; ai != NULL; ai = ai->ai_next) {
+
+ /* ignore elements with unsupported address family, */
+ /* settle family-specific sockaddr structure size. */
+ if(ai->ai_family == AF_INET)
+ ss_size = sizeof(struct sockaddr_in);
+#ifdef ENABLE_IPV6
+ else if(ai->ai_family == AF_INET6)
+ ss_size = sizeof(struct sockaddr_in6);
+#endif
+ else
+ continue;
+
+ /* ignore elements without required address info */
+ if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0))
+ continue;
+
+ /* ignore elements with bogus address size */
+ if((size_t)ai->ai_addrlen < ss_size)
+ continue;
+
+ if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
+ error = EAI_MEMORY;
+ break;
+ }
+
+ /* copy each structure member individually, member ordering, */
+ /* size, or padding might be different for each platform. */
+
+ ca->ai_flags = ai->ai_flags;
+ ca->ai_family = ai->ai_family;
+ ca->ai_socktype = ai->ai_socktype;
+ ca->ai_protocol = ai->ai_protocol;
+ ca->ai_addrlen = (curl_socklen_t)ss_size;
+ ca->ai_addr = NULL;
+ ca->ai_canonname = NULL;
+ ca->ai_next = NULL;
+
+ if((ca->ai_addr = malloc(ss_size)) == NULL) {
+ error = EAI_MEMORY;
+ free(ca);
+ break;
+ }
+ memcpy(ca->ai_addr, ai->ai_addr, ss_size);
+
+ if(ai->ai_canonname != NULL) {
+ if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
+ error = EAI_MEMORY;
+ free(ca->ai_addr);
+ free(ca);
+ break;
+ }
+ }
+
+ /* if the return list is empty, this becomes the first element */
+ if(!cafirst)
+ cafirst = ca;
+
+ /* add this element last in the return list */
+ if(calast)
+ calast->ai_next = ca;
+ calast = ca;
+
+ }
+
+ /* destroy the addrinfo list */
+ if(aihead)
+ freeaddrinfo(aihead);
+
+ /* if we failed, also destroy the Curl_addrinfo list */
+ if(error) {
+ Curl_freeaddrinfo(cafirst);
+ cafirst = NULL;
+ }
+ else if(!cafirst) {
+#ifdef EAI_NONAME
+ /* rfc3493 conformant */
+ error = EAI_NONAME;
+#else
+ /* rfc3493 obsoleted */
+ error = EAI_NODATA;
+#endif
+#ifdef USE_WINSOCK
+ SET_SOCKERRNO(error);
+#endif
+ }
+
+ *result = cafirst;
+
+ /* This is not a CURLcode */
+ return error;
+}
+#endif /* HAVE_GETADDRINFO */
+
+
+/*
+ * Curl_he2ai()
+ *
+ * This function returns a pointer to the first element of a newly allocated
+ * Curl_addrinfo struct linked list filled with the data of a given hostent.
+ * Curl_addrinfo is meant to work like the addrinfo struct does for a IPv6
+ * stack, but usable also for IPv4, all hosts and environments.
+ *
+ * The memory allocated by this function *MUST* be free'd later on calling
+ * Curl_freeaddrinfo(). For each successful call to this function there
+ * must be an associated call later to Curl_freeaddrinfo().
+ *
+ * Curl_addrinfo defined in "lib/curl_addrinfo.h"
+ *
+ * struct Curl_addrinfo {
+ * int ai_flags;
+ * int ai_family;
+ * int ai_socktype;
+ * int ai_protocol;
+ * curl_socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
+ * char *ai_canonname;
+ * struct sockaddr *ai_addr;
+ * struct Curl_addrinfo *ai_next;
+ * };
+ * typedef struct Curl_addrinfo Curl_addrinfo;
+ *
+ * hostent defined in <netdb.h>
+ *
+ * struct hostent {
+ * char *h_name;
+ * char **h_aliases;
+ * int h_addrtype;
+ * int h_length;
+ * char **h_addr_list;
+ * };
+ *
+ * for backward compatibility:
+ *
+ * #define h_addr h_addr_list[0]
+ */
+
+Curl_addrinfo *
+Curl_he2ai(const struct hostent *he, int port)
+{
+ Curl_addrinfo *ai;
+ Curl_addrinfo *prevai = NULL;
+ Curl_addrinfo *firstai = NULL;
+ struct sockaddr_in *addr;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *addr6;
+#endif
+ CURLcode result = CURLE_OK;
+ int i;
+ char *curr;
+
+ if(!he)
+ /* no input == no output! */
+ return NULL;
+
+ DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
+
+ for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) {
+
+ size_t ss_size;
+#ifdef ENABLE_IPV6
+ if(he->h_addrtype == AF_INET6)
+ ss_size = sizeof (struct sockaddr_in6);
+ else
+#endif
+ ss_size = sizeof (struct sockaddr_in);
+
+ if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ if((ai->ai_canonname = strdup(he->h_name)) == NULL) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(ai);
+ break;
+ }
+ if((ai->ai_addr = calloc(1, ss_size)) == NULL) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(ai->ai_canonname);
+ free(ai);
+ break;
+ }
+
+ if(!firstai)
+ /* store the pointer we want to return from this function */
+ firstai = ai;
+
+ if(prevai)
+ /* make the previous entry point to this */
+ prevai->ai_next = ai;
+
+ ai->ai_family = he->h_addrtype;
+
+ /* we return all names as STREAM, so when using this address for TFTP
+ the type must be ignored and conn->socktype be used instead! */
+ ai->ai_socktype = SOCK_STREAM;
+
+ ai->ai_addrlen = (curl_socklen_t)ss_size;
+
+ /* leave the rest of the struct filled with zero */
+
+ switch (ai->ai_family) {
+ case AF_INET:
+ addr = (void *)ai->ai_addr; /* storage area for this info */
+
+ memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
+ addr->sin_family = (unsigned short)(he->h_addrtype);
+ addr->sin_port = htons((unsigned short)port);
+ break;
+
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ addr6 = (void *)ai->ai_addr; /* storage area for this info */
+
+ memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
+ addr6->sin6_family = (unsigned short)(he->h_addrtype);
+ addr6->sin6_port = htons((unsigned short)port);
+ break;
+#endif
+ }
+
+ prevai = ai;
+ }
+
+ if(result != CURLE_OK) {
+ Curl_freeaddrinfo(firstai);
+ firstai = NULL;
+ }
+
+ return firstai;
+}
+
+
+struct namebuff {
+ struct hostent hostentry;
+ union {
+ struct in_addr ina4;
+#ifdef ENABLE_IPV6
+ struct in6_addr ina6;
+#endif
+ } addrentry;
+ char *h_addr_list[2];
+};
+
+
+/*
+ * Curl_ip2addr()
+ *
+ * This function takes an internet address, in binary form, as input parameter
+ * along with its address family and the string version of the address, and it
+ * returns a Curl_addrinfo chain filled in correctly with information for the
+ * given address/host
+ */
+
+Curl_addrinfo *
+Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
+{
+ Curl_addrinfo *ai;
+
+#if defined(__VMS) && \
+ defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
+#pragma pointer_size save
+#pragma pointer_size short
+#pragma message disable PTRMISMATCH
+#endif
+
+ struct hostent *h;
+ struct namebuff *buf;
+ char *addrentry;
+ char *hoststr;
+ size_t addrsize;
+
+ DEBUGASSERT(inaddr && hostname);
+
+ buf = malloc(sizeof(struct namebuff));
+ if(!buf)
+ return NULL;
+
+ hoststr = strdup(hostname);
+ if(!hoststr) {
+ free(buf);
+ return NULL;
+ }
+
+ switch(af) {
+ case AF_INET:
+ addrsize = sizeof(struct in_addr);
+ addrentry = (void *)&buf->addrentry.ina4;
+ memcpy(addrentry, inaddr, sizeof(struct in_addr));
+ break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ addrsize = sizeof(struct in6_addr);
+ addrentry = (void *)&buf->addrentry.ina6;
+ memcpy(addrentry, inaddr, sizeof(struct in6_addr));
+ break;
+#endif
+ default:
+ free(hoststr);
+ free(buf);
+ return NULL;
+ }
+
+ h = &buf->hostentry;
+ h->h_name = hoststr;
+ h->h_aliases = NULL;
+ h->h_addrtype = (short)af;
+ h->h_length = (short)addrsize;
+ h->h_addr_list = &buf->h_addr_list[0];
+ h->h_addr_list[0] = addrentry;
+ h->h_addr_list[1] = NULL; /* terminate list of entries */
+
+#if defined(__VMS) && \
+ defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
+#pragma pointer_size restore
+#pragma message enable PTRMISMATCH
+#endif
+
+ ai = Curl_he2ai(h, port);
+
+ free(hoststr);
+ free(buf);
+
+ return ai;
+}
+
+/*
+ * Given an IPv4 or IPv6 dotted string address, this converts it to a proper
+ * allocated Curl_addrinfo struct and returns it.
+ */
+Curl_addrinfo *Curl_str2addr(char *address, int port)
+{
+ struct in_addr in;
+ if(Curl_inet_pton(AF_INET, address, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, address, port);
+#ifdef ENABLE_IPV6
+ else {
+ struct in6_addr in6;
+ if(Curl_inet_pton(AF_INET6, address, &in6) > 0)
+ /* This is a dotted IPv6 address ::1-style */
+ return Curl_ip2addr(AF_INET6, &in6, address, port);
+ }
+#endif
+ return NULL; /* bad input format */
+}
+
+#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
+/*
+ * curl_dofreeaddrinfo()
+ *
+ * This is strictly for memory tracing and are using the same style as the
+ * family otherwise present in memdebug.c. I put these ones here since they
+ * require a bunch of structs I didn't want to include in memdebug.c
+ */
+
+void
+curl_dofreeaddrinfo(struct addrinfo *freethis,
+ int line, const char *source)
+{
+ (freeaddrinfo)(freethis);
+ curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n",
+ source, line, (void *)freethis);
+}
+#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
+
+
+#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
+/*
+ * curl_dogetaddrinfo()
+ *
+ * This is strictly for memory tracing and are using the same style as the
+ * family otherwise present in memdebug.c. I put these ones here since they
+ * require a bunch of structs I didn't want to include in memdebug.c
+ */
+
+int
+curl_dogetaddrinfo(const char *hostname,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **result,
+ int line, const char *source)
+{
+ int res=(getaddrinfo)(hostname, service, hints, result);
+ if(0 == res)
+ /* success */
+ curl_memlog("ADDR %s:%d getaddrinfo() = %p\n",
+ source, line, (void *)*result);
+ else
+ curl_memlog("ADDR %s:%d getaddrinfo() failed\n",
+ source, line);
+ return res;
+}
+#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_addrinfo.h b/external/libcurl_android/jni/libcurl/lib/curl_addrinfo.h
new file mode 100755
index 00000000..6d2b753e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_addrinfo.h
@@ -0,0 +1,97 @@
+#ifndef HEADER_CURL_ADDRINFO_H
+#define HEADER_CURL_ADDRINFO_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#ifdef __VMS
+# include <in.h>
+# include <inet.h>
+# include <stdlib.h>
+#endif
+
+
+/*
+ * Curl_addrinfo is our internal struct definition that we use to allow
+ * consistent internal handling of this data. We use this even when the
+ * system provides an addrinfo structure definition. And we use this for
+ * all sorts of IPv4 and IPV6 builds.
+ */
+
+struct Curl_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ curl_socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct Curl_addrinfo *ai_next;
+};
+typedef struct Curl_addrinfo Curl_addrinfo;
+
+void
+Curl_freeaddrinfo(Curl_addrinfo *cahead);
+
+#ifdef HAVE_GETADDRINFO
+int
+Curl_getaddrinfo_ex(const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ Curl_addrinfo **result);
+#endif
+
+Curl_addrinfo *
+Curl_he2ai(const struct hostent *he, int port);
+
+Curl_addrinfo *
+Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
+
+Curl_addrinfo *Curl_str2addr(char *dotted, int port);
+
+#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
+void
+curl_dofreeaddrinfo(struct addrinfo *freethis,
+ int line, const char *source);
+#endif
+
+#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
+int
+curl_dogetaddrinfo(const char *hostname,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **result,
+ int line, const char *source);
+#endif
+
+#endif /* HEADER_CURL_ADDRINFO_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_base64.h b/external/libcurl_android/jni/libcurl/lib/curl_base64.h
new file mode 100755
index 00000000..92896fec
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_base64.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_BASE64_H
+#define HEADER_CURL_BASE64_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+CURLcode Curl_base64_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen);
+CURLcode Curl_base64url_encode(struct SessionHandle *data,
+ const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen);
+
+CURLcode Curl_base64_decode(const char *src,
+ unsigned char **outptr, size_t *outlen);
+
+#endif /* HEADER_CURL_BASE64_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_config.h b/external/libcurl_android/jni/libcurl/lib/curl_config.h
new file mode 100755
index 00000000..27ea909b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_config.h
@@ -0,0 +1,1037 @@
+/* lib/curl_config.h. Generated from curl_config.h.in by configure. */
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+/* #undef CURL_CA_BUNDLE */
+
+/* Location of default ca path */
+/* #undef CURL_CA_PATH */
+
+/* to disable cookies support */
+/* #undef CURL_DISABLE_COOKIES */
+
+/* to disable cryptographic authentication */
+/* #undef CURL_DISABLE_CRYPTO_AUTH */
+
+/* to disable DICT */
+/* #undef CURL_DISABLE_DICT */
+
+/* to disable FILE */
+/* #undef CURL_DISABLE_FILE */
+
+/* to disable FTP */
+/* #undef CURL_DISABLE_FTP */
+
+/* to disable Gopher */
+/* #undef CURL_DISABLE_GOPHER */
+
+/* to disable HTTP */
+/* #undef CURL_DISABLE_HTTP */
+
+/* to disable IMAP */
+/* #undef CURL_DISABLE_IMAP */
+
+/* to disable LDAP */
+#define CURL_DISABLE_LDAP 1
+
+/* to disable LDAPS */
+#define CURL_DISABLE_LDAPS 1
+
+/* to disable --libcurl C code generation option */
+/* #undef CURL_DISABLE_LIBCURL_OPTION */
+
+/* to disable POP3 */
+/* #undef CURL_DISABLE_POP3 */
+
+/* to disable proxies */
+/* #undef CURL_DISABLE_PROXY */
+
+/* to disable RTSP */
+/* #undef CURL_DISABLE_RTSP */
+
+/* to disable SMTP */
+/* #undef CURL_DISABLE_SMTP */
+
+/* to disable TELNET */
+/* #undef CURL_DISABLE_TELNET */
+
+/* to disable TFTP */
+/* #undef CURL_DISABLE_TFTP */
+
+/* to disable TLS-SRP authentication */
+/* #undef CURL_DISABLE_TLS_SRP */
+
+/* to disable verbose strings */
+/* #undef CURL_DISABLE_VERBOSE_STRINGS */
+
+/* Definition to make a library symbol externally visible. */
+#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default")))
+
+/* Use Windows LDAP implementation */
+/* #undef CURL_LDAP_WIN */
+
+/* your Entropy Gathering Daemon socket pathname */
+/* #undef EGD_SOCKET */
+
+/* Define if you want to enable IPv6 support */
+/* #undef ENABLE_IPV6 */
+
+/* Define to the type of arg 2 for gethostname. */
+#define GETHOSTNAME_TYPE_ARG2 unsigned int
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Specifies the number of arguments to getservbyport_r */
+/* #undef GETSERVBYPORT_R_ARGS */
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+/* #undef GETSERVBYPORT_R_BUFSIZE */
+
+/* Define to 1 if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+/* #undef HAVE_ARPA_TFTP_H */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+#define HAVE_CLOCK_GETTIME_MONOTONIC 1
+
+/* Define to 1 if you have the closesocket function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+/* #undef HAVE_CLOSESOCKET_CAMEL */
+
+/* Define to 1 if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
+
+/* Define to 1 if you have the <crypto.h> header file. */
+/* #undef HAVE_CRYPTO_H */
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+/* #undef HAVE_CYASSL_ERROR_SSL_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* #undef HAVE_ENGINE_CLEANUP */
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <err.h> header file. */
+/* #undef HAVE_ERR_H */
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have the freeifaddrs function. */
+/* #undef HAVE_FREEIFADDRS */
+
+/* Define to 1 if you have the fsetxattr function. */
+/* #undef HAVE_FSETXATTR */
+
+/* fsetxattr() takes 5 args */
+/* #undef HAVE_FSETXATTR_5 */
+
+/* fsetxattr() takes 6 args */
+/* #undef HAVE_FSETXATTR_6 */
+
+/* Define to 1 if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the gai_strerror function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#define HAVE_GETADDRINFO_THREADSAFE 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+/* #undef HAVE_GETHOSTBYADDR_R */
+
+/* gethostbyaddr_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYADDR_R_5 */
+
+/* gethostbyaddr_r() takes 7 args */
+/* #undef HAVE_GETHOSTBYADDR_R_7 */
+
+/* gethostbyaddr_r() takes 8 args */
+/* #undef HAVE_GETHOSTBYADDR_R_8 */
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostbyname_r function. */
+#define HAVE_GETHOSTBYNAME_R 1
+
+/* gethostbyname_r() takes 3 args */
+/* #undef HAVE_GETHOSTBYNAME_R_3 */
+
+/* gethostbyname_r() takes 5 args */
+/* #undef HAVE_GETHOSTBYNAME_R_5 */
+
+/* gethostbyname_r() takes 6 args */
+#define HAVE_GETHOSTBYNAME_R_6 1
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have a working getifaddrs function. */
+/* #undef HAVE_GETIFADDRS */
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass_r' function. */
+/* #undef HAVE_GETPASS_R */
+
+/* Define to 1 if you have the `getppid' function. */
+#define HAVE_GETPPID 1
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#define HAVE_GETPROTOBYNAME 1
+
+/* Define to 1 if you have the `getpwuid' function. */
+#define HAVE_GETPWUID 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+/* #undef HAVE_GETPWUID_R */
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+/* #undef HAVE_GETSERVBYPORT_R */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+/* #undef HAVE_GLIBC_STRERROR_R */
+
+/* Define to 1 if you have a working gmtime_r function. */
+#define HAVE_GMTIME_R 1
+
+/* if you have the function gnutls_srp_verifier */
+/* #undef HAVE_GNUTLS_SRP */
+
+/* if you have GSS-API libraries */
+/* #undef HAVE_GSSAPI */
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */
+
+/* if you have GNU GSS */
+/* #undef HAVE_GSSGNU */
+
+/* if you have Heimdal */
+/* #undef HAVE_GSSHEIMDAL */
+
+/* if you have MIT Kerberos */
+/* #undef HAVE_GSSMIT */
+
+/* Define to 1 if you have the `idna_strerror' function. */
+/* #undef HAVE_IDNA_STRERROR */
+
+/* Define to 1 if you have the `idn_free' function. */
+/* #undef HAVE_IDN_FREE */
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+/* #undef HAVE_IDN_FREE_H */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+/* #undef HAVE_IFADDRS_H */
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#define HAVE_IF_NAMETOINDEX 1
+
+/* Define to 1 if you have the `inet_addr' function. */
+#define HAVE_INET_ADDR 1
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+/* #undef HAVE_INET_NTOA_R */
+
+/* inet_ntoa_r() takes 2 args */
+/* #undef HAVE_INET_NTOA_R_2 */
+
+/* inet_ntoa_r() takes 3 args */
+/* #undef HAVE_INET_NTOA_R_3 */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the lber.h header file. */
+/* #undef HAVE_LBER_H */
+
+/* Define to 1 if you have the ldapssl.h header file. */
+/* #undef HAVE_LDAPSSL_H */
+
+/* Define to 1 if you have the ldap.h header file. */
+/* #undef HAVE_LDAP_H */
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+/* #undef HAVE_LDAP_INIT_FD */
+
+/* Use LDAPS implementation */
+#define HAVE_LDAP_SSL 1
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+/* #undef HAVE_LDAP_SSL_H */
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+/* #undef HAVE_LDAP_URL_PARSE */
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+/* #undef HAVE_LIBIDN */
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+/* #undef HAVE_LIBRTMP_RTMP_H */
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+/* #undef HAVE_LIBSSH2 */
+
+/* Define to 1 if you have the `libssh2_exit' function. */
+/* #undef HAVE_LIBSSH2_EXIT */
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+/* #undef HAVE_LIBSSH2_H */
+
+/* Define to 1 if you have the `libssh2_init' function. */
+/* #undef HAVE_LIBSSH2_INIT */
+
+/* Define to 1 if you have the `libssh2_scp_send64' function. */
+/* #undef HAVE_LIBSSH2_SCP_SEND64 */
+
+/* Define to 1 if you have the `libssh2_session_handshake' function. */
+/* #undef HAVE_LIBSSH2_SESSION_HANDSHAKE */
+
+/* Define to 1 if you have the `libssh2_version' function. */
+/* #undef HAVE_LIBSSH2_VERSION */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* if zlib is available */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have a working localtime_r function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the memrchr function or macro. */
+#define HAVE_MEMRCHR 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+#define HAVE_MSG_NOSIGNAL 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+/* #undef HAVE_NI_WITHSCOPEID */
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+/* #undef HAVE_OLD_GSSMIT */
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+/* #undef HAVE_OPENSSL_ENGINE_H */
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+/* #undef HAVE_OPENSSL_ERR_H */
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+/* #undef HAVE_OPENSSL_PEM_H */
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+/* #undef HAVE_OPENSSL_PKCS12_H */
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+/* #undef HAVE_OPENSSL_RSA_H */
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+/* #undef HAVE_OPENSSL_SSL_H */
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+/* #undef HAVE_OPENSSL_X509_H */
+
+/* Define to 1 if you have the <pem.h> header file. */
+/* #undef HAVE_PEM_H */
+
+/* Define to 1 if you have the `perror' function. */
+#define HAVE_PERROR 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have a working poll function. */
+#define HAVE_POLL 1
+
+/* If you have a fine poll */
+#define HAVE_POLL_FINE 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#define HAVE_POSIX_STRERROR_R 1
+
+/* if you have <pthread.h> */
+/* #undef HAVE_PTHREAD_H */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `RAND_egd' function. */
+/* #undef HAVE_RAND_EGD */
+
+/* Define to 1 if you have the `RAND_screen' function. */
+/* #undef HAVE_RAND_SCREEN */
+
+/* Define to 1 if you have the `RAND_status' function. */
+/* #undef HAVE_RAND_STATUS */
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the <rsa.h> header file. */
+/* #undef HAVE_RSA_H */
+
+/* Define to 1 if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setmode' function. */
+/* #undef HAVE_SETMODE */
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the siginterrupt function. */
+#define HAVE_SIGINTERRUPT 1
+
+/* Define to 1 if you have the signal function. */
+/* #undef HAVE_SIGNAL */
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#define HAVE_SIGSETJMP 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */
+
+/* Define to 1 if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the socketpair function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have the <socket.h> header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* if you have the function SRP_Calc_client_key */
+/* #undef HAVE_SSLEAY_SRP */
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+/* #undef HAVE_SSLV2_CLIENT_METHOD */
+
+/* Define to 1 if you have the `SSL_CTX_set_alpn_protos' function. */
+/* #undef HAVE_SSL_CTX_SET_ALPN_PROTOS */
+
+/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */
+/* #undef HAVE_SSL_CTX_SET_ALPN_SELECT_CB */
+
+/* Define to 1 if you have the `SSL_CTX_set_next_proto_select_cb' function. */
+/* #undef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB */
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+/* #undef HAVE_SSL_GET_SHUTDOWN */
+
+/* Define to 1 if you have the <ssl.h> header file. */
+/* #undef HAVE_SSL_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the strerror_r function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the strtok_r function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the strtoll function. */
+#define HAVE_STRTOLL 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+/* #undef HAVE_SYS_FILIO_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#define HAVE_SYS_UTIME_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+/* #undef HAVE_SYS_XATTR_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+#define HAVE_TERMIO_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tld.h> header file. */
+/* #undef HAVE_TLD_H */
+
+/* Define to 1 if you have the `tld_strerror' function. */
+/* #undef HAVE_TLD_STRERROR */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#define HAVE_VARIADIC_MACROS_C99 1
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#define HAVE_VARIADIC_MACROS_GCC 1
+
+/* Define to 1 if you have the winber.h header file. */
+/* #undef HAVE_WINBER_H */
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winldap.h header file. */
+/* #undef HAVE_WINLDAP_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define this symbol if your OS supports changing the contents of argv */
+/* #undef HAVE_WRITABLE_ARGV */
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to 1 if you have the <x509.h> header file. */
+/* #undef HAVE_X509_H */
+
+/* if you have the zlib.h header file */
+#define HAVE_ZLIB_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+/* #undef NEED_LBER_H */
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_ENABLED */
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+/* #undef NTLM_WB_FILE */
+
+/* cpu-machine-OS */
+#define OS "arm-unknown-none"
+
+/* Name of package */
+#define PACKAGE "curl"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "curl"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "curl -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "curl"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* a suitable file to read random data from */
+/* #undef RANDOM_FILE */
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 unsigned int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV int
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 5 for select. */
+#define SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#define SELECT_TYPE_ARG1 int
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#define SELECT_TYPE_ARG234 fd_set *
+
+/* Define to the type of arg 5 for select. */
+#define SELECT_TYPE_ARG5 struct timeval *
+
+/* Define to the function return type for select. */
+#define SELECT_TYPE_RETV int
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 unsigned int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV int
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* The size of `long long', as computed by sizeof. */
+/* #undef SIZEOF_LONG_LONG */
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 4
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 4
+
+/* The size of `void*', as computed by sizeof. */
+#define SIZEOF_VOIDP 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to the type of arg 3 for strerror_r. */
+#define STRERROR_R_TYPE_ARG3 size_t
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to enable c-ares support */
+/* #undef USE_ARES */
+
+/* if axTLS is enabled */
+/* #undef USE_AXTLS */
+
+/* if CyaSSL is enabled */
+/* #undef USE_CYASSL */
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+/* #undef USE_DARWINSSL */
+
+/* if GnuTLS is enabled */
+/* #undef USE_GNUTLS */
+
+/* if GnuTLS uses nettle as crypto backend */
+/* #undef USE_GNUTLS_NETTLE */
+
+/* if librtmp is in use */
+/* #undef USE_LIBRTMP */
+
+/* if libSSH2 is in use */
+/* #undef USE_LIBSSH2 */
+
+/* If you want to build curl with the built-in manual */
+#define USE_MANUAL 1
+
+/* Define to enable metalink support */
+/* #undef USE_METALINK */
+
+/* if nghttp2 is in use */
+/* #undef USE_NGHTTP2 */
+
+/* if NSS is enabled */
+/* #undef USE_NSS */
+
+/* Use OpenLDAP-specific code */
+/* #undef USE_OPENLDAP */
+
+/* if OpenSSL is in use */
+/* #undef USE_OPENSSL */
+
+/* if PolarSSL is enabled */
+/* #undef USE_POLARSSL */
+
+/* to enable Windows native SSL/TLS support */
+/* #undef USE_SCHANNEL */
+
+/* if SSL is enabled */
+/* #undef USE_SSLEAY */
+
+/* if you want POSIX threaded DNS lookup */
+/* #undef USE_THREADS_POSIX */
+
+/* Use TLS-SRP authentication */
+/* #undef USE_TLS_SRP */
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+/* #undef USE_WIN32_IDN */
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+/* #undef USE_WIN32_LARGE_FILES */
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+/* #undef USE_WIN32_SMALL_FILES */
+
+/* to enable SSPI support */
+/* #undef USE_WINDOWS_SSPI */
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+/* #undef USE_YASSLEMUL */
+
+/* Version number of package */
+#define VERSION "-"
+
+/* Define to 1 to provide own prototypes. */
+/* #undef WANT_IDN_PROTOTYPES */
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* the signed version of size_t */
+/* #undef ssize_t */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_config.h.in b/external/libcurl_android/jni/libcurl/lib/curl_config.h.in
new file mode 100755
index 00000000..8273c326
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_config.h.in
@@ -0,0 +1,1036 @@
+/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Location of default ca bundle */
+#undef CURL_CA_BUNDLE
+
+/* Location of default ca path */
+#undef CURL_CA_PATH
+
+/* to disable cookies support */
+#undef CURL_DISABLE_COOKIES
+
+/* to disable cryptographic authentication */
+#undef CURL_DISABLE_CRYPTO_AUTH
+
+/* to disable DICT */
+#undef CURL_DISABLE_DICT
+
+/* to disable FILE */
+#undef CURL_DISABLE_FILE
+
+/* to disable FTP */
+#undef CURL_DISABLE_FTP
+
+/* to disable Gopher */
+#undef CURL_DISABLE_GOPHER
+
+/* to disable HTTP */
+#undef CURL_DISABLE_HTTP
+
+/* to disable IMAP */
+#undef CURL_DISABLE_IMAP
+
+/* to disable LDAP */
+#undef CURL_DISABLE_LDAP
+
+/* to disable LDAPS */
+#undef CURL_DISABLE_LDAPS
+
+/* to disable --libcurl C code generation option */
+#undef CURL_DISABLE_LIBCURL_OPTION
+
+/* to disable POP3 */
+#undef CURL_DISABLE_POP3
+
+/* to disable proxies */
+#undef CURL_DISABLE_PROXY
+
+/* to disable RTSP */
+#undef CURL_DISABLE_RTSP
+
+/* to disable SMTP */
+#undef CURL_DISABLE_SMTP
+
+/* to disable TELNET */
+#undef CURL_DISABLE_TELNET
+
+/* to disable TFTP */
+#undef CURL_DISABLE_TFTP
+
+/* to disable TLS-SRP authentication */
+#undef CURL_DISABLE_TLS_SRP
+
+/* to disable verbose strings */
+#undef CURL_DISABLE_VERBOSE_STRINGS
+
+/* Definition to make a library symbol externally visible. */
+#undef CURL_EXTERN_SYMBOL
+
+/* Use Windows LDAP implementation */
+#undef CURL_LDAP_WIN
+
+/* your Entropy Gathering Daemon socket pathname */
+#undef EGD_SOCKET
+
+/* Define if you want to enable IPv6 support */
+#undef ENABLE_IPV6
+
+/* Define to the type of arg 2 for gethostname. */
+#undef GETHOSTNAME_TYPE_ARG2
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#undef GETNAMEINFO_QUAL_ARG1
+
+/* Define to the type of arg 1 for getnameinfo. */
+#undef GETNAMEINFO_TYPE_ARG1
+
+/* Define to the type of arg 2 for getnameinfo. */
+#undef GETNAMEINFO_TYPE_ARG2
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#undef GETNAMEINFO_TYPE_ARG46
+
+/* Define to the type of arg 7 for getnameinfo. */
+#undef GETNAMEINFO_TYPE_ARG7
+
+/* Specifies the number of arguments to getservbyport_r */
+#undef GETSERVBYPORT_R_ARGS
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+#undef GETSERVBYPORT_R_BUFSIZE
+
+/* Define to 1 if you have the alarm function. */
+#undef HAVE_ALARM
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the <arpa/tftp.h> header file. */
+#undef HAVE_ARPA_TFTP_H
+
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if you have the basename function. */
+#undef HAVE_BASENAME
+
+/* Define to 1 if bool is an available type. */
+#undef HAVE_BOOL_T
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+#undef HAVE_CLOCK_GETTIME_MONOTONIC
+
+/* Define to 1 if you have the closesocket function. */
+#undef HAVE_CLOSESOCKET
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+#undef HAVE_CLOSESOCKET_CAMEL
+
+/* Define to 1 if you have the connect function. */
+#undef HAVE_CONNECT
+
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
+
+/* Define to 1 if you have the <crypto.h> header file. */
+#undef HAVE_CRYPTO_H
+
+/* Define to 1 if you have the <cyassl/error-ssl.h> header file. */
+#undef HAVE_CYASSL_ERROR_SSL_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+#undef HAVE_ENGINE_CLEANUP
+
+/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
+#undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the <err.h> header file. */
+#undef HAVE_ERR_H
+
+/* Define to 1 if you have the fcntl function. */
+#undef HAVE_FCNTL
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#undef HAVE_FCNTL_O_NONBLOCK
+
+/* Define to 1 if you have the fdopen function. */
+#undef HAVE_FDOPEN
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#undef HAVE_FREEADDRINFO
+
+/* Define to 1 if you have the freeifaddrs function. */
+#undef HAVE_FREEIFADDRS
+
+/* Define to 1 if you have the fsetxattr function. */
+#undef HAVE_FSETXATTR
+
+/* fsetxattr() takes 5 args */
+#undef HAVE_FSETXATTR_5
+
+/* fsetxattr() takes 6 args */
+#undef HAVE_FSETXATTR_6
+
+/* Define to 1 if you have the ftruncate function. */
+#undef HAVE_FTRUNCATE
+
+/* Define to 1 if you have the gai_strerror function. */
+#undef HAVE_GAI_STRERROR
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+#undef HAVE_GETADDRINFO_THREADSAFE
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#undef HAVE_GETHOSTBYADDR
+
+/* Define to 1 if you have the gethostbyaddr_r function. */
+#undef HAVE_GETHOSTBYADDR_R
+
+/* gethostbyaddr_r() takes 5 args */
+#undef HAVE_GETHOSTBYADDR_R_5
+
+/* gethostbyaddr_r() takes 7 args */
+#undef HAVE_GETHOSTBYADDR_R_7
+
+/* gethostbyaddr_r() takes 8 args */
+#undef HAVE_GETHOSTBYADDR_R_8
+
+/* Define to 1 if you have the gethostbyname function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the gethostbyname_r function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* gethostbyname_r() takes 3 args */
+#undef HAVE_GETHOSTBYNAME_R_3
+
+/* gethostbyname_r() takes 5 args */
+#undef HAVE_GETHOSTBYNAME_R_5
+
+/* gethostbyname_r() takes 6 args */
+#undef HAVE_GETHOSTBYNAME_R_6
+
+/* Define to 1 if you have the gethostname function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if you have a working getifaddrs function. */
+#undef HAVE_GETIFADDRS
+
+/* Define to 1 if you have the getnameinfo function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define to 1 if you have the `getpass_r' function. */
+#undef HAVE_GETPASS_R
+
+/* Define to 1 if you have the `getppid' function. */
+#undef HAVE_GETPPID
+
+/* Define to 1 if you have the `getprotobyname' function. */
+#undef HAVE_GETPROTOBYNAME
+
+/* Define to 1 if you have the `getpwuid' function. */
+#undef HAVE_GETPWUID
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#undef HAVE_GETPWUID_R
+
+/* Define to 1 if you have the `getrlimit' function. */
+#undef HAVE_GETRLIMIT
+
+/* Define to 1 if you have the getservbyport_r function. */
+#undef HAVE_GETSERVBYPORT_R
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have a working glibc-style strerror_r function. */
+#undef HAVE_GLIBC_STRERROR_R
+
+/* Define to 1 if you have a working gmtime_r function. */
+#undef HAVE_GMTIME_R
+
+/* if you have the function gnutls_srp_verifier */
+#undef HAVE_GNUTLS_SRP
+
+/* if you have GSS-API libraries */
+#undef HAVE_GSSAPI
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_KRB5_H
+
+/* if you have GNU GSS */
+#undef HAVE_GSSGNU
+
+/* if you have Heimdal */
+#undef HAVE_GSSHEIMDAL
+
+/* if you have MIT Kerberos */
+#undef HAVE_GSSMIT
+
+/* Define to 1 if you have the `idna_strerror' function. */
+#undef HAVE_IDNA_STRERROR
+
+/* Define to 1 if you have the `idn_free' function. */
+#undef HAVE_IDN_FREE
+
+/* Define to 1 if you have the <idn-free.h> header file. */
+#undef HAVE_IDN_FREE_H
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
+/* Define to 1 if you have the `if_nametoindex' function. */
+#undef HAVE_IF_NAMETOINDEX
+
+/* Define to 1 if you have the `inet_addr' function. */
+#undef HAVE_INET_ADDR
+
+/* Define to 1 if you have the inet_ntoa_r function. */
+#undef HAVE_INET_NTOA_R
+
+/* inet_ntoa_r() takes 2 args */
+#undef HAVE_INET_NTOA_R_2
+
+/* inet_ntoa_r() takes 3 args */
+#undef HAVE_INET_NTOA_R_3
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#undef HAVE_INET_NTOP
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#undef HAVE_INET_PTON
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the ioctl function. */
+#undef HAVE_IOCTL
+
+/* Define to 1 if you have the ioctlsocket function. */
+#undef HAVE_IOCTLSOCKET
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+#undef HAVE_IOCTLSOCKET_CAMEL
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+ */
+#undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+#undef HAVE_IOCTLSOCKET_FIONBIO
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#undef HAVE_IOCTL_FIONBIO
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#undef HAVE_IOCTL_SIOCGIFADDR
+
+/* Define to 1 if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define to 1 if you have the lber.h header file. */
+#undef HAVE_LBER_H
+
+/* Define to 1 if you have the ldapssl.h header file. */
+#undef HAVE_LDAPSSL_H
+
+/* Define to 1 if you have the ldap.h header file. */
+#undef HAVE_LDAP_H
+
+/* Define to 1 if you have the `ldap_init_fd' function. */
+#undef HAVE_LDAP_INIT_FD
+
+/* Use LDAPS implementation */
+#undef HAVE_LDAP_SSL
+
+/* Define to 1 if you have the ldap_ssl.h header file. */
+#undef HAVE_LDAP_SSL_H
+
+/* Define to 1 if you have the `ldap_url_parse' function. */
+#undef HAVE_LDAP_URL_PARSE
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define to 1 if you have the `idn' library (-lidn). */
+#undef HAVE_LIBIDN
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+#undef HAVE_LIBRESOLVE
+
+/* Define to 1 if you have the <librtmp/rtmp.h> header file. */
+#undef HAVE_LIBRTMP_RTMP_H
+
+/* Define to 1 if you have the `ssh2' library (-lssh2). */
+#undef HAVE_LIBSSH2
+
+/* Define to 1 if you have the `libssh2_exit' function. */
+#undef HAVE_LIBSSH2_EXIT
+
+/* Define to 1 if you have the <libssh2.h> header file. */
+#undef HAVE_LIBSSH2_H
+
+/* Define to 1 if you have the `libssh2_init' function. */
+#undef HAVE_LIBSSH2_INIT
+
+/* Define to 1 if you have the `libssh2_scp_send64' function. */
+#undef HAVE_LIBSSH2_SCP_SEND64
+
+/* Define to 1 if you have the `libssh2_session_handshake' function. */
+#undef HAVE_LIBSSH2_SESSION_HANDSHAKE
+
+/* Define to 1 if you have the `libssh2_version' function. */
+#undef HAVE_LIBSSH2_VERSION
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
+
+/* if zlib is available */
+#undef HAVE_LIBZ
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* if your compiler supports LL */
+#undef HAVE_LL
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if you have a working localtime_r function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#undef HAVE_LONGLONG
+
+/* Define to 1 if you have the malloc.h header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the memory.h header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the memrchr function or macro. */
+#undef HAVE_MEMRCHR
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+#undef HAVE_MSG_NOSIGNAL
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+#undef HAVE_NGHTTP2_NGHTTP2_H
+
+/* Define to 1 if NI_WITHSCOPEID exists and works. */
+#undef HAVE_NI_WITHSCOPEID
+
+/* if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE
+ */
+#undef HAVE_OLD_GSSMIT
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+#undef HAVE_OPENSSL_CRYPTO_H
+
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+#undef HAVE_OPENSSL_ENGINE_H
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+#undef HAVE_OPENSSL_ERR_H
+
+/* Define to 1 if you have the <openssl/pem.h> header file. */
+#undef HAVE_OPENSSL_PEM_H
+
+/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
+#undef HAVE_OPENSSL_PKCS12_H
+
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#undef HAVE_OPENSSL_RSA_H
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define to 1 if you have the <openssl/x509.h> header file. */
+#undef HAVE_OPENSSL_X509_H
+
+/* Define to 1 if you have the <pem.h> header file. */
+#undef HAVE_PEM_H
+
+/* Define to 1 if you have the `perror' function. */
+#undef HAVE_PERROR
+
+/* Define to 1 if you have the `pipe' function. */
+#undef HAVE_PIPE
+
+/* Define to 1 if you have a working poll function. */
+#undef HAVE_POLL
+
+/* If you have a fine poll */
+#undef HAVE_POLL_FINE
+
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
+/* Define to 1 if you have a working POSIX-style strerror_r function. */
+#undef HAVE_POSIX_STRERROR_R
+
+/* if you have <pthread.h> */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define to 1 if you have the `RAND_egd' function. */
+#undef HAVE_RAND_EGD
+
+/* Define to 1 if you have the `RAND_screen' function. */
+#undef HAVE_RAND_SCREEN
+
+/* Define to 1 if you have the `RAND_status' function. */
+#undef HAVE_RAND_STATUS
+
+/* Define to 1 if you have the recv function. */
+#undef HAVE_RECV
+
+/* Define to 1 if you have the <rsa.h> header file. */
+#undef HAVE_RSA_H
+
+/* Define to 1 if you have the select function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the send function. */
+#undef HAVE_SEND
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#undef HAVE_SETJMP_H
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the `setmode' function. */
+#undef HAVE_SETMODE
+
+/* Define to 1 if you have the `setrlimit' function. */
+#undef HAVE_SETRLIMIT
+
+/* Define to 1 if you have the setsockopt function. */
+#undef HAVE_SETSOCKOPT
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+#undef HAVE_SETSOCKOPT_SO_NONBLOCK
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define to 1 if you have the sigaction function. */
+#undef HAVE_SIGACTION
+
+/* Define to 1 if you have the siginterrupt function. */
+#undef HAVE_SIGINTERRUPT
+
+/* Define to 1 if you have the signal function. */
+#undef HAVE_SIGNAL
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if you have the sigsetjmp function or macro. */
+#undef HAVE_SIGSETJMP
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#undef HAVE_SIG_ATOMIC_T
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+#undef HAVE_SIG_ATOMIC_T_VOLATILE
+
+/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
+#undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+
+/* Define to 1 if you have the socket function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if you have the socketpair function. */
+#undef HAVE_SOCKETPAIR
+
+/* Define to 1 if you have the <socket.h> header file. */
+#undef HAVE_SOCKET_H
+
+/* if you have the function SRP_Calc_client_key */
+#undef HAVE_SSLEAY_SRP
+
+/* Define to 1 if you have the `SSLv2_client_method' function. */
+#undef HAVE_SSLV2_CLIENT_METHOD
+
+/* Define to 1 if you have the `SSL_CTX_set_alpn_protos' function. */
+#undef HAVE_SSL_CTX_SET_ALPN_PROTOS
+
+/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */
+#undef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
+
+/* Define to 1 if you have the `SSL_CTX_set_next_proto_select_cb' function. */
+#undef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
+
+/* Define to 1 if you have the `SSL_get_shutdown' function. */
+#undef HAVE_SSL_GET_SHUTDOWN
+
+/* Define to 1 if you have the <ssl.h> header file. */
+#undef HAVE_SSL_H
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the strcasecmp function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the strcmpi function. */
+#undef HAVE_STRCMPI
+
+/* Define to 1 if you have the strdup function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the strerror_r function. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the stricmp function. */
+#undef HAVE_STRICMP
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the strncasecmp function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the strncmpi function. */
+#undef HAVE_STRNCMPI
+
+/* Define to 1 if you have the strnicmp function. */
+#undef HAVE_STRNICMP
+
+/* Define to 1 if you have the <stropts.h> header file. */
+#undef HAVE_STROPTS_H
+
+/* Define to 1 if you have the strstr function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the strtok_r function. */
+#undef HAVE_STRTOK_R
+
+/* Define to 1 if you have the strtoll function. */
+#undef HAVE_STRTOLL
+
+/* if struct sockaddr_storage is defined */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define to 1 if you have the timeval struct. */
+#undef HAVE_STRUCT_TIMEVAL
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#undef HAVE_SYS_POLL_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#undef HAVE_SYS_UIO_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#undef HAVE_SYS_UTIME_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#undef HAVE_SYS_XATTR_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <tld.h> header file. */
+#undef HAVE_TLD_H
+
+/* Define to 1 if you have the `tld_strerror' function. */
+#undef HAVE_TLD_STRERROR
+
+/* Define to 1 if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `utime' function. */
+#undef HAVE_UTIME
+
+/* Define to 1 if you have the <utime.h> header file. */
+#undef HAVE_UTIME_H
+
+/* Define to 1 if compiler supports C99 variadic macro style. */
+#undef HAVE_VARIADIC_MACROS_C99
+
+/* Define to 1 if compiler supports old gcc variadic macro style. */
+#undef HAVE_VARIADIC_MACROS_GCC
+
+/* Define to 1 if you have the winber.h header file. */
+#undef HAVE_WINBER_H
+
+/* Define to 1 if you have the windows.h header file. */
+#undef HAVE_WINDOWS_H
+
+/* Define to 1 if you have the winldap.h header file. */
+#undef HAVE_WINLDAP_H
+
+/* Define to 1 if you have the winsock2.h header file. */
+#undef HAVE_WINSOCK2_H
+
+/* Define to 1 if you have the winsock.h header file. */
+#undef HAVE_WINSOCK_H
+
+/* Define this symbol if your OS supports changing the contents of argv */
+#undef HAVE_WRITABLE_ARGV
+
+/* Define to 1 if you have the writev function. */
+#undef HAVE_WRITEV
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+#undef HAVE_WS2TCPIP_H
+
+/* Define to 1 if you have the <x509.h> header file. */
+#undef HAVE_X509_H
+
+/* if you have the zlib.h header file */
+#undef HAVE_ZLIB_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if you need the lber.h header file even with ldap.h */
+#undef NEED_LBER_H
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+#undef NEED_MALLOC_H
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+#undef NEED_MEMORY_H
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+#undef NEED_REENTRANT
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+#undef NEED_THREAD_SAFE
+
+/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */
+#undef NTLM_WB_ENABLED
+
+/* Define absolute filename for winbind's ntlm_auth helper. */
+#undef NTLM_WB_FILE
+
+/* cpu-machine-OS */
+#undef OS
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* a suitable file to read random data from */
+#undef RANDOM_FILE
+
+/* Define to the type of arg 1 for recv. */
+#undef RECV_TYPE_ARG1
+
+/* Define to the type of arg 2 for recv. */
+#undef RECV_TYPE_ARG2
+
+/* Define to the type of arg 3 for recv. */
+#undef RECV_TYPE_ARG3
+
+/* Define to the type of arg 4 for recv. */
+#undef RECV_TYPE_ARG4
+
+/* Define to the function return type for recv. */
+#undef RECV_TYPE_RETV
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to the type qualifier of arg 5 for select. */
+#undef SELECT_QUAL_ARG5
+
+/* Define to the type of arg 1 for select. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for select. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for select. */
+#undef SELECT_TYPE_ARG5
+
+/* Define to the function return type for select. */
+#undef SELECT_TYPE_RETV
+
+/* Define to the type qualifier of arg 2 for send. */
+#undef SEND_QUAL_ARG2
+
+/* Define to the type of arg 1 for send. */
+#undef SEND_TYPE_ARG1
+
+/* Define to the type of arg 2 for send. */
+#undef SEND_TYPE_ARG2
+
+/* Define to the type of arg 3 for send. */
+#undef SEND_TYPE_ARG3
+
+/* Define to the type of arg 4 for send. */
+#undef SEND_TYPE_ARG4
+
+/* Define to the function return type for send. */
+#undef SEND_TYPE_RETV
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
+/* The size of `off_t', as computed by sizeof. */
+#undef SIZEOF_OFF_T
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of `size_t', as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
+/* The size of `time_t', as computed by sizeof. */
+#undef SIZEOF_TIME_T
+
+/* The size of `void*', as computed by sizeof. */
+#undef SIZEOF_VOIDP
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to the type of arg 3 for strerror_r. */
+#undef STRERROR_R_TYPE_ARG3
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to enable c-ares support */
+#undef USE_ARES
+
+/* if axTLS is enabled */
+#undef USE_AXTLS
+
+/* if CyaSSL is enabled */
+#undef USE_CYASSL
+
+/* to enable iOS/Mac OS X native SSL/TLS support */
+#undef USE_DARWINSSL
+
+/* if GnuTLS is enabled */
+#undef USE_GNUTLS
+
+/* if GnuTLS uses nettle as crypto backend */
+#undef USE_GNUTLS_NETTLE
+
+/* if librtmp is in use */
+#undef USE_LIBRTMP
+
+/* if libSSH2 is in use */
+#undef USE_LIBSSH2
+
+/* If you want to build curl with the built-in manual */
+#undef USE_MANUAL
+
+/* Define to enable metalink support */
+#undef USE_METALINK
+
+/* if nghttp2 is in use */
+#undef USE_NGHTTP2
+
+/* if NSS is enabled */
+#undef USE_NSS
+
+/* Use OpenLDAP-specific code */
+#undef USE_OPENLDAP
+
+/* if OpenSSL is in use */
+#undef USE_OPENSSL
+
+/* if PolarSSL is enabled */
+#undef USE_POLARSSL
+
+/* to enable Windows native SSL/TLS support */
+#undef USE_SCHANNEL
+
+/* if SSL is enabled */
+#undef USE_SSLEAY
+
+/* if you want POSIX threaded DNS lookup */
+#undef USE_THREADS_POSIX
+
+/* Use TLS-SRP authentication */
+#undef USE_TLS_SRP
+
+/* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
+#undef USE_WIN32_IDN
+
+/* Define to 1 if you are building a Windows target with large file support.
+ */
+#undef USE_WIN32_LARGE_FILES
+
+/* Define to 1 if you are building a Windows target without large file
+ support. */
+#undef USE_WIN32_SMALL_FILES
+
+/* to enable SSPI support */
+#undef USE_WINDOWS_SSPI
+
+/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
+#undef USE_YASSLEMUL
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 to provide own prototypes. */
+#undef WANT_IDN_PROTOTYPES
+
+/* Define to avoid automatic inclusion of winsock.h */
+#undef WIN32_LEAN_AND_MEAN
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+#undef in_addr_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* the signed version of size_t */
+#undef ssize_t
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_fnmatch.c b/external/libcurl_android/jni/libcurl/lib/curl_fnmatch.c
new file mode 100755
index 00000000..63f67b9a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_fnmatch.c
@@ -0,0 +1,427 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "curl_fnmatch.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
+#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
+
+#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN
+
+#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1)
+#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2)
+#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3)
+#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4)
+#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5)
+#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6)
+#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7)
+#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8)
+#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9)
+#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
+
+typedef enum {
+ CURLFNM_LOOP_DEFAULT = 0,
+ CURLFNM_LOOP_BACKSLASH
+} loop_state;
+
+typedef enum {
+ CURLFNM_SCHS_DEFAULT = 0,
+ CURLFNM_SCHS_MAYRANGE,
+ CURLFNM_SCHS_MAYRANGE2,
+ CURLFNM_SCHS_RIGHTBR,
+ CURLFNM_SCHS_RIGHTBRLEFTBR
+} setcharset_state;
+
+typedef enum {
+ CURLFNM_PKW_INIT = 0,
+ CURLFNM_PKW_DDOT
+} parsekey_state;
+
+#define SETCHARSET_OK 1
+#define SETCHARSET_FAIL 0
+
+static int parsekeyword(unsigned char **pattern, unsigned char *charset)
+{
+ parsekey_state state = CURLFNM_PKW_INIT;
+#define KEYLEN 10
+ char keyword[KEYLEN] = { 0 };
+ int found = FALSE;
+ int i;
+ unsigned char *p = *pattern;
+ for(i = 0; !found; i++) {
+ char c = *p++;
+ if(i >= KEYLEN)
+ return SETCHARSET_FAIL;
+ switch(state) {
+ case CURLFNM_PKW_INIT:
+ if(ISALPHA(c) && ISLOWER(c))
+ keyword[i] = c;
+ else if(c == ':')
+ state = CURLFNM_PKW_DDOT;
+ else
+ return 0;
+ break;
+ case CURLFNM_PKW_DDOT:
+ if(c == ']')
+ found = TRUE;
+ else
+ return SETCHARSET_FAIL;
+ }
+ }
+#undef KEYLEN
+
+ *pattern = p; /* move caller's pattern pointer */
+ if(strcmp(keyword, "digit") == 0)
+ charset[CURLFNM_DIGIT] = 1;
+ else if(strcmp(keyword, "alnum") == 0)
+ charset[CURLFNM_ALNUM] = 1;
+ else if(strcmp(keyword, "alpha") == 0)
+ charset[CURLFNM_ALPHA] = 1;
+ else if(strcmp(keyword, "xdigit") == 0)
+ charset[CURLFNM_XDIGIT] = 1;
+ else if(strcmp(keyword, "print") == 0)
+ charset[CURLFNM_PRINT] = 1;
+ else if(strcmp(keyword, "graph") == 0)
+ charset[CURLFNM_GRAPH] = 1;
+ else if(strcmp(keyword, "space") == 0)
+ charset[CURLFNM_SPACE] = 1;
+ else if(strcmp(keyword, "blank") == 0)
+ charset[CURLFNM_BLANK] = 1;
+ else if(strcmp(keyword, "upper") == 0)
+ charset[CURLFNM_UPPER] = 1;
+ else if(strcmp(keyword, "lower") == 0)
+ charset[CURLFNM_LOWER] = 1;
+ else
+ return SETCHARSET_FAIL;
+ return SETCHARSET_OK;
+}
+
+/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
+static int setcharset(unsigned char **p, unsigned char *charset)
+{
+ setcharset_state state = CURLFNM_SCHS_DEFAULT;
+ unsigned char rangestart = 0;
+ unsigned char lastchar = 0;
+ bool something_found = FALSE;
+ unsigned char c;
+ for(;;) {
+ c = **p;
+ switch(state) {
+ case CURLFNM_SCHS_DEFAULT:
+ if(ISALNUM(c)) { /* ASCII value */
+ rangestart = c;
+ charset[c] = 1;
+ (*p)++;
+ state = CURLFNM_SCHS_MAYRANGE;
+ something_found = TRUE;
+ }
+ else if(c == ']') {
+ if(something_found)
+ return SETCHARSET_OK;
+ else
+ something_found = TRUE;
+ state = CURLFNM_SCHS_RIGHTBR;
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == '[') {
+ char c2 = *((*p)+1);
+ if(c2 == ':') { /* there has to be a keyword */
+ (*p) += 2;
+ if(parsekeyword(p, charset)) {
+ state = CURLFNM_SCHS_DEFAULT;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ else {
+ charset[c] = 1;
+ (*p)++;
+ }
+ something_found = TRUE;
+ }
+ else if(c == '?' || c == '*') {
+ something_found = TRUE;
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == '^' || c == '!') {
+ if(!something_found) {
+ if(charset[CURLFNM_NEGATE]) {
+ charset[c] = 1;
+ something_found = TRUE;
+ }
+ else
+ charset[CURLFNM_NEGATE] = 1; /* negate charset */
+ }
+ else
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == '\\') {
+ c = *(++(*p));
+ if(ISPRINT((c))) {
+ something_found = TRUE;
+ state = CURLFNM_SCHS_MAYRANGE;
+ charset[c] = 1;
+ rangestart = c;
+ (*p)++;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ else if(c == '\0') {
+ return SETCHARSET_FAIL;
+ }
+ else {
+ charset[c] = 1;
+ (*p)++;
+ something_found = TRUE;
+ }
+ break;
+ case CURLFNM_SCHS_MAYRANGE:
+ if(c == '-') {
+ charset[c] = 1;
+ (*p)++;
+ lastchar = '-';
+ state = CURLFNM_SCHS_MAYRANGE2;
+ }
+ else if(c == '[') {
+ state = CURLFNM_SCHS_DEFAULT;
+ }
+ else if(ISALNUM(c)) {
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == '\\') {
+ c = *(++(*p));
+ if(ISPRINT(c)) {
+ charset[c] = 1;
+ (*p)++;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ else if(c == ']') {
+ return SETCHARSET_OK;
+ }
+ else
+ return SETCHARSET_FAIL;
+ break;
+ case CURLFNM_SCHS_MAYRANGE2:
+ if(c == '\\') {
+ c = *(++(*p));
+ if(!ISPRINT(c))
+ return SETCHARSET_FAIL;
+ }
+ if(c == ']') {
+ return SETCHARSET_OK;
+ }
+ else if(c == '\\') {
+ c = *(++(*p));
+ if(ISPRINT(c)) {
+ charset[c] = 1;
+ state = CURLFNM_SCHS_DEFAULT;
+ (*p)++;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ if(c >= rangestart) {
+ if((ISLOWER(c) && ISLOWER(rangestart)) ||
+ (ISDIGIT(c) && ISDIGIT(rangestart)) ||
+ (ISUPPER(c) && ISUPPER(rangestart))) {
+ charset[lastchar] = 0;
+ rangestart++;
+ while(rangestart++ <= c)
+ charset[rangestart-1] = 1;
+ (*p)++;
+ state = CURLFNM_SCHS_DEFAULT;
+ }
+ else
+ return SETCHARSET_FAIL;
+ }
+ break;
+ case CURLFNM_SCHS_RIGHTBR:
+ if(c == '[') {
+ state = CURLFNM_SCHS_RIGHTBRLEFTBR;
+ charset[c] = 1;
+ (*p)++;
+ }
+ else if(c == ']') {
+ return SETCHARSET_OK;
+ }
+ else if(c == '\0') {
+ return SETCHARSET_FAIL;
+ }
+ else if(ISPRINT(c)) {
+ charset[c] = 1;
+ (*p)++;
+ state = CURLFNM_SCHS_DEFAULT;
+ }
+ else
+ /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a
+ * nonsense warning 'statement not reached' at end of the fnc when
+ * compiling on Solaris */
+ goto fail;
+ break;
+ case CURLFNM_SCHS_RIGHTBRLEFTBR:
+ if(c == ']') {
+ return SETCHARSET_OK;
+ }
+ else {
+ state = CURLFNM_SCHS_DEFAULT;
+ charset[c] = 1;
+ (*p)++;
+ }
+ break;
+ }
+ }
+fail:
+ return SETCHARSET_FAIL;
+}
+
+static int loop(const unsigned char *pattern, const unsigned char *string)
+{
+ loop_state state = CURLFNM_LOOP_DEFAULT;
+ unsigned char *p = (unsigned char *)pattern;
+ unsigned char *s = (unsigned char *)string;
+ unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
+ int rc = 0;
+
+ for(;;) {
+ switch(state) {
+ case CURLFNM_LOOP_DEFAULT:
+ if(*p == '*') {
+ while(*(p+1) == '*') /* eliminate multiple stars */
+ p++;
+ if(*s == '\0' && *(p+1) == '\0')
+ return CURL_FNMATCH_MATCH;
+ rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */
+ if(rc == CURL_FNMATCH_MATCH)
+ return CURL_FNMATCH_MATCH;
+ if(*s) /* let the star eat up one character */
+ s++;
+ else
+ return CURL_FNMATCH_NOMATCH;
+ }
+ else if(*p == '?') {
+ if(ISPRINT(*s)) {
+ s++;
+ p++;
+ }
+ else if(*s == '\0')
+ return CURL_FNMATCH_NOMATCH;
+ else
+ return CURL_FNMATCH_FAIL; /* cannot deal with other character */
+ }
+ else if(*p == '\0') {
+ if(*s == '\0')
+ return CURL_FNMATCH_MATCH;
+ else
+ return CURL_FNMATCH_NOMATCH;
+ }
+ else if(*p == '\\') {
+ state = CURLFNM_LOOP_BACKSLASH;
+ p++;
+ }
+ else if(*p == '[') {
+ unsigned char *pp = p+1; /* cannot handle with pointer to register */
+ if(setcharset(&pp, charset)) {
+ int found = FALSE;
+ if(charset[(unsigned int)*s])
+ found = TRUE;
+ else if(charset[CURLFNM_ALNUM])
+ found = ISALNUM(*s);
+ else if(charset[CURLFNM_ALPHA])
+ found = ISALPHA(*s);
+ else if(charset[CURLFNM_DIGIT])
+ found = ISDIGIT(*s);
+ else if(charset[CURLFNM_XDIGIT])
+ found = ISXDIGIT(*s);
+ else if(charset[CURLFNM_PRINT])
+ found = ISPRINT(*s);
+ else if(charset[CURLFNM_SPACE])
+ found = ISSPACE(*s);
+ else if(charset[CURLFNM_UPPER])
+ found = ISUPPER(*s);
+ else if(charset[CURLFNM_LOWER])
+ found = ISLOWER(*s);
+ else if(charset[CURLFNM_BLANK])
+ found = ISBLANK(*s);
+ else if(charset[CURLFNM_GRAPH])
+ found = ISGRAPH(*s);
+
+ if(charset[CURLFNM_NEGATE])
+ found = !found;
+
+ if(found) {
+ p = pp+1;
+ s++;
+ memset(charset, 0, CURLFNM_CHSET_SIZE);
+ }
+ else
+ return CURL_FNMATCH_NOMATCH;
+ }
+ else
+ return CURL_FNMATCH_FAIL;
+ }
+ else {
+ if(*p++ != *s++)
+ return CURL_FNMATCH_NOMATCH;
+ }
+ break;
+ case CURLFNM_LOOP_BACKSLASH:
+ if(ISPRINT(*p)) {
+ if(*p++ == *s++)
+ state = CURLFNM_LOOP_DEFAULT;
+ else
+ return CURL_FNMATCH_NOMATCH;
+ }
+ else
+ return CURL_FNMATCH_FAIL;
+ break;
+ }
+ }
+}
+
+/*
+ * @unittest: 1307
+ */
+int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
+{
+ (void)ptr; /* the argument is specified by the curl_fnmatch_callback
+ prototype, but not used by Curl_fnmatch() */
+ if(!pattern || !string) {
+ return CURL_FNMATCH_FAIL;
+ }
+ return loop((unsigned char *)pattern, (unsigned char *)string);
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_fnmatch.h b/external/libcurl_android/jni/libcurl/lib/curl_fnmatch.h
new file mode 100755
index 00000000..6335d031
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_fnmatch.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_FNMATCH_H
+#define HEADER_CURL_FNMATCH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#define CURL_FNMATCH_MATCH 0
+#define CURL_FNMATCH_NOMATCH 1
+#define CURL_FNMATCH_FAIL 2
+
+/* default pattern matching function
+ * =================================
+ * Implemented with recursive backtracking, if you want to use Curl_fnmatch,
+ * please note that there is not implemented UTF/UNICODE support.
+ *
+ * Implemented features:
+ * '?' notation, does not match UTF characters
+ * '*' can also work with UTF string
+ * [a-zA-Z0-9] enumeration support
+ *
+ * keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space
+ * and upper (use as "[[:alnum:]]")
+ */
+int Curl_fnmatch(void *ptr, const char *pattern, const char *string);
+
+#endif /* HEADER_CURL_FNMATCH_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_gethostname.c b/external/libcurl_android/jni/libcurl/lib/curl_gethostname.c
new file mode 100755
index 00000000..ded1e6f9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_gethostname.c
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "curl_gethostname.h"
+
+/*
+ * Curl_gethostname() is a wrapper around gethostname() which allows
+ * overriding the host name that the function would normally return.
+ * This capability is used by the test suite to verify exact matching
+ * of NTLM authentication, which exercises libcurl's MD4 and DES code
+ * as well as by the SMTP module when a hostname is not provided.
+ *
+ * For libcurl debug enabled builds host name overriding takes place
+ * when environment variable CURL_GETHOSTNAME is set, using the value
+ * held by the variable to override returned host name.
+ *
+ * Note: The function always returns the un-qualified hostname rather
+ * than being provider dependent.
+ *
+ * For libcurl shared library release builds the test suite preloads
+ * another shared library named libhostname using the LD_PRELOAD
+ * mechanism which intercepts, and might override, the gethostname()
+ * function call. In this case a given platform must support the
+ * LD_PRELOAD mechanism and additionally have environment variable
+ * CURL_GETHOSTNAME set in order to override the returned host name.
+ *
+ * For libcurl static library release builds no overriding takes place.
+ */
+
+int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
+
+#ifndef HAVE_GETHOSTNAME
+
+ /* Allow compilation and return failure when unavailable */
+ (void) name;
+ (void) namelen;
+ return -1;
+
+#else
+ int err;
+ char* dot;
+
+#ifdef DEBUGBUILD
+
+ /* Override host name when environment variable CURL_GETHOSTNAME is set */
+ const char *force_hostname = getenv("CURL_GETHOSTNAME");
+ if(force_hostname) {
+ strncpy(name, force_hostname, namelen);
+ err = 0;
+ }
+ else {
+ name[0] = '\0';
+ err = gethostname(name, namelen);
+ }
+
+#else /* DEBUGBUILD */
+
+ /* The call to system's gethostname() might get intercepted by the
+ libhostname library when libcurl is built as a non-debug shared
+ library when running the test suite. */
+ name[0] = '\0';
+ err = gethostname(name, namelen);
+
+#endif
+
+ name[namelen - 1] = '\0';
+
+ if(err)
+ return err;
+
+ /* Truncate domain, leave only machine name */
+ dot = strchr(name, '.');
+ if(dot)
+ *dot = '\0';
+
+ return 0;
+#endif
+
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_gethostname.h b/external/libcurl_android/jni/libcurl/lib/curl_gethostname.h
new file mode 100755
index 00000000..48740f62
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_gethostname.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_GETHOSTNAME_H
+#define HEADER_CURL_GETHOSTNAME_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Hostname buffer size */
+#define HOSTNAME_MAX 1024
+
+/* This returns the local machine's un-qualified hostname */
+int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen);
+
+#endif /* HEADER_CURL_GETHOSTNAME_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_gssapi.c b/external/libcurl_android/jni/libcurl/lib/curl_gssapi.c
new file mode 100755
index 00000000..232b3ef9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_gssapi.c
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2011 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_GSSAPI
+
+#include "curl_gssapi.h"
+#include "sendf.h"
+
+static const char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02";
+gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes };
+static const char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02";
+gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes };
+
+OM_uint32 Curl_gss_init_sec_context(
+ struct SessionHandle *data,
+ OM_uint32 *minor_status,
+ gss_ctx_id_t *context,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags)
+{
+ OM_uint32 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
+
+ if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) {
+#ifdef GSS_C_DELEG_POLICY_FLAG
+ req_flags |= GSS_C_DELEG_POLICY_FLAG;
+#else
+ infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
+ "compiled in\n");
+#endif
+ }
+
+ if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG)
+ req_flags |= GSS_C_DELEG_FLAG;
+
+ return gss_init_sec_context(minor_status,
+ GSS_C_NO_CREDENTIAL, /* cred_handle */
+ context,
+ target_name,
+ mech_type,
+ req_flags,
+ 0, /* time_req */
+ input_chan_bindings,
+ input_token,
+ NULL, /* actual_mech_type */
+ output_token,
+ ret_flags,
+ NULL /* time_rec */);
+}
+
+#endif /* HAVE_GSSAPI */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_gssapi.h b/external/libcurl_android/jni/libcurl/lib/curl_gssapi.h
new file mode 100755
index 00000000..b91bd7ea
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_gssapi.h
@@ -0,0 +1,60 @@
+#ifndef HEADER_CURL_GSSAPI_H
+#define HEADER_CURL_GSSAPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "urldata.h"
+
+#ifdef HAVE_GSSAPI
+
+#ifdef HAVE_GSSGNU
+# include <gss.h>
+#elif defined HAVE_GSSMIT
+ /* MIT style */
+# include <gssapi/gssapi.h>
+# include <gssapi/gssapi_generic.h>
+# include <gssapi/gssapi_krb5.h>
+#else
+ /* Heimdal-style */
+# include <gssapi.h>
+#endif
+
+extern gss_OID_desc Curl_spnego_mech_oid;
+extern gss_OID_desc Curl_krb5_mech_oid;
+
+/* Common method for using GSS-API */
+
+OM_uint32 Curl_gss_init_sec_context(
+ struct SessionHandle *data,
+ OM_uint32 *minor_status,
+ gss_ctx_id_t *context,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags);
+
+#endif /* HAVE_GSSAPI */
+
+#endif /* HEADER_CURL_GSSAPI_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_hmac.h b/external/libcurl_android/jni/libcurl/lib/curl_hmac.h
new file mode 100755
index 00000000..9b65c8c2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_hmac.h
@@ -0,0 +1,67 @@
+#ifndef HEADER_CURL_HMAC_H
+#define HEADER_CURL_HMAC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+
+typedef void (* HMAC_hinit_func)(void * context);
+typedef void (* HMAC_hupdate_func)(void * context,
+ const unsigned char * data,
+ unsigned int len);
+typedef void (* HMAC_hfinal_func)(unsigned char * result, void * context);
+
+
+/* Per-hash function HMAC parameters. */
+
+typedef struct {
+ HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */
+ HMAC_hupdate_func hmac_hupdate; /* Update context with data. */
+ HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */
+ unsigned int hmac_ctxtsize; /* Context structure size. */
+ unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */
+ unsigned int hmac_resultlen; /* Result length (bytes). */
+} HMAC_params;
+
+
+/* HMAC computation context. */
+
+typedef struct {
+ const HMAC_params * hmac_hash; /* Hash function definition. */
+ void * hmac_hashctxt1; /* Hash function context 1. */
+ void * hmac_hashctxt2; /* Hash function context 2. */
+} HMAC_context;
+
+
+/* Prototypes. */
+
+HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams,
+ const unsigned char * key,
+ unsigned int keylen);
+int Curl_HMAC_update(HMAC_context * context,
+ const unsigned char * data,
+ unsigned int len);
+int Curl_HMAC_final(HMAC_context * context, unsigned char * result);
+
+#endif
+
+#endif /* HEADER_CURL_HMAC_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ldap.h b/external/libcurl_android/jni/libcurl/lib/curl_ldap.h
new file mode 100755
index 00000000..93fb4b07
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ldap.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_LDAP_H
+#define HEADER_CURL_LDAP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_LDAP
+extern const struct Curl_handler Curl_handler_ldap;
+
+#if !defined(CURL_DISABLE_LDAPS) && \
+ ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+ (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+extern const struct Curl_handler Curl_handler_ldaps;
+#endif
+
+#endif
+#endif /* HEADER_CURL_LDAP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_md4.h b/external/libcurl_android/jni/libcurl/lib/curl_md4.h
new file mode 100755
index 00000000..b0be9cf6
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_md4.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_MD4_H
+#define HEADER_CURL_MD4_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/* NSS crypto library does not provide the MD4 hash algorithm, so that we have
+ * a local implementation of it */
+#ifdef USE_NSS
+void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
+#endif /* USE_NSS */
+
+#endif /* HEADER_CURL_MD4_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_md5.h b/external/libcurl_android/jni/libcurl/lib/curl_md5.h
new file mode 100755
index 00000000..9c0e0b5e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_md5.h
@@ -0,0 +1,63 @@
+#ifndef HEADER_CURL_MD5_H
+#define HEADER_CURL_MD5_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include "curl_hmac.h"
+
+#define MD5_DIGEST_LEN 16
+
+typedef void (* Curl_MD5_init_func)(void *context);
+typedef void (* Curl_MD5_update_func)(void *context,
+ const unsigned char *data,
+ unsigned int len);
+typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context);
+
+typedef struct {
+ Curl_MD5_init_func md5_init_func; /* Initialize context procedure */
+ Curl_MD5_update_func md5_update_func; /* Update context with data */
+ Curl_MD5_final_func md5_final_func; /* Get final result procedure */
+ unsigned int md5_ctxtsize; /* Context structure size */
+ unsigned int md5_resultlen; /* Result length (bytes) */
+} MD5_params;
+
+typedef struct {
+ const MD5_params *md5_hash; /* Hash function definition */
+ void *md5_hashctx; /* Hash function context */
+} MD5_context;
+
+extern const MD5_params Curl_DIGEST_MD5[1];
+extern const HMAC_params Curl_HMAC_MD5[1];
+
+void Curl_md5it(unsigned char *output,
+ const unsigned char *input);
+
+MD5_context * Curl_MD5_init(const MD5_params *md5params);
+int Curl_MD5_update(MD5_context *context,
+ const unsigned char *data,
+ unsigned int len);
+int Curl_MD5_final(MD5_context *context, unsigned char *result);
+
+#endif
+
+#endif /* HEADER_CURL_MD5_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_memory.h b/external/libcurl_android/jni/libcurl/lib/curl_memory.h
new file mode 100755
index 00000000..e3cdc721
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_memory.h
@@ -0,0 +1,140 @@
+#ifndef HEADER_CURL_MEMORY_H
+#define HEADER_CURL_MEMORY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Nasty internal details ahead...
+ *
+ * File curl_memory.h must be included by _all_ *.c source files
+ * that use memory related functions strdup, malloc, calloc, realloc
+ * or free, and given source file is used to build libcurl library.
+ *
+ * There is nearly no exception to above rule. All libcurl source
+ * files in 'lib' subdirectory as well as those living deep inside
+ * 'packages' subdirectories and linked together in order to build
+ * libcurl library shall follow it.
+ *
+ * File lib/strdup.c is an exception, given that it provides a strdup
+ * clone implementation while using malloc. Extra care needed inside
+ * this one. TODO: revisit this paragraph and related code.
+ *
+ * The need for curl_memory.h inclusion is due to libcurl's feature
+ * of allowing library user to provide memory replacement functions,
+ * memory callbacks, at runtime with curl_global_init_mem()
+ *
+ * Any *.c source file used to build libcurl library that does not
+ * include curl_memory.h and uses any memory function of the five
+ * mentioned above will compile without any indication, but it will
+ * trigger weird memory related issues at runtime.
+ *
+ * OTOH some source files from 'lib' subdirectory may additionally be
+ * used directly as source code when using some curlx_ functions by
+ * third party programs that don't even use libcurl at all. When using
+ * these source files in this way it is necessary these are compiled
+ * with CURLX_NO_MEMORY_CALLBACKS defined, in order to ensure that no
+ * attempt of calling libcurl's memory callbacks is done from code
+ * which can not use this machinery.
+ *
+ * Notice that libcurl's 'memory tracking' system works chaining into
+ * the memory callback machinery. This implies that when compiling
+ * 'lib' source files with CURLX_NO_MEMORY_CALLBACKS defined this file
+ * disengages usage of libcurl's 'memory tracking' system, defining
+ * MEMDEBUG_NODEFINES and overriding CURLDEBUG purpose.
+ *
+ * CURLX_NO_MEMORY_CALLBACKS takes precedence over CURLDEBUG. This is
+ * done in order to allow building a 'memory tracking' enabled libcurl
+ * and at the same time allow building programs which do not use it.
+ *
+ * Programs and libraries in 'tests' subdirectories have specific
+ * purposes and needs, and as such each one will use whatever fits
+ * best, depending additionally wether it links with libcurl or not.
+ *
+ * Caveat emptor. Proper curlx_* separation is a work in progress
+ * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may
+ * still be required. IOW don't use them yet, there are sharp edges.
+ */
+
+#ifdef HEADER_CURL_MEMDEBUG_H
+#error "Header memdebug.h shall not be included before curl_memory.h"
+#endif
+
+#ifndef CURLX_NO_MEMORY_CALLBACKS
+
+#include <curl/curl.h> /* for the callback typedefs */
+
+extern curl_malloc_callback Curl_cmalloc;
+extern curl_free_callback Curl_cfree;
+extern curl_realloc_callback Curl_crealloc;
+extern curl_strdup_callback Curl_cstrdup;
+extern curl_calloc_callback Curl_ccalloc;
+#if defined(WIN32) && defined(UNICODE)
+extern curl_wcsdup_callback Curl_cwcsdup;
+#endif
+
+#ifndef CURLDEBUG
+
+/*
+ * libcurl's 'memory tracking' system defines strdup, malloc, calloc,
+ * realloc and free, along with others, in memdebug.h in a different
+ * way although still using memory callbacks forward declared above.
+ * When using the 'memory tracking' system (CURLDEBUG defined) we do
+ * not define here the five memory functions given that definitions
+ * from memdebug.h are the ones that shall be used.
+ */
+
+#undef strdup
+#define strdup(ptr) Curl_cstrdup(ptr)
+#undef malloc
+#define malloc(size) Curl_cmalloc(size)
+#undef calloc
+#define calloc(nbelem,size) Curl_ccalloc(nbelem, size)
+#undef realloc
+#define realloc(ptr,size) Curl_crealloc(ptr, size)
+#undef free
+#define free(ptr) Curl_cfree(ptr)
+
+#ifdef WIN32
+# ifdef UNICODE
+# undef wcsdup
+# define wcsdup(ptr) Curl_cwcsdup(ptr)
+# undef _wcsdup
+# define _wcsdup(ptr) Curl_cwcsdup(ptr)
+# undef _tcsdup
+# define _tcsdup(ptr) Curl_cwcsdup(ptr)
+# else
+# undef _tcsdup
+# define _tcsdup(ptr) Curl_cstrdup(ptr)
+# endif
+#endif
+
+#endif /* CURLDEBUG */
+
+#else /* CURLX_NO_MEMORY_CALLBACKS */
+
+#ifndef MEMDEBUG_NODEFINES
+#define MEMDEBUG_NODEFINES
+#endif
+
+#endif /* CURLX_NO_MEMORY_CALLBACKS */
+
+#endif /* HEADER_CURL_MEMORY_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_memrchr.c b/external/libcurl_android/jni/libcurl/lib/curl_memrchr.c
new file mode 100755
index 00000000..a71c2bb4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_memrchr.c
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "curl_memrchr.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef HAVE_MEMRCHR
+
+/*
+ * Curl_memrchr()
+ *
+ * Our memrchr() function clone for systems which lack this function. The
+ * memrchr() function is like the memchr() function, except that it searches
+ * backwards from the end of the n bytes pointed to by s instead of forward
+ * from the beginning.
+ */
+
+void *
+Curl_memrchr(const void *s, int c, size_t n)
+{
+ const unsigned char *p = s;
+ const unsigned char *q = s;
+
+ p += n - 1;
+
+ while(p >= q) {
+ if(*p == (unsigned char)c)
+ return (void *)p;
+ p--;
+ }
+
+ return NULL;
+}
+
+#endif /* HAVE_MEMRCHR */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_memrchr.h b/external/libcurl_android/jni/libcurl/lib/curl_memrchr.h
new file mode 100755
index 00000000..324c73a7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_memrchr.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_MEMRCHR_H
+#define HEADER_CURL_MEMRCHR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_MEMRCHR
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#else /* HAVE_MEMRCHR */
+
+void *Curl_memrchr(const void *s, int c, size_t n);
+
+#define memrchr(x,y,z) Curl_memrchr((x),(y),(z))
+
+#endif /* HAVE_MEMRCHR */
+
+#endif /* HEADER_CURL_MEMRCHR_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_multibyte.c b/external/libcurl_android/jni/libcurl/lib/curl_multibyte.c
new file mode 100755
index 00000000..6c02239e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_multibyte.c
@@ -0,0 +1,82 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_WIN32_IDN) || (defined(USE_WINDOWS_SSPI) && defined(UNICODE))
+
+ /*
+ * MultiByte conversions using Windows kernel32 library.
+ */
+
+#include "curl_multibyte.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8)
+{
+ wchar_t *str_w = NULL;
+
+ if(str_utf8) {
+ int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
+ str_utf8, -1, NULL, 0);
+ if(str_w_len > 0) {
+ str_w = malloc(str_w_len * sizeof(wchar_t));
+ if(str_w) {
+ if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w,
+ str_w_len) == 0) {
+ Curl_safefree(str_w);
+ }
+ }
+ }
+ }
+
+ return str_w;
+}
+
+char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
+{
+ char *str_utf8 = NULL;
+
+ if(str_w) {
+ int str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL,
+ 0, NULL, NULL);
+ if(str_utf8_len > 0) {
+ str_utf8 = malloc(str_utf8_len * sizeof(wchar_t));
+ if(str_utf8) {
+ if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len,
+ NULL, FALSE) == 0) {
+ Curl_safefree(str_utf8);
+ }
+ }
+ }
+ }
+
+ return str_utf8;
+}
+
+#endif /* USE_WIN32_IDN || (USE_WINDOWS_SSPI && UNICODE) */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_multibyte.h b/external/libcurl_android/jni/libcurl/lib/curl_multibyte.h
new file mode 100755
index 00000000..7ee5eae1
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_multibyte.h
@@ -0,0 +1,90 @@
+#ifndef HEADER_CURL_MULTIBYTE_H
+#define HEADER_CURL_MULTIBYTE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(USE_WIN32_IDN) || (defined(USE_WINDOWS_SSPI) && defined(UNICODE))
+
+ /*
+ * MultiByte conversions using Windows kernel32 library.
+ */
+
+wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8);
+char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w);
+
+#endif /* USE_WIN32_IDN || (USE_WINDOWS_SSPI && UNICODE) */
+
+
+#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI)
+
+/*
+ * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8()
+ * and Curl_unicodefree() main purpose is to minimize the number of
+ * preprocessor conditional directives needed by code using these
+ * to differentiate UNICODE from non-UNICODE builds.
+ *
+ * When building with UNICODE defined, this two macros
+ * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8()
+ * return a pointer to a newly allocated memory area holding result.
+ * When the result is no longer needed, allocated memory is intended
+ * to be free'ed with Curl_unicodefree().
+ *
+ * When building without UNICODE defined, this macros
+ * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8()
+ * return the pointer received as argument. Curl_unicodefree() does
+ * no actual free'ing of this pointer it is simply set to NULL.
+ */
+
+#ifdef UNICODE
+
+#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr))
+#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr))
+#define Curl_unicodefree(ptr) \
+ do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE
+
+typedef union {
+ unsigned short *tchar_ptr;
+ const unsigned short *const_tchar_ptr;
+ unsigned short *tbyte_ptr;
+ const unsigned short *const_tbyte_ptr;
+} xcharp_u;
+
+#else
+
+#define Curl_convert_UTF8_to_tchar(ptr) (ptr)
+#define Curl_convert_tchar_to_UTF8(ptr) (ptr)
+#define Curl_unicodefree(ptr) \
+ do {(ptr) = NULL;} WHILE_FALSE
+
+typedef union {
+ char *tchar_ptr;
+ const char *const_tchar_ptr;
+ unsigned char *tbyte_ptr;
+ const unsigned char *const_tbyte_ptr;
+} xcharp_u;
+
+#endif /* UNICODE */
+
+#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI */
+
+#endif /* HEADER_CURL_MULTIBYTE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ntlm.c b/external/libcurl_android/jni/libcurl/lib/curl_ntlm.c
new file mode 100755
index 00000000..8c02aba5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ntlm.c
@@ -0,0 +1,248 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NTLM
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#include "urldata.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_msgs.h"
+#include "curl_ntlm_wb.h"
+#include "url.h"
+#include "curl_memory.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#if defined(USE_NSS)
+#include "vtls/nssg.h"
+#elif defined(USE_WINDOWS_SSPI)
+#include "curl_sspi.h"
+#endif
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+CURLcode Curl_input_ntlm(struct connectdata *conn,
+ bool proxy, /* if proxy or not */
+ const char *header) /* rest of the www-authenticate:
+ header */
+{
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ CURLcode result = CURLE_OK;
+
+#ifdef USE_NSS
+ result = Curl_nss_force_init(conn->data);
+ if(result)
+ return result;
+#endif
+
+ ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
+
+ if(checkprefix("NTLM", header)) {
+ header += strlen("NTLM");
+
+ while(*header && ISSPACE(*header))
+ header++;
+
+ if(*header) {
+ result = Curl_ntlm_decode_type2_message(conn->data, header, ntlm);
+ if(CURLE_OK != result)
+ return result;
+
+ ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+ }
+ else {
+ if(ntlm->state == NTLMSTATE_TYPE3) {
+ infof(conn->data, "NTLM handshake rejected\n");
+ Curl_http_ntlm_cleanup(conn);
+ ntlm->state = NTLMSTATE_NONE;
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+ else if(ntlm->state >= NTLMSTATE_TYPE1) {
+ infof(conn->data, "NTLM handshake failure (internal error)\n");
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+ ntlm->state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+ }
+ }
+
+ return result;
+}
+
+/*
+ * This is for creating ntlm header output
+ */
+CURLcode Curl_output_ntlm(struct connectdata *conn,
+ bool proxy)
+{
+ char *base64 = NULL;
+ size_t len = 0;
+ CURLcode error;
+
+ /* point to the address of the pointer that holds the string to send to the
+ server, which is for a plain host or for a HTTP proxy */
+ char **allocuserpwd;
+
+ /* point to the name and password for this */
+ const char *userp;
+ const char *passwdp;
+
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ struct auth *authp;
+
+ DEBUGASSERT(conn);
+ DEBUGASSERT(conn->data);
+
+#ifdef USE_NSS
+ if(CURLE_OK != Curl_nss_force_init(conn->data))
+ return CURLE_OUT_OF_MEMORY;
+#endif
+
+ if(proxy) {
+ allocuserpwd = &conn->allocptr.proxyuserpwd;
+ userp = conn->proxyuser;
+ passwdp = conn->proxypasswd;
+ ntlm = &conn->proxyntlm;
+ authp = &conn->data->state.authproxy;
+ }
+ else {
+ allocuserpwd = &conn->allocptr.userpwd;
+ userp = conn->user;
+ passwdp = conn->passwd;
+ ntlm = &conn->ntlm;
+ authp = &conn->data->state.authhost;
+ }
+ authp->done = FALSE;
+
+ /* not set means empty */
+ if(!userp)
+ userp = "";
+
+ if(!passwdp)
+ passwdp = "";
+
+#ifdef USE_WINDOWS_SSPI
+ if(s_hSecDll == NULL) {
+ /* not thread safe and leaks - use curl_global_init() to avoid */
+ CURLcode err = Curl_sspi_global_init();
+ if(s_hSecDll == NULL)
+ return err;
+ }
+#endif
+
+ switch(ntlm->state) {
+ case NTLMSTATE_TYPE1:
+ default: /* for the weird cases we (re)start here */
+ /* Create a type-1 message */
+ error = Curl_ntlm_create_type1_message(userp, passwdp, ntlm, &base64,
+ &len);
+ if(error)
+ return error;
+
+ if(base64) {
+ Curl_safefree(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
+ proxy ? "Proxy-" : "",
+ base64);
+ free(base64);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
+ DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
+ }
+ break;
+
+ case NTLMSTATE_TYPE2:
+ /* We already received the type-2 message, create a type-3 message */
+ error = Curl_ntlm_create_type3_message(conn->data, userp, passwdp,
+ ntlm, &base64, &len);
+ if(error)
+ return error;
+
+ if(base64) {
+ Curl_safefree(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
+ proxy ? "Proxy-" : "",
+ base64);
+ free(base64);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
+ DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
+
+ ntlm->state = NTLMSTATE_TYPE3; /* we send a type-3 */
+ authp->done = TRUE;
+ }
+ break;
+
+ case NTLMSTATE_TYPE3:
+ /* connection is already authenticated,
+ * don't send a header in future requests */
+ Curl_safefree(*allocuserpwd);
+ authp->done = TRUE;
+ break;
+ }
+
+ return CURLE_OK;
+}
+
+void Curl_http_ntlm_cleanup(struct connectdata *conn)
+{
+#ifdef USE_WINDOWS_SSPI
+ Curl_ntlm_sspi_cleanup(&conn->ntlm);
+ Curl_ntlm_sspi_cleanup(&conn->proxyntlm);
+#elif defined(NTLM_WB_ENABLED)
+ Curl_ntlm_wb_cleanup(conn);
+#else
+ (void)conn;
+#endif
+
+#ifndef USE_WINDOWS_SSPI
+ Curl_safefree(conn->ntlm.target_info);
+ conn->ntlm.target_info_len = 0;
+
+ Curl_safefree(conn->proxyntlm.target_info);
+ conn->proxyntlm.target_info_len = 0;
+#endif
+}
+
+#endif /* USE_NTLM */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ntlm.h b/external/libcurl_android/jni/libcurl/lib/curl_ntlm.h
new file mode 100755
index 00000000..21a9e9e4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ntlm.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_NTLM_H
+#define HEADER_CURL_NTLM_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NTLM
+
+/* this is for ntlm header input */
+CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
+ const char *header);
+
+/* this is for creating ntlm header output */
+CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
+
+void Curl_http_ntlm_cleanup(struct connectdata *conn);
+
+#else
+
+#define Curl_http_ntlm_cleanup(a) Curl_nop_stmt
+
+#endif
+
+#endif /* HEADER_CURL_NTLM_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ntlm_core.c b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_core.c
new file mode 100755
index 00000000..b0116262
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_core.c
@@ -0,0 +1,651 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#ifdef USE_SSLEAY
+
+# ifdef USE_OPENSSL
+# include <openssl/des.h>
+# ifndef OPENSSL_NO_MD4
+# include <openssl/md4.h>
+# endif
+# include <openssl/md5.h>
+# include <openssl/ssl.h>
+# include <openssl/rand.h>
+# else
+# include <des.h>
+# ifndef OPENSSL_NO_MD4
+# include <md4.h>
+# endif
+# include <md5.h>
+# include <ssl.h>
+# include <rand.h>
+# endif
+# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+# define DES_key_schedule des_key_schedule
+# define DES_cblock des_cblock
+# define DES_set_odd_parity des_set_odd_parity
+# define DES_set_key des_set_key
+# define DES_ecb_encrypt des_ecb_encrypt
+# define DESKEY(x) x
+# define DESKEYARG(x) x
+# else
+# define DESKEYARG(x) *x
+# define DESKEY(x) &x
+# endif
+
+#elif defined(USE_GNUTLS_NETTLE)
+
+# include <nettle/des.h>
+# include <nettle/md4.h>
+
+#elif defined(USE_GNUTLS)
+
+# include <gcrypt.h>
+# define MD5_DIGEST_LENGTH 16
+# define MD4_DIGEST_LENGTH 16
+
+#elif defined(USE_NSS)
+
+# include <nss.h>
+# include <pk11pub.h>
+# include <hasht.h>
+# include "curl_md4.h"
+# define MD5_DIGEST_LENGTH MD5_LENGTH
+
+#elif defined(USE_DARWINSSL)
+
+# include <CommonCrypto/CommonCryptor.h>
+# include <CommonCrypto/CommonDigest.h>
+
+#else
+# error "Can't compile NTLM support without a crypto library."
+#endif
+
+#include "urldata.h"
+#include "non-ascii.h"
+#include "rawstr.h"
+#include "curl_memory.h"
+#include "curl_ntlm_core.h"
+#include "curl_md5.h"
+#include "curl_hmac.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#define NTLM_HMAC_MD5_LEN (16)
+#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
+#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
+
+#ifdef USE_SSLEAY
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
+ * key schedule ks is also set.
+ */
+static void setup_des_key(const unsigned char *key_56,
+ DES_key_schedule DESKEYARG(ks))
+{
+ DES_cblock key;
+
+ key[0] = key_56[0];
+ key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+ key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+ key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+ key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+ key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+ key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+ key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+
+ DES_set_odd_parity(&key);
+ DES_set_key(&key, ks);
+}
+
+#else /* defined(USE_SSLEAY) */
+
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key. Used by GnuTLS and NSS.
+ */
+static void extend_key_56_to_64(const unsigned char *key_56, char *key)
+{
+ key[0] = key_56[0];
+ key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+ key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+ key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+ key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+ key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+ key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+ key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+}
+
+#if defined(USE_GNUTLS_NETTLE)
+
+static void setup_des_key(const unsigned char *key_56,
+ struct des_ctx *des)
+{
+ char key[8];
+ extend_key_56_to_64(key_56, key);
+ des_set_key(des, (const uint8_t*)key);
+}
+
+#elif defined(USE_GNUTLS)
+
+/*
+ * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
+ */
+static void setup_des_key(const unsigned char *key_56,
+ gcry_cipher_hd_t *des)
+{
+ char key[8];
+ extend_key_56_to_64(key_56, key);
+ gcry_cipher_setkey(*des, key, 8);
+}
+
+#elif defined(USE_NSS)
+
+/*
+ * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
+ * the expanded key. The caller is responsible for giving 64 bit of valid
+ * data is IN and (at least) 64 bit large buffer as OUT.
+ */
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
+ PK11SlotInfo *slot = NULL;
+ char key[8]; /* expanded 64 bit key */
+ SECItem key_item;
+ PK11SymKey *symkey = NULL;
+ SECItem *param = NULL;
+ PK11Context *ctx = NULL;
+ int out_len; /* not used, required by NSS */
+ bool rv = FALSE;
+
+ /* use internal slot for DES encryption (requires NSS to be initialized) */
+ slot = PK11_GetInternalKeySlot();
+ if(!slot)
+ return FALSE;
+
+ /* expand the 56 bit key to 64 bit and wrap by NSS */
+ extend_key_56_to_64(key_56, key);
+ key_item.data = (unsigned char *)key;
+ key_item.len = /* hard-wired */ 8;
+ symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
+ &key_item, NULL);
+ if(!symkey)
+ goto fail;
+
+ /* create DES encryption context */
+ param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
+ if(!param)
+ goto fail;
+ ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
+ if(!ctx)
+ goto fail;
+
+ /* perform the encryption */
+ if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
+ (unsigned char *)in, /* inbuflen */ 8)
+ && SECSuccess == PK11_Finalize(ctx))
+ rv = /* all OK */ TRUE;
+
+fail:
+ /* cleanup */
+ if(ctx)
+ PK11_DestroyContext(ctx, PR_TRUE);
+ if(symkey)
+ PK11_FreeSymKey(symkey);
+ if(param)
+ SECITEM_FreeItem(param, PR_TRUE);
+ PK11_FreeSlot(slot);
+ return rv;
+}
+
+#elif defined(USE_DARWINSSL)
+
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ char key[8];
+ size_t out_len;
+ CCCryptorStatus err;
+
+ extend_key_56_to_64(key_56, key);
+ err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key,
+ kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out,
+ 8 /* outbuflen */, &out_len);
+ return err == kCCSuccess;
+}
+
+#endif /* defined(USE_DARWINSSL) */
+
+#endif /* defined(USE_SSLEAY) */
+
+ /*
+ * takes a 21 byte array and treats it as 3 56-bit DES keys. The
+ * 8 byte plaintext is encrypted with each key and the resulting 24
+ * bytes are stored in the results array.
+ */
+void Curl_ntlm_core_lm_resp(const unsigned char *keys,
+ const unsigned char *plaintext,
+ unsigned char *results)
+{
+#ifdef USE_SSLEAY
+ DES_key_schedule ks;
+
+ setup_des_key(keys, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(keys + 7, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8),
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(keys + 14, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
+ DESKEY(ks), DES_ENCRYPT);
+#elif defined(USE_GNUTLS_NETTLE)
+ struct des_ctx des;
+ setup_des_key(keys, &des);
+ des_encrypt(&des, 8, results, plaintext);
+ setup_des_key(keys + 7, &des);
+ des_encrypt(&des, 8, results + 8, plaintext);
+ setup_des_key(keys + 14, &des);
+ des_encrypt(&des, 8, results + 16, plaintext);
+#elif defined(USE_GNUTLS)
+ gcry_cipher_hd_t des;
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys, &des);
+ gcry_cipher_encrypt(des, results, 8, plaintext, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys + 7, &des);
+ gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(keys + 14, &des);
+ gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
+ gcry_cipher_close(des);
+#elif defined(USE_NSS) || defined(USE_DARWINSSL)
+ encrypt_des(plaintext, results, keys);
+ encrypt_des(plaintext, results + 8, keys + 7);
+ encrypt_des(plaintext, results + 16, keys + 14);
+#endif
+}
+
+/*
+ * Set up lanmanager hashed password
+ */
+void Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *lmbuffer /* 21 bytes */)
+{
+ CURLcode res;
+ unsigned char pw[14];
+ static const unsigned char magic[] = {
+ 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
+ };
+ size_t len = CURLMIN(strlen(password), 14);
+
+ Curl_strntoupper((char *)pw, password, len);
+ memset(&pw[len], 0, 14 - len);
+
+ /*
+ * The LanManager hashed password needs to be created using the
+ * password in the network encoding not the host encoding.
+ */
+ res = Curl_convert_to_network(data, (char *)pw, 14);
+ if(res)
+ return;
+
+ {
+ /* Create LanManager hashed password. */
+
+#ifdef USE_SSLEAY
+ DES_key_schedule ks;
+
+ setup_des_key(pw, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
+ DESKEY(ks), DES_ENCRYPT);
+
+ setup_des_key(pw + 7, DESKEY(ks));
+ DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
+ DESKEY(ks), DES_ENCRYPT);
+#elif defined(USE_GNUTLS_NETTLE)
+ struct des_ctx des;
+ setup_des_key(pw, &des);
+ des_encrypt(&des, 8, lmbuffer, magic);
+ setup_des_key(pw + 7, &des);
+ des_encrypt(&des, 8, lmbuffer + 8, magic);
+#elif defined(USE_GNUTLS)
+ gcry_cipher_hd_t des;
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(pw, &des);
+ gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
+ gcry_cipher_close(des);
+
+ gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ setup_des_key(pw + 7, &des);
+ gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
+ gcry_cipher_close(des);
+#elif defined(USE_NSS) || defined(USE_DARWINSSL)
+ encrypt_des(magic, lmbuffer, pw);
+ encrypt_des(magic, lmbuffer + 8, pw + 7);
+#endif
+
+ memset(lmbuffer + 16, 0, 21 - 16);
+ }
+}
+
+#if USE_NTRESPONSES
+static void ascii_to_unicode_le(unsigned char *dest, const char *src,
+ size_t srclen)
+{
+ size_t i;
+ for(i = 0; i < srclen; i++) {
+ dest[2 * i] = (unsigned char)src[i];
+ dest[2 * i + 1] = '\0';
+ }
+}
+
+static void ascii_uppercase_to_unicode_le(unsigned char *dest,
+ const char *src, size_t srclen)
+{
+ size_t i;
+ for(i = 0; i < srclen; i++) {
+ dest[2 * i] = (unsigned char)(toupper(src[i]));
+ dest[2 * i + 1] = '\0';
+ }
+}
+
+static void write32_le(const int value, unsigned char *buffer)
+{
+ buffer[0] = (char)(value & 0x000000FF);
+ buffer[1] = (char)((value & 0x0000FF00) >> 8);
+ buffer[2] = (char)((value & 0x00FF0000) >> 16);
+ buffer[3] = (char)((value & 0xFF000000) >> 24);
+}
+
+#if defined(HAVE_LONGLONG)
+static void write64_le(const long long value, unsigned char *buffer)
+#else
+static void write64_le(const __int64 value, unsigned char *buffer)
+#endif
+{
+ write32_le((int)value, buffer);
+ write32_le((int)(value >> 32), buffer + 4);
+}
+
+/*
+ * Set up nt hashed passwords
+ */
+CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *ntbuffer /* 21 bytes */)
+{
+ size_t len = strlen(password);
+ unsigned char *pw = malloc(len * 2);
+ CURLcode result;
+ if(!pw)
+ return CURLE_OUT_OF_MEMORY;
+
+ ascii_to_unicode_le(pw, password, len);
+
+ /*
+ * The NT hashed password needs to be created using the password in the
+ * network encoding not the host encoding.
+ */
+ result = Curl_convert_to_network(data, (char *)pw, len * 2);
+ if(result)
+ return result;
+
+ {
+ /* Create NT hashed password. */
+#ifdef USE_SSLEAY
+ MD4_CTX MD4pw;
+ MD4_Init(&MD4pw);
+ MD4_Update(&MD4pw, pw, 2 * len);
+ MD4_Final(ntbuffer, &MD4pw);
+#elif defined(USE_GNUTLS_NETTLE)
+ struct md4_ctx MD4pw;
+ md4_init(&MD4pw);
+ md4_update(&MD4pw, (unsigned int)(2 * len), pw);
+ md4_digest(&MD4pw, MD4_DIGEST_SIZE, ntbuffer);
+#elif defined(USE_GNUTLS)
+ gcry_md_hd_t MD4pw;
+ gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
+ gcry_md_write(MD4pw, pw, 2 * len);
+ memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
+ gcry_md_close(MD4pw);
+#elif defined(USE_NSS)
+ Curl_md4it(ntbuffer, pw, 2 * len);
+#elif defined(USE_DARWINSSL)
+ (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
+#endif
+
+ memset(ntbuffer + 16, 0, 21 - 16);
+ }
+
+ free(pw);
+
+ return CURLE_OK;
+}
+
+/* This returns the HMAC MD5 digest */
+CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
+ const unsigned char *data, unsigned int datalen,
+ unsigned char *output)
+{
+ HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
+
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Update the digest with the given challenge */
+ Curl_HMAC_update(ctxt, data, datalen);
+
+ /* Finalise the digest */
+ Curl_HMAC_final(ctxt, output);
+
+ return CURLE_OK;
+}
+
+/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
+ * (uppercase UserName + Domain) as the data
+ */
+CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
+ const char *domain, size_t domlen,
+ unsigned char *ntlmhash,
+ unsigned char *ntlmv2hash)
+{
+ /* Unicode representation */
+ size_t identity_len = (userlen + domlen) * 2;
+ unsigned char *identity = malloc(identity_len);
+ CURLcode res = CURLE_OK;
+
+ if(!identity)
+ return CURLE_OUT_OF_MEMORY;
+
+ ascii_uppercase_to_unicode_le(identity, user, userlen);
+ ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
+
+ res = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
+ ntlmv2hash);
+
+ Curl_safefree(identity);
+
+ return res;
+}
+
+/*
+ * Curl_ntlm_core_mk_ntlmv2_resp()
+ *
+ * This creates the NTLMv2 response as set in the ntlm type-3 message.
+ *
+ * Parameters:
+ *
+ * ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
+ * challenge_client [in] - The client nonce (8 bytes)
+ * ntlm [in] - The ntlm data struct being used to read TargetInfo
+ and Server challenge received in the type-2 message
+ * ntresp [out] - The address where a pointer to newly allocated
+ * memory holding the NTLMv2 response.
+ * ntresp_len [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
+ unsigned char *challenge_client,
+ struct ntlmdata *ntlm,
+ unsigned char **ntresp,
+ unsigned int *ntresp_len)
+{
+/* NTLMv2 response structure :
+------------------------------------------------------------------------------
+0 HMAC MD5 16 bytes
+------BLOB--------------------------------------------------------------------
+16 Signature 0x01010000
+20 Reserved long (0x00000000)
+24 Timestamp LE, 64-bit signed value representing the number of
+ tenths of a microsecond since January 1, 1601.
+32 Client Nonce 8 bytes
+40 Unknown 4 bytes
+44 Target Info N bytes (from the type-2 message)
+44+N Unknown 4 bytes
+------------------------------------------------------------------------------
+*/
+
+ unsigned int len = 0;
+ unsigned char *ptr = NULL;
+ unsigned char hmac_output[NTLM_HMAC_MD5_LEN];
+#if defined(HAVE_LONGLONG)
+ long long tw;
+#else
+ __int64 tw;
+#endif
+ CURLcode res = CURLE_OK;
+
+ /* Calculate the timestamp */
+#ifdef DEBUGBUILD
+ char *force_timestamp = getenv("CURL_FORCETIME");
+ if(force_timestamp)
+ tw = 11644473600ULL * 10000000ULL;
+ else
+#endif
+ tw = ((long long)time(NULL) + 11644473600ULL) * 10000000ULL;
+
+ /* Calculate the response len */
+ len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
+
+ /* Allocate the response */
+ ptr = malloc(len);
+ if(!ptr)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(ptr, 0, len);
+
+ /* Create the BLOB structure */
+ snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
+ NTLMv2_BLOB_SIGNATURE
+ "%c%c%c%c", /* Reserved = 0 */
+ 0, 0, 0, 0);
+
+ write64_le(tw, ptr + 24);
+ memcpy(ptr + 32, challenge_client, 8);
+ memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
+
+ /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
+ memcpy(ptr + 8, &ntlm->nonce[0], 8);
+ res = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
+ NTLMv2_BLOB_LEN + 8, hmac_output);
+ if(res) {
+ Curl_safefree(ptr);
+ return res;
+ }
+
+ /* Concatenate the HMAC MD5 output with the BLOB */
+ memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN);
+
+ /* Return the response */
+ *ntresp = ptr;
+ *ntresp_len = len;
+
+ return res;
+}
+
+/*
+ * Curl_ntlm_core_mk_lmv2_resp()
+ *
+ * This creates the LMv2 response as used in the ntlm type-3 message.
+ *
+ * Parameters:
+ *
+ * ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
+ * challenge_client [in] - The client nonce (8 bytes)
+ * challenge_client [in] - The server challenge (8 bytes)
+ * lmresp [out] - The LMv2 response (24 bytes)
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
+ unsigned char *challenge_client,
+ unsigned char *challenge_server,
+ unsigned char *lmresp)
+{
+ unsigned char data[16];
+ unsigned char hmac_output[16];
+ CURLcode res = CURLE_OK;
+
+ memcpy(&data[0], challenge_server, 8);
+ memcpy(&data[8], challenge_client, 8);
+
+ res = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
+ if(res)
+ return res;
+
+ /* Concatenate the HMAC MD5 output with the client nonce */
+ memcpy(lmresp, hmac_output, 16);
+ memcpy(lmresp+16, challenge_client, 8);
+
+ return res;
+}
+
+#endif /* USE_NTRESPONSES */
+
+#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ntlm_core.h b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_core.h
new file mode 100755
index 00000000..fe41cddf
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_core.h
@@ -0,0 +1,89 @@
+#ifndef HEADER_CURL_NTLM_CORE_H
+#define HEADER_CURL_NTLM_CORE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
+
+#ifdef USE_SSLEAY
+# if !defined(OPENSSL_VERSION_NUMBER) && \
+ !defined(HEADER_SSL_H) && !defined(HEADER_MD5_H)
+# error "curl_ntlm_core.h shall not be included before OpenSSL headers."
+# endif
+# ifdef OPENSSL_NO_MD4
+# define USE_NTRESPONSES 0
+# define USE_NTLM2SESSION 0
+# endif
+#endif
+
+/*
+ * Define USE_NTRESPONSES to 1 in order to make the type-3 message include
+ * the NT response message. Define USE_NTLM2SESSION to 1 in order to make
+ * the type-3 message include the NTLM2Session response message, requires
+ * USE_NTRESPONSES defined to 1.
+ */
+
+#ifndef USE_NTRESPONSES
+# define USE_NTRESPONSES 1
+# define USE_NTLM2SESSION 1
+#endif
+
+void Curl_ntlm_core_lm_resp(const unsigned char *keys,
+ const unsigned char *plaintext,
+ unsigned char *results);
+
+void Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *lmbuffer /* 21 bytes */);
+
+#if USE_NTRESPONSES
+CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
+ const unsigned char *data, unsigned int datalen,
+ unsigned char *output);
+
+CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
+ const char *password,
+ unsigned char *ntbuffer /* 21 bytes */);
+
+CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
+ const char *domain, size_t domlen,
+ unsigned char *ntlmhash,
+ unsigned char *ntlmv2hash);
+
+CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
+ unsigned char *challenge_client,
+ struct ntlmdata *ntlm,
+ unsigned char **ntresp,
+ unsigned int *ntresp_len);
+
+CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
+ unsigned char *challenge_client,
+ unsigned char *challenge_server,
+ unsigned char *lmresp);
+
+#endif
+
+#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
+
+#endif /* HEADER_CURL_NTLM_CORE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ntlm_msgs.c b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_msgs.c
new file mode 100755
index 00000000..b8079263
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_msgs.c
@@ -0,0 +1,1010 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NTLM
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#include "urldata.h"
+#include "non-ascii.h"
+#include "sendf.h"
+#include "curl_base64.h"
+#include "curl_ntlm_core.h"
+#include "curl_gethostname.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+#include "curl_memory.h"
+
+#ifdef USE_WINDOWS_SSPI
+# include "curl_sspi.h"
+#endif
+
+#include "vtls/vtls.h"
+
+#define BUILDING_CURL_NTLM_MSGS_C
+#include "curl_ntlm_msgs.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* "NTLMSSP" signature is always in ASCII regardless of the platform */
+#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
+
+#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
+#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
+ (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+static void ntlm_print_flags(FILE *handle, unsigned long flags)
+{
+ if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
+ if(flags & NTLMFLAG_NEGOTIATE_OEM)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
+ if(flags & NTLMFLAG_REQUEST_TARGET)
+ fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
+ if(flags & (1<<3))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
+ if(flags & NTLMFLAG_NEGOTIATE_SIGN)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
+ if(flags & NTLMFLAG_NEGOTIATE_SEAL)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
+ if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
+ if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
+ if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
+ if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
+ if(flags & (1<<10))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
+ if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
+ if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
+ if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
+ if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
+ if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
+ if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
+ if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
+ if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
+ fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
+ if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
+ if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
+ fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
+ if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
+ fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
+ if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
+ fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
+ if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
+ if(flags & (1<<24))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
+ if(flags & (1<<25))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
+ if(flags & (1<<26))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
+ if(flags & (1<<27))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
+ if(flags & (1<<28))
+ fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
+ if(flags & NTLMFLAG_NEGOTIATE_128)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
+ if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
+ if(flags & NTLMFLAG_NEGOTIATE_56)
+ fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
+}
+
+static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
+{
+ const char *p = buf;
+ (void)handle;
+ fprintf(stderr, "0x");
+ while(len-- > 0)
+ fprintf(stderr, "%02.2x", (unsigned int)*p++);
+}
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+#ifndef USE_WINDOWS_SSPI
+/*
+ * This function converts from the little endian format used in the
+ * incoming package to whatever endian format we're using natively.
+ * Argument is a pointer to a 4 byte buffer.
+ */
+static unsigned int readint_le(unsigned char *buf)
+{
+ return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
+ ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
+}
+
+/*
+ * This function converts from the little endian format used in the incoming
+ * package to whatever endian format we're using natively. Argument is a
+ * pointer to a 2 byte buffer.
+ */
+static unsigned int readshort_le(unsigned char *buf)
+{
+ return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8);
+}
+
+/*
+ * Curl_ntlm_decode_type2_target()
+ *
+ * This is used to decode the "target info" in the ntlm type-2 message
+ * received.
+ *
+ * Parameters:
+ *
+ * data [in] - Pointer to the session handle
+ * buffer [in] - The decoded base64 ntlm header of Type 2
+ * size [in] - The input buffer size, atleast 32 bytes
+ * ntlm [in] - Pointer to ntlm data struct being used and modified.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data,
+ unsigned char *buffer,
+ size_t size,
+ struct ntlmdata *ntlm)
+{
+ unsigned int target_info_len = 0;
+ unsigned int target_info_offset = 0;
+
+ Curl_safefree(ntlm->target_info);
+ ntlm->target_info_len = 0;
+
+ if(size >= 48) {
+ target_info_len = readshort_le(&buffer[40]);
+ target_info_offset = readint_le(&buffer[44]);
+ if(target_info_len > 0) {
+ if(((target_info_offset + target_info_len) > size) ||
+ (target_info_offset < 48)) {
+ infof(data, "NTLM handshake failure (bad type-2 message). "
+ "Target Info Offset Len is set incorrect by the peer\n");
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+ ntlm->target_info = malloc(target_info_len);
+ if(!ntlm->target_info)
+ return CURLE_OUT_OF_MEMORY;
+
+ memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
+ ntlm->target_info_len = target_info_len;
+
+ }
+
+ }
+
+ return CURLE_OK;
+}
+
+#endif
+
+/*
+ NTLM message structure notes:
+
+ A 'short' is a 'network short', a little-endian 16-bit unsigned value.
+
+ A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
+
+ A 'security buffer' represents a triplet used to point to a buffer,
+ consisting of two shorts and one long:
+
+ 1. A 'short' containing the length of the buffer content in bytes.
+ 2. A 'short' containing the allocated space for the buffer in bytes.
+ 3. A 'long' containing the offset to the start of the buffer in bytes,
+ from the beginning of the NTLM message.
+*/
+
+/*
+ * Curl_ntlm_decode_type2_message()
+ *
+ * This is used to decode a ntlm type-2 message received from a HTTP or SASL
+ * based (such as SMTP, POP3 or IMAP) server. The message is first decoded
+ * from a base64 string into a raw ntlm message and checked for validity
+ * before the appropriate data for creating a type-3 message is written to
+ * the given ntlm data structure.
+ *
+ * Parameters:
+ *
+ * data [in] - Pointer to session handle.
+ * header [in] - Pointer to the input buffer.
+ * ntlm [in] - Pointer to ntlm data struct being used and modified.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
+ const char *header,
+ struct ntlmdata *ntlm)
+{
+#ifndef USE_WINDOWS_SSPI
+ static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
+#endif
+
+ /* NTLM type-2 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x02000000)
+ 12 Target Name security buffer
+ 20 Flags long
+ 24 Challenge 8 bytes
+ (32) Context 8 bytes (two consecutive longs) (*)
+ (40) Target Information security buffer (*)
+ (48) OS Version Structure 8 bytes (*)
+ 32 (48) (56) Start of data block (*)
+ (*) -> Optional
+ */
+
+ size_t size = 0;
+ unsigned char *buffer = NULL;
+ CURLcode error;
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_WINDOWS_SSPI)
+ (void)data;
+#endif
+
+ error = Curl_base64_decode(header, &buffer, &size);
+ if(error)
+ return error;
+
+ if(!buffer) {
+ infof(data, "NTLM handshake failure (unhandled condition)\n");
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+#ifdef USE_WINDOWS_SSPI
+ ntlm->type_2 = malloc(size + 1);
+ if(ntlm->type_2 == NULL) {
+ free(buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ntlm->n_type_2 = curlx_uztoul(size);
+ memcpy(ntlm->type_2, buffer, size);
+#else
+ ntlm->flags = 0;
+
+ if((size < 32) ||
+ (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
+ (memcmp(buffer + 8, type2_marker, sizeof(type2_marker)) != 0)) {
+ /* This was not a good enough type-2 message */
+ free(buffer);
+ infof(data, "NTLM handshake failure (bad type-2 message)\n");
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+ ntlm->flags = readint_le(&buffer[20]);
+ memcpy(ntlm->nonce, &buffer[24], 8);
+
+ if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
+ error = Curl_ntlm_decode_type2_target(data, buffer, size, ntlm);
+ if(error) {
+ free(buffer);
+ infof(data, "NTLM handshake failure (bad type-2 message)\n");
+ return error;
+ }
+ }
+
+ DEBUG_OUT({
+ fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
+ ntlm_print_flags(stderr, ntlm->flags);
+ fprintf(stderr, "\n nonce=");
+ ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
+ fprintf(stderr, "\n****\n");
+ fprintf(stderr, "**** Header %s\n ", header);
+ });
+#endif
+ free(buffer);
+
+ return CURLE_OK;
+}
+
+#ifdef USE_WINDOWS_SSPI
+void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm)
+{
+ Curl_safefree(ntlm->type_2);
+
+ if(ntlm->has_handles) {
+ s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
+ s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
+ ntlm->has_handles = 0;
+ }
+
+ ntlm->max_token_length = 0;
+ Curl_safefree(ntlm->output_token);
+
+ Curl_sspi_free_identity(ntlm->p_identity);
+ ntlm->p_identity = NULL;
+}
+#endif
+
+#ifndef USE_WINDOWS_SSPI
+/* copy the source to the destination and fill in zeroes in every
+ other destination byte! */
+static void unicodecpy(unsigned char *dest, const char *src, size_t length)
+{
+ size_t i;
+ for(i = 0; i < length; i++) {
+ dest[2 * i] = (unsigned char)src[i];
+ dest[2 * i + 1] = '\0';
+ }
+}
+#endif
+
+/*
+ * Curl_ntlm_create_type1_message()
+ *
+ * This is used to generate an already encoded NTLM type-1 message ready for
+ * sending to the recipient, be it a HTTP or SASL based (such as SMTP, POP3
+ * or IMAP) server, using the appropriate compile time crypo API.
+ *
+ * Parameters:
+ *
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_ntlm_create_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen)
+{
+ /* NTLM type-1 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x01000000)
+ 12 Flags long
+ (16) Supplied Domain security buffer (*)
+ (24) Supplied Workstation security buffer (*)
+ (32) OS Version Structure 8 bytes (*)
+ (32) (40) Start of data block (*)
+ (*) -> Optional
+ */
+
+ size_t size;
+
+#ifdef USE_WINDOWS_SSPI
+
+ PSecPkgInfo SecurityPackage;
+ SecBuffer type_1_buf;
+ SecBufferDesc type_1_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
+
+ Curl_ntlm_sspi_cleanup(ntlm);
+
+ /* Query the security package for NTLM */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT("NTLM"),
+ &SecurityPackage);
+ if(status != SEC_E_OK)
+ return CURLE_NOT_BUILT_IN;
+
+ ntlm->max_token_length = SecurityPackage->cbMaxToken;
+
+ /* Release the package buffer as it is not required anymore */
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+
+ /* Allocate our output buffer */
+ ntlm->output_token = malloc(ntlm->max_token_length);
+ if(!ntlm->output_token)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(userp && *userp) {
+ CURLcode result;
+
+ /* Populate our identity structure */
+ result = Curl_create_sspi_identity(userp, passwdp, &ntlm->identity);
+ if(result)
+ return result;
+
+ /* Allow proper cleanup of the identity structure */
+ ntlm->p_identity = &ntlm->identity;
+ }
+ else
+ /* Use the current Windows user */
+ ntlm->p_identity = NULL;
+
+ /* Acquire our credientials handle */
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT("NTLM"),
+ SECPKG_CRED_OUTBOUND, NULL,
+ ntlm->p_identity, NULL, NULL,
+ &ntlm->handle, &tsDummy);
+ if(status != SEC_E_OK)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Setup the type-1 "output" security buffer */
+ type_1_desc.ulVersion = SECBUFFER_VERSION;
+ type_1_desc.cBuffers = 1;
+ type_1_desc.pBuffers = &type_1_buf;
+ type_1_buf.BufferType = SECBUFFER_TOKEN;
+ type_1_buf.pvBuffer = ntlm->output_token;
+ type_1_buf.cbBuffer = curlx_uztoul(ntlm->max_token_length);
+
+ /* Generate our type-1 message */
+ status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL,
+ (TCHAR *) TEXT(""),
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONNECTION,
+ 0, SECURITY_NETWORK_DREP,
+ NULL, 0,
+ &ntlm->c_handle, &type_1_desc,
+ &attrs, &tsDummy);
+
+ if(status == SEC_I_COMPLETE_AND_CONTINUE ||
+ status == SEC_I_CONTINUE_NEEDED)
+ s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &type_1_desc);
+ else if(status != SEC_E_OK) {
+ s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
+ return CURLE_RECV_ERROR;
+ }
+
+ ntlm->has_handles = 1;
+ size = type_1_buf.cbBuffer;
+
+#else
+
+ unsigned char ntlmbuf[NTLM_BUFSIZE];
+ const char *host = ""; /* empty */
+ const char *domain = ""; /* empty */
+ size_t hostlen = 0;
+ size_t domlen = 0;
+ size_t hostoff = 0;
+ size_t domoff = hostoff + hostlen; /* This is 0: remember that host and
+ domain are empty */
+ (void)userp;
+ (void)passwdp;
+ (void)ntlm;
+
+#if USE_NTLM2SESSION
+#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
+#else
+#define NTLM2FLAG 0
+#endif
+ snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+ NTLMSSP_SIGNATURE "%c"
+ "\x01%c%c%c" /* 32-bit type = 1 */
+ "%c%c%c%c" /* 32-bit NTLM flag field */
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host name offset */
+ "%c%c" /* 2 zeroes */
+ "%s" /* host name */
+ "%s", /* domain string */
+ 0, /* trailing zero */
+ 0, 0, 0, /* part of type-1 long */
+
+ LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0, 0,
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0, 0,
+ host, /* this is empty */
+ domain /* this is empty */);
+
+ /* Initial packet length */
+ size = 32 + hostlen + domlen;
+
+#endif
+
+ DEBUG_OUT({
+ fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
+ "0x%08.8x ",
+ LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+ NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
+ ntlm_print_flags(stderr,
+ NTLMFLAG_NEGOTIATE_OEM |
+ NTLMFLAG_REQUEST_TARGET |
+ NTLMFLAG_NEGOTIATE_NTLM_KEY |
+ NTLM2FLAG |
+ NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
+ fprintf(stderr, "\n****\n");
+ });
+
+ /* Return with binary blob encoded into base64 */
+#ifdef USE_WINDOWS_SSPI
+ return Curl_base64_encode(NULL, (char *)ntlm->output_token, size,
+ outptr, outlen);
+#else
+ return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+#endif
+}
+
+/*
+ * Curl_ntlm_create_type3_message()
+ *
+ * This is used to generate an already encoded NTLM type-3 message ready for
+ * sending to the recipient, be it a HTTP or SASL based (such as SMTP, POP3
+ * or IMAP) server, using the appropriate compile time crypo API.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen)
+{
+ /* NTLM type-3 message structure:
+
+ Index Description Content
+ 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
+ (0x4e544c4d53535000)
+ 8 NTLM Message Type long (0x03000000)
+ 12 LM/LMv2 Response security buffer
+ 20 NTLM/NTLMv2 Response security buffer
+ 28 Target Name security buffer
+ 36 User Name security buffer
+ 44 Workstation Name security buffer
+ (52) Session Key security buffer (*)
+ (60) Flags long (*)
+ (64) OS Version Structure 8 bytes (*)
+ 52 (64) (72) Start of data block
+ (*) -> Optional
+ */
+
+ size_t size;
+
+#ifdef USE_WINDOWS_SSPI
+ CURLcode result = CURLE_OK;
+ SecBuffer type_2_buf;
+ SecBuffer type_3_buf;
+ SecBufferDesc type_2_desc;
+ SecBufferDesc type_3_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
+
+ (void)passwdp;
+ (void)userp;
+ (void)data;
+
+ /* Setup the type-2 "input" security buffer */
+ type_2_desc.ulVersion = SECBUFFER_VERSION;
+ type_2_desc.cBuffers = 1;
+ type_2_desc.pBuffers = &type_2_buf;
+ type_2_buf.BufferType = SECBUFFER_TOKEN;
+ type_2_buf.pvBuffer = ntlm->type_2;
+ type_2_buf.cbBuffer = ntlm->n_type_2;
+
+ /* Setup the type-3 "output" security buffer */
+ type_3_desc.ulVersion = SECBUFFER_VERSION;
+ type_3_desc.cBuffers = 1;
+ type_3_desc.pBuffers = &type_3_buf;
+ type_3_buf.BufferType = SECBUFFER_TOKEN;
+ type_3_buf.pvBuffer = ntlm->output_token;
+ type_3_buf.cbBuffer = curlx_uztoul(ntlm->max_token_length);
+
+ /* Generate our type-3 message */
+ status = s_pSecFn->InitializeSecurityContext(&ntlm->handle,
+ &ntlm->c_handle,
+ (TCHAR *) TEXT(""),
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONNECTION,
+ 0, SECURITY_NETWORK_DREP,
+ &type_2_desc,
+ 0, &ntlm->c_handle,
+ &type_3_desc,
+ &attrs, &tsDummy);
+ if(status != SEC_E_OK)
+ return CURLE_RECV_ERROR;
+
+ size = type_3_buf.cbBuffer;
+
+ /* Return with binary blob encoded into base64 */
+ result = Curl_base64_encode(NULL, (char *)ntlm->output_token, size,
+ outptr, outlen);
+
+ Curl_ntlm_sspi_cleanup(ntlm);
+
+ return result;
+
+#else
+
+ unsigned char ntlmbuf[NTLM_BUFSIZE];
+ int lmrespoff;
+ unsigned char lmresp[24]; /* fixed-size */
+#if USE_NTRESPONSES
+ int ntrespoff;
+ unsigned int ntresplen = 24;
+ unsigned char ntresp[24]; /* fixed-size */
+ unsigned char *ptr_ntresp = &ntresp[0];
+ unsigned char *ntlmv2resp = NULL;
+#endif
+ bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
+ char host[HOSTNAME_MAX + 1] = "";
+ const char *user;
+ const char *domain = "";
+ size_t hostoff = 0;
+ size_t useroff = 0;
+ size_t domoff = 0;
+ size_t hostlen = 0;
+ size_t userlen = 0;
+ size_t domlen = 0;
+ CURLcode res = CURLE_OK;
+
+ user = strchr(userp, '\\');
+ if(!user)
+ user = strchr(userp, '/');
+
+ if(user) {
+ domain = userp;
+ domlen = (user - domain);
+ user++;
+ }
+ else
+ user = userp;
+
+ if(user)
+ userlen = strlen(user);
+
+ /* Get the machine's un-qualified host name as NTLM doesn't like the fully
+ qualified domain name */
+ if(Curl_gethostname(host, sizeof(host))) {
+ infof(data, "gethostname() failed, continuing without!\n");
+ hostlen = 0;
+ }
+ else {
+ hostlen = strlen(host);
+ }
+
+#if USE_NTRESPONSES
+ if(ntlm->target_info_len) {
+ unsigned char ntbuffer[0x18];
+ unsigned int entropy[2];
+ unsigned char ntlmv2hash[0x18];
+
+ entropy[0] = Curl_rand(data);
+ entropy[1] = Curl_rand(data);
+
+ res = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
+ if(res)
+ return res;
+
+ res = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
+ ntbuffer, ntlmv2hash);
+ if(res)
+ return res;
+
+ /* LMv2 response */
+ res = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
+ (unsigned char *)&entropy[0],
+ &ntlm->nonce[0], lmresp);
+ if(res)
+ return res;
+
+ /* NTLMv2 response */
+ res = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
+ (unsigned char *)&entropy[0],
+ ntlm, &ntlmv2resp, &ntresplen);
+ if(res)
+ return res;
+
+ ptr_ntresp = ntlmv2resp;
+ }
+ else
+#endif
+
+#if USE_NTLM2SESSION
+ /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
+ if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
+ unsigned char ntbuffer[0x18];
+ unsigned char tmp[0x18];
+ unsigned char md5sum[MD5_DIGEST_LENGTH];
+ unsigned int entropy[2];
+
+ /* Need to create 8 bytes random data */
+ entropy[0] = Curl_rand(data);
+ entropy[1] = Curl_rand(data);
+
+ /* 8 bytes random data as challenge in lmresp */
+ memcpy(lmresp, entropy, 8);
+
+ /* Pad with zeros */
+ memset(lmresp + 8, 0, 0x10);
+
+ /* Fill tmp with challenge(nonce?) + entropy */
+ memcpy(tmp, &ntlm->nonce[0], 8);
+ memcpy(tmp + 8, entropy, 8);
+
+ Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
+
+ /* We shall only use the first 8 bytes of md5sum, but the des
+ code in Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
+ if(CURLE_OUT_OF_MEMORY ==
+ Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
+
+ /* End of NTLM2 Session code */
+
+ }
+ else
+#endif
+ {
+
+#if USE_NTRESPONSES
+ unsigned char ntbuffer[0x18];
+#endif
+ unsigned char lmbuffer[0x18];
+
+#if USE_NTRESPONSES
+ if(CURLE_OUT_OF_MEMORY ==
+ Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
+ return CURLE_OUT_OF_MEMORY;
+ Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
+#endif
+
+ Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
+ Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
+ /* A safer but less compatible alternative is:
+ * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
+ * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
+ }
+
+ if(unicode) {
+ domlen = domlen * 2;
+ userlen = userlen * 2;
+ hostlen = hostlen * 2;
+ }
+
+ lmrespoff = 64; /* size of the message header */
+#if USE_NTRESPONSES
+ ntrespoff = lmrespoff + 0x18;
+ domoff = ntrespoff + ntresplen;
+#else
+ domoff = lmrespoff + 0x18;
+#endif
+ useroff = domoff + domlen;
+ hostoff = useroff + userlen;
+
+ /* Create the big type-3 message binary blob */
+ size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+ NTLMSSP_SIGNATURE "%c"
+ "\x03%c%c%c" /* 32-bit type = 3 */
+
+ "%c%c" /* LanManager length */
+ "%c%c" /* LanManager allocated space */
+ "%c%c" /* LanManager offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* NT-response length */
+ "%c%c" /* NT-response allocated space */
+ "%c%c" /* NT-response offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* domain length */
+ "%c%c" /* domain allocated space */
+ "%c%c" /* domain name offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* user length */
+ "%c%c" /* user allocated space */
+ "%c%c" /* user offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* host length */
+ "%c%c" /* host allocated space */
+ "%c%c" /* host offset */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c" /* session key length (unknown purpose) */
+ "%c%c" /* session key allocated space (unknown purpose) */
+ "%c%c" /* session key offset (unknown purpose) */
+ "%c%c" /* 2 zeroes */
+
+ "%c%c%c%c", /* flags */
+
+ /* domain string */
+ /* user string */
+ /* host string */
+ /* LanManager response */
+ /* NT response */
+
+ 0, /* zero termination */
+ 0, 0, 0, /* type-3 long, the 24 upper bits */
+
+ SHORTPAIR(0x18), /* LanManager response length, twice */
+ SHORTPAIR(0x18),
+ SHORTPAIR(lmrespoff),
+ 0x0, 0x0,
+
+#if USE_NTRESPONSES
+ SHORTPAIR(ntresplen), /* NT-response length, twice */
+ SHORTPAIR(ntresplen),
+ SHORTPAIR(ntrespoff),
+ 0x0, 0x0,
+#else
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+#endif
+ SHORTPAIR(domlen),
+ SHORTPAIR(domlen),
+ SHORTPAIR(domoff),
+ 0x0, 0x0,
+
+ SHORTPAIR(userlen),
+ SHORTPAIR(userlen),
+ SHORTPAIR(useroff),
+ 0x0, 0x0,
+
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostlen),
+ SHORTPAIR(hostoff),
+ 0x0, 0x0,
+
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+
+ LONGQUARTET(ntlm->flags));
+
+ DEBUGASSERT(size == 64);
+ DEBUGASSERT(size == (size_t)lmrespoff);
+
+ /* We append the binary hashes */
+ if(size < (NTLM_BUFSIZE - 0x18)) {
+ memcpy(&ntlmbuf[size], lmresp, 0x18);
+ size += 0x18;
+ }
+
+ DEBUG_OUT({
+ fprintf(stderr, "**** TYPE3 header lmresp=");
+ ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
+ });
+
+#if USE_NTRESPONSES
+ if(size < (NTLM_BUFSIZE - ntresplen)) {
+ DEBUGASSERT(size == (size_t)ntrespoff);
+ memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
+ size += ntresplen;
+ }
+
+ DEBUG_OUT({
+ fprintf(stderr, "\n ntresp=");
+ ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
+ });
+
+ Curl_safefree(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
+
+#endif
+
+ DEBUG_OUT({
+ fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
+ LONGQUARTET(ntlm->flags), ntlm->flags);
+ ntlm_print_flags(stderr, ntlm->flags);
+ fprintf(stderr, "\n****\n");
+ });
+
+ /* Make sure that the domain, user and host strings fit in the
+ buffer before we copy them there. */
+ if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
+ failf(data, "user + domain + host name too big");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ DEBUGASSERT(size == domoff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], domain, domlen / 2);
+ else
+ memcpy(&ntlmbuf[size], domain, domlen);
+
+ size += domlen;
+
+ DEBUGASSERT(size == useroff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], user, userlen / 2);
+ else
+ memcpy(&ntlmbuf[size], user, userlen);
+
+ size += userlen;
+
+ DEBUGASSERT(size == hostoff);
+ if(unicode)
+ unicodecpy(&ntlmbuf[size], host, hostlen / 2);
+ else
+ memcpy(&ntlmbuf[size], host, hostlen);
+
+ size += hostlen;
+
+ /* Convert domain, user, and host to ASCII but leave the rest as-is */
+ res = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
+ size - domoff);
+ if(res)
+ return CURLE_CONV_FAILED;
+
+ /* Return with binary blob encoded into base64 */
+ return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+#endif
+}
+
+#endif /* USE_NTLM */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ntlm_msgs.h b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_msgs.h
new file mode 100755
index 00000000..80413c88
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_msgs.h
@@ -0,0 +1,177 @@
+#ifndef HEADER_CURL_NTLM_MSGS_H
+#define HEADER_CURL_NTLM_MSGS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NTLM
+
+/* This is to generate a base64 encoded NTLM type-1 message */
+CURLcode Curl_ntlm_create_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen);
+
+/* This is to generate a base64 encoded NTLM type-3 message */
+CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen);
+
+/* This is to decode a NTLM type-2 message */
+CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
+ const char* header,
+ struct ntlmdata* ntlm);
+
+/* This is to decode target info received in NTLM type-2 message */
+CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data,
+ unsigned char* buffer,
+ size_t size,
+ struct ntlmdata* ntlm);
+
+
+/* This is to clean up the ntlm data structure */
+#ifdef USE_WINDOWS_SSPI
+void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm);
+#else
+#define Curl_ntlm_sspi_cleanup(x)
+#endif
+
+/* NTLM buffer fixed size, large enough for long user + host + domain */
+#define NTLM_BUFSIZE 1024
+
+/* Stuff only required for curl_ntlm_msgs.c */
+#ifdef BUILDING_CURL_NTLM_MSGS_C
+
+/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
+
+#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
+/* Indicates that Unicode strings are supported for use in security buffer
+ data. */
+
+#define NTLMFLAG_NEGOTIATE_OEM (1<<1)
+/* Indicates that OEM strings are supported for use in security buffer data. */
+
+#define NTLMFLAG_REQUEST_TARGET (1<<2)
+/* Requests that the server's authentication realm be included in the Type 2
+ message. */
+
+/* unknown (1<<3) */
+#define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
+/* Specifies that authenticated communication between the client and server
+ should carry a digital signature (message integrity). */
+
+#define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
+/* Specifies that authenticated communication between the client and server
+ should be encrypted (message confidentiality). */
+
+#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
+/* Indicates that datagram authentication is being used. */
+
+#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
+/* Indicates that the LAN Manager session key should be used for signing and
+ sealing authenticated communications. */
+
+#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
+/* unknown purpose */
+
+#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
+/* Indicates that NTLM authentication is being used. */
+
+/* unknown (1<<10) */
+
+#define NTLMFLAG_NEGOTIATE_ANONYMOUS (1<<11)
+/* Sent by the client in the Type 3 message to indicate that an anonymous
+ context has been established. This also affects the response fields. */
+
+#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
+/* Sent by the client in the Type 1 message to indicate that a desired
+ authentication realm is included in the message. */
+
+#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
+/* Sent by the client in the Type 1 message to indicate that the client
+ workstation's name is included in the message. */
+
+#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
+/* Sent by the server to indicate that the server and client are on the same
+ machine. Implies that the client may use a pre-established local security
+ context rather than responding to the challenge. */
+
+#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
+/* Indicates that authenticated communication between the client and server
+ should be signed with a "dummy" signature. */
+
+#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
+/* Sent by the server in the Type 2 message to indicate that the target
+ authentication realm is a domain. */
+
+#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
+/* Sent by the server in the Type 2 message to indicate that the target
+ authentication realm is a server. */
+
+#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
+/* Sent by the server in the Type 2 message to indicate that the target
+ authentication realm is a share. Presumably, this is for share-level
+ authentication. Usage is unclear. */
+
+#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
+/* Indicates that the NTLM2 signing and sealing scheme should be used for
+ protecting authenticated communications. */
+
+#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
+/* unknown purpose */
+
+#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
+/* unknown purpose */
+
+#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
+/* unknown purpose */
+
+#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
+/* Sent by the server in the Type 2 message to indicate that it is including a
+ Target Information block in the message. */
+
+/* unknown (1<24) */
+/* unknown (1<25) */
+/* unknown (1<26) */
+/* unknown (1<27) */
+/* unknown (1<28) */
+
+#define NTLMFLAG_NEGOTIATE_128 (1<<29)
+/* Indicates that 128-bit encryption is supported. */
+
+#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
+/* Indicates that the client will provide an encrypted master key in
+ the "Session Key" field of the Type 3 message. */
+
+#define NTLMFLAG_NEGOTIATE_56 (1<<31)
+/* Indicates that 56-bit encryption is supported. */
+
+#endif /* BUILDING_CURL_NTLM_MSGS_C */
+
+#endif /* USE_NTLM */
+
+#endif /* HEADER_CURL_NTLM_MSGS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ntlm_wb.c b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_wb.c
new file mode 100755
index 00000000..23ee7264
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_wb.c
@@ -0,0 +1,435 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+
+/*
+ * NTLM details:
+ *
+ * http://davenport.sourceforge.net/ntlm.html
+ * http://www.innovation.ch/java/ntlm.html
+ */
+
+#define DEBUG_ME 0
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "select.h"
+#include "curl_ntlm_msgs.h"
+#include "curl_ntlm_wb.h"
+#include "url.h"
+#include "strerror.h"
+#include "curl_memory.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+#else
+# define DEBUG_OUT(x) Curl_nop_stmt
+#endif
+
+/* Portable 'sclose_nolog' used only in child process instead of 'sclose'
+ to avoid fooling the socket leak detector */
+#if defined(HAVE_CLOSESOCKET)
+# define sclose_nolog(x) closesocket((x))
+#elif defined(HAVE_CLOSESOCKET_CAMEL)
+# define sclose_nolog(x) CloseSocket((x))
+#else
+# define sclose_nolog(x) close((x))
+#endif
+
+void Curl_ntlm_wb_cleanup(struct connectdata *conn)
+{
+ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
+ sclose(conn->ntlm_auth_hlpr_socket);
+ conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+ }
+
+ if(conn->ntlm_auth_hlpr_pid) {
+ int i;
+ for(i = 0; i < 4; i++) {
+ pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG);
+ if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD)
+ break;
+ switch(i) {
+ case 0:
+ kill(conn->ntlm_auth_hlpr_pid, SIGTERM);
+ break;
+ case 1:
+ /* Give the process another moment to shut down cleanly before
+ bringing down the axe */
+ Curl_wait_ms(1);
+ break;
+ case 2:
+ kill(conn->ntlm_auth_hlpr_pid, SIGKILL);
+ break;
+ case 3:
+ break;
+ }
+ }
+ conn->ntlm_auth_hlpr_pid = 0;
+ }
+
+ Curl_safefree(conn->challenge_header);
+ conn->challenge_header = NULL;
+ Curl_safefree(conn->response_header);
+ conn->response_header = NULL;
+}
+
+static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
+{
+ curl_socket_t sockfds[2];
+ pid_t child_pid;
+ const char *username;
+ char *slash, *domain = NULL;
+ const char *ntlm_auth = NULL;
+ char *ntlm_auth_alloc = NULL;
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
+ struct passwd pw, *pw_res;
+ char pwbuf[1024];
+#endif
+ int error;
+
+ /* Return if communication with ntlm_auth already set up */
+ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
+ conn->ntlm_auth_hlpr_pid)
+ return CURLE_OK;
+
+ username = userp;
+ /* The real ntlm_auth really doesn't like being invoked with an
+ empty username. It won't make inferences for itself, and expects
+ the client to do so (mostly because it's really designed for
+ servers like squid to use for auth, and client support is an
+ afterthought for it). So try hard to provide a suitable username
+ if we don't already have one. But if we can't, provide the
+ empty one anyway. Perhaps they have an implementation of the
+ ntlm_auth helper which *doesn't* need it so we might as well try */
+ if(!username || !username[0]) {
+ username = getenv("NTLMUSER");
+ if(!username || !username[0])
+ username = getenv("LOGNAME");
+ if(!username || !username[0])
+ username = getenv("USER");
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
+ if((!username || !username[0]) &&
+ !getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) &&
+ pw_res) {
+ username = pw.pw_name;
+ }
+#endif
+ if(!username || !username[0])
+ username = userp;
+ }
+ slash = strpbrk(username, "\\/");
+ if(slash) {
+ if((domain = strdup(username)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ slash = domain + (slash - username);
+ *slash = '\0';
+ username = username + (slash - domain) + 1;
+ }
+
+ /* For testing purposes, when DEBUGBUILD is defined and environment
+ variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform
+ NTLM challenge/response which only accepts commands and output
+ strings pre-written in test case definitions */
+#ifdef DEBUGBUILD
+ ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE");
+ if(ntlm_auth_alloc)
+ ntlm_auth = ntlm_auth_alloc;
+ else
+#endif
+ ntlm_auth = NTLM_WB_FILE;
+
+ if(access(ntlm_auth, X_OK) != 0) {
+ error = ERRNO;
+ failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
+ ntlm_auth, error, Curl_strerror(conn, error));
+ goto done;
+ }
+
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
+ error = ERRNO;
+ failf(conn->data, "Could not open socket pair. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ goto done;
+ }
+
+ child_pid = fork();
+ if(child_pid == -1) {
+ error = ERRNO;
+ sclose(sockfds[0]);
+ sclose(sockfds[1]);
+ failf(conn->data, "Could not fork. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ goto done;
+ }
+ else if(!child_pid) {
+ /*
+ * child process
+ */
+
+ /* Don't use sclose in the child since it fools the socket leak detector */
+ sclose_nolog(sockfds[0]);
+ if(dup2(sockfds[1], STDIN_FILENO) == -1) {
+ error = ERRNO;
+ failf(conn->data, "Could not redirect child stdin. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
+ error = ERRNO;
+ failf(conn->data, "Could not redirect child stdout. errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ if(domain)
+ execl(ntlm_auth, ntlm_auth,
+ "--helper-protocol", "ntlmssp-client-1",
+ "--use-cached-creds",
+ "--username", username,
+ "--domain", domain,
+ NULL);
+ else
+ execl(ntlm_auth, ntlm_auth,
+ "--helper-protocol", "ntlmssp-client-1",
+ "--use-cached-creds",
+ "--username", username,
+ NULL);
+
+ error = ERRNO;
+ sclose_nolog(sockfds[1]);
+ failf(conn->data, "Could not execl(). errno %d: %s",
+ error, Curl_strerror(conn, error));
+ exit(1);
+ }
+
+ sclose(sockfds[1]);
+ conn->ntlm_auth_hlpr_socket = sockfds[0];
+ conn->ntlm_auth_hlpr_pid = child_pid;
+ Curl_safefree(domain);
+ Curl_safefree(ntlm_auth_alloc);
+ return CURLE_OK;
+
+done:
+ Curl_safefree(domain);
+ Curl_safefree(ntlm_auth_alloc);
+ return CURLE_REMOTE_ACCESS_DENIED;
+}
+
+static CURLcode ntlm_wb_response(struct connectdata *conn,
+ const char *input, curlntlm state)
+{
+ char *buf = malloc(NTLM_BUFSIZE);
+ size_t len_in = strlen(input), len_out = 0;
+
+ if(!buf)
+ return CURLE_OUT_OF_MEMORY;
+
+ while(len_in > 0) {
+ ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in);
+ if(written == -1) {
+ /* Interrupted by a signal, retry it */
+ if(errno == EINTR)
+ continue;
+ /* write failed if other errors happen */
+ goto done;
+ }
+ input += written;
+ len_in -= written;
+ }
+ /* Read one line */
+ while(1) {
+ ssize_t size;
+ char *newbuf;
+
+ size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
+ if(size == -1) {
+ if(errno == EINTR)
+ continue;
+ goto done;
+ }
+ else if(size == 0)
+ goto done;
+
+ len_out += size;
+ if(buf[len_out - 1] == '\n') {
+ buf[len_out - 1] = '\0';
+ goto wrfinish;
+ }
+ newbuf = realloc(buf, len_out + NTLM_BUFSIZE);
+ if(!newbuf) {
+ free(buf);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ buf = newbuf;
+ }
+ goto done;
+wrfinish:
+ /* Samba/winbind installed but not configured */
+ if(state == NTLMSTATE_TYPE1 &&
+ len_out == 3 &&
+ buf[0] == 'P' && buf[1] == 'W')
+ return CURLE_REMOTE_ACCESS_DENIED;
+ /* invalid response */
+ if(len_out < 4)
+ goto done;
+ if(state == NTLMSTATE_TYPE1 &&
+ (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' '))
+ goto done;
+ if(state == NTLMSTATE_TYPE2 &&
+ (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') &&
+ (buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
+ goto done;
+
+ conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3);
+ free(buf);
+ return CURLE_OK;
+done:
+ free(buf);
+ return CURLE_REMOTE_ACCESS_DENIED;
+}
+
+/*
+ * This is for creating ntlm header output by delegating challenge/response
+ * to Samba's winbind daemon helper ntlm_auth.
+ */
+CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
+ bool proxy)
+{
+ /* point to the address of the pointer that holds the string to send to the
+ server, which is for a plain host or for a HTTP proxy */
+ char **allocuserpwd;
+ /* point to the name and password for this */
+ const char *userp;
+ /* point to the correct struct with this */
+ struct ntlmdata *ntlm;
+ struct auth *authp;
+
+ CURLcode res = CURLE_OK;
+ char *input;
+
+ DEBUGASSERT(conn);
+ DEBUGASSERT(conn->data);
+
+ if(proxy) {
+ allocuserpwd = &conn->allocptr.proxyuserpwd;
+ userp = conn->proxyuser;
+ ntlm = &conn->proxyntlm;
+ authp = &conn->data->state.authproxy;
+ }
+ else {
+ allocuserpwd = &conn->allocptr.userpwd;
+ userp = conn->user;
+ ntlm = &conn->ntlm;
+ authp = &conn->data->state.authhost;
+ }
+ authp->done = FALSE;
+
+ /* not set means empty */
+ if(!userp)
+ userp="";
+
+ switch(ntlm->state) {
+ case NTLMSTATE_TYPE1:
+ default:
+ /* Use Samba's 'winbind' daemon to support NTLM authentication,
+ * by delegating the NTLM challenge/response protocal to a helper
+ * in ntlm_auth.
+ * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
+ * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
+ * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html
+ * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this
+ * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute
+ * filename of ntlm_auth helper.
+ * If NTLM authentication using winbind fails, go back to original
+ * request handling process.
+ */
+ /* Create communication with ntlm_auth */
+ res = ntlm_wb_init(conn, userp);
+ if(res)
+ return res;
+ res = ntlm_wb_response(conn, "YR\n", ntlm->state);
+ if(res)
+ return res;
+
+ Curl_safefree(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: %s\r\n",
+ proxy ? "Proxy-" : "",
+ conn->response_header);
+ DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
+ Curl_safefree(conn->response_header);
+ conn->response_header = NULL;
+ break;
+ case NTLMSTATE_TYPE2:
+ input = aprintf("TT %s\n", conn->challenge_header);
+ if(!input)
+ return CURLE_OUT_OF_MEMORY;
+ res = ntlm_wb_response(conn, input, ntlm->state);
+ free(input);
+ input = NULL;
+ if(res)
+ return res;
+
+ Curl_safefree(*allocuserpwd);
+ *allocuserpwd = aprintf("%sAuthorization: %s\r\n",
+ proxy ? "Proxy-" : "",
+ conn->response_header);
+ DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
+ ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
+ authp->done = TRUE;
+ Curl_ntlm_wb_cleanup(conn);
+ break;
+ case NTLMSTATE_TYPE3:
+ /* connection is already authenticated,
+ * don't send a header in future requests */
+ if(*allocuserpwd) {
+ free(*allocuserpwd);
+ *allocuserpwd=NULL;
+ }
+ authp->done = TRUE;
+ break;
+ }
+
+ return CURLE_OK;
+}
+
+#endif /* USE_NTLM && NTLM_WB_ENABLED */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_ntlm_wb.h b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_wb.h
new file mode 100755
index 00000000..db6bc16b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_ntlm_wb.h
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_NTLM_WB_H
+#define HEADER_CURL_NTLM_WB_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+
+/* this is for creating ntlm header output by delegating challenge/response
+ to Samba's winbind daemon helper ntlm_auth */
+CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
+
+void Curl_ntlm_wb_cleanup(struct connectdata *conn);
+
+#endif /* USE_NTLM && NTLM_WB_ENABLED */
+
+#endif /* HEADER_CURL_NTLM_WB_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_rtmp.c b/external/libcurl_android/jni/libcurl/lib/curl_rtmp.c
new file mode 100755
index 00000000..e0c24b03
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_rtmp.c
@@ -0,0 +1,311 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_LIBRTMP
+
+#include "urldata.h"
+#include "nonblock.h" /* for curlx_nonblock */
+#include "progress.h" /* for Curl_pgrsSetUploadSize */
+#include "transfer.h"
+#include "warnless.h"
+#include <curl/curl.h>
+#include <librtmp/rtmp.h>
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef _WIN32
+#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
+#define SET_RCVTIMEO(tv,s) int tv = s*1000
+#else
+#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
+#endif
+
+#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */
+
+static CURLcode rtmp_setup(struct connectdata *conn);
+static CURLcode rtmp_do(struct connectdata *conn, bool *done);
+static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature);
+static CURLcode rtmp_connect(struct connectdata *conn, bool *done);
+static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead);
+
+static Curl_recv rtmp_recv;
+static Curl_send rtmp_send;
+
+/*
+ * RTMP protocol handler.h, based on http://rtmpdump.mplayerhq.hu
+ */
+
+const struct Curl_handler Curl_handler_rtmp = {
+ "RTMP", /* scheme */
+ rtmp_setup, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMP, /* defport */
+ CURLPROTO_RTMP, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmpt = {
+ "RTMPT", /* scheme */
+ rtmp_setup, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMPT, /* defport */
+ CURLPROTO_RTMPT, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmpe = {
+ "RTMPE", /* scheme */
+ rtmp_setup, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMP, /* defport */
+ CURLPROTO_RTMPE, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmpte = {
+ "RTMPTE", /* scheme */
+ rtmp_setup, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMPT, /* defport */
+ CURLPROTO_RTMPTE, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmps = {
+ "RTMPS", /* scheme */
+ rtmp_setup, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMPS, /* defport */
+ CURLPROTO_RTMPS, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+const struct Curl_handler Curl_handler_rtmpts = {
+ "RTMPTS", /* scheme */
+ rtmp_setup, /* setup_connection */
+ rtmp_do, /* do_it */
+ rtmp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtmp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtmp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_RTMPS, /* defport */
+ CURLPROTO_RTMPTS, /* protocol */
+ PROTOPT_NONE /* flags*/
+};
+
+static CURLcode rtmp_setup(struct connectdata *conn)
+{
+ RTMP *r = RTMP_Alloc();
+
+ if(!r)
+ return CURLE_OUT_OF_MEMORY;
+
+ RTMP_Init(r);
+ RTMP_SetBufferMS(r, DEF_BUFTIME);
+ if(!RTMP_SetupURL(r, conn->data->change.url)) {
+ RTMP_Free(r);
+ return CURLE_URL_MALFORMAT;
+ }
+ conn->proto.generic = r;
+ return CURLE_OK;
+}
+
+static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
+{
+ RTMP *r = conn->proto.generic;
+ SET_RCVTIMEO(tv,10);
+
+ r->m_sb.sb_socket = conn->sock[FIRSTSOCKET];
+
+ /* We have to know if it's a write before we send the
+ * connect request packet
+ */
+ if(conn->data->set.upload)
+ r->Link.protocol |= RTMP_FEATURE_WRITE;
+
+ /* For plain streams, use the buffer toggle trick to keep data flowing */
+ if(!(r->Link.lFlags & RTMP_LF_LIVE) &&
+ !(r->Link.protocol & RTMP_FEATURE_HTTP))
+ r->Link.lFlags |= RTMP_LF_BUFX;
+
+ curlx_nonblock(r->m_sb.sb_socket, FALSE);
+ setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO,
+ (char *)&tv, sizeof(tv));
+
+ if(!RTMP_Connect1(r, NULL))
+ return CURLE_FAILED_INIT;
+
+ /* Clients must send a periodic BytesReceived report to the server */
+ r->m_bSendCounter = true;
+
+ *done = TRUE;
+ conn->recv[FIRSTSOCKET] = rtmp_recv;
+ conn->send[FIRSTSOCKET] = rtmp_send;
+ return CURLE_OK;
+}
+
+static CURLcode rtmp_do(struct connectdata *conn, bool *done)
+{
+ RTMP *r = conn->proto.generic;
+
+ if(!RTMP_ConnectStream(r, 0))
+ return CURLE_FAILED_INIT;
+
+ if(conn->data->set.upload) {
+ Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize);
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+ }
+ else
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+ *done = TRUE;
+ return CURLE_OK;
+}
+
+static CURLcode rtmp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ (void)conn; /* unused */
+ (void)status; /* unused */
+ (void)premature; /* unused */
+
+ return CURLE_OK;
+}
+
+static CURLcode rtmp_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ RTMP *r = conn->proto.generic;
+ (void)dead_connection;
+ if(r) {
+ conn->proto.generic = NULL;
+ RTMP_Close(r);
+ RTMP_Free(r);
+ }
+ return CURLE_OK;
+}
+
+static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
+ size_t len, CURLcode *err)
+{
+ RTMP *r = conn->proto.generic;
+ ssize_t nread;
+
+ (void)sockindex; /* unused */
+
+ nread = RTMP_Read(r, buf, curlx_uztosi(len));
+ if(nread < 0) {
+ if(r->m_read.status == RTMP_READ_COMPLETE ||
+ r->m_read.status == RTMP_READ_EOF) {
+ conn->data->req.size = conn->data->req.bytecount;
+ nread = 0;
+ }
+ else
+ *err = CURLE_RECV_ERROR;
+ }
+ return nread;
+}
+
+static ssize_t rtmp_send(struct connectdata *conn, int sockindex,
+ const void *buf, size_t len, CURLcode *err)
+{
+ RTMP *r = conn->proto.generic;
+ ssize_t num;
+
+ (void)sockindex; /* unused */
+
+ num = RTMP_Write(r, (char *)buf, curlx_uztosi(len));
+ if(num < 0)
+ *err = CURLE_SEND_ERROR;
+
+ return num;
+}
+#endif /* USE_LIBRTMP */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_rtmp.h b/external/libcurl_android/jni/libcurl/lib/curl_rtmp.h
new file mode 100755
index 00000000..4a9e9e60
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_rtmp.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_RTMP_H
+#define HEADER_CURL_RTMP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifdef USE_LIBRTMP
+extern const struct Curl_handler Curl_handler_rtmp;
+extern const struct Curl_handler Curl_handler_rtmpt;
+extern const struct Curl_handler Curl_handler_rtmpe;
+extern const struct Curl_handler Curl_handler_rtmpte;
+extern const struct Curl_handler Curl_handler_rtmps;
+extern const struct Curl_handler Curl_handler_rtmpts;
+#endif
+
+#endif /* HEADER_CURL_RTMP_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_sasl.c b/external/libcurl_android/jni/libcurl/lib/curl_sasl.c
new file mode 100755
index 00000000..7e2b8afa
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_sasl.c
@@ -0,0 +1,741 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC2195 CRAM-MD5 authentication
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4616 PLAIN authentication
+ * RFC6749 OAuth 2.0 Authorization Framework
+ * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "urldata.h"
+
+#include "curl_base64.h"
+#include "curl_md5.h"
+#include "vtls/vtls.h"
+#include "curl_hmac.h"
+#include "curl_ntlm_msgs.h"
+#include "curl_sasl.h"
+#include "warnless.h"
+#include "curl_memory.h"
+#include "strtok.h"
+#include "rawstr.h"
+
+#ifdef USE_NSS
+#include "vtls/nssg.h" /* for Curl_nss_force_init() */
+#endif
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if defined(USE_WINDOWS_SSPI)
+extern void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5);
+#endif
+
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI)
+#define DIGEST_QOP_VALUE_AUTH (1 << 0)
+#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
+#define DIGEST_QOP_VALUE_AUTH_CONF (1 << 2)
+
+#define DIGEST_QOP_VALUE_STRING_AUTH "auth"
+#define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int"
+#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf"
+
+/* Retrieves the value for a corresponding key from the challenge string
+ * returns TRUE if the key could be found, FALSE if it does not exists
+ */
+static bool sasl_digest_get_key_value(const char *chlg,
+ const char *key,
+ char *value,
+ size_t max_val_len,
+ char end_char)
+{
+ char *find_pos;
+ size_t i;
+
+ find_pos = strstr(chlg, key);
+ if(!find_pos)
+ return FALSE;
+
+ find_pos += strlen(key);
+
+ for(i = 0; *find_pos && *find_pos != end_char && i < max_val_len - 1; ++i)
+ value[i] = *find_pos++;
+ value[i] = '\0';
+
+ return TRUE;
+}
+
+static CURLcode sasl_digest_get_qop_values(const char *options, int *value)
+{
+ char *tmp;
+ char *token;
+ char *tok_buf;
+
+ /* Initialise the output */
+ *value = 0;
+
+ /* Tokenise the list of qop values. Use a temporary clone of the buffer since
+ strtok_r() ruins it. */
+ tmp = strdup(options);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ token = strtok_r(tmp, ",", &tok_buf);
+ while(token != NULL) {
+ if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH))
+ *value |= DIGEST_QOP_VALUE_AUTH;
+ else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
+ *value |= DIGEST_QOP_VALUE_AUTH_INT;
+ else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
+ *value |= DIGEST_QOP_VALUE_AUTH_CONF;
+
+ token = strtok_r(NULL, ",", &tok_buf);
+ }
+
+ Curl_safefree(tmp);
+
+ return CURLE_OK;
+}
+#endif
+
+#if !defined(USE_WINDOWS_SSPI)
+/*
+ * Curl_sasl_build_spn()
+ *
+ * This is used to build a SPN string in the format service/host.
+ *
+ * Parameters:
+ *
+ * serivce [in] - The service type such as www, smtp, pop or imap.
+ * instance [in] - The instance name such as the host nme or realm.
+ *
+ * Returns a pointer to the newly allocated SPN.
+ */
+char *Curl_sasl_build_spn(const char *service, const char *host)
+{
+ /* Generate and return our SPN */
+ return aprintf("%s/%s", service, host);
+}
+#endif
+
+/*
+ * Curl_sasl_create_plain_message()
+ *
+ * This is used to generate an already encoded PLAIN message ready
+ * for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result;
+ char *plainauth;
+ size_t ulen;
+ size_t plen;
+
+ ulen = strlen(userp);
+ plen = strlen(passwdp);
+
+ plainauth = malloc(2 * ulen + plen + 2);
+ if(!plainauth) {
+ *outlen = 0;
+ *outptr = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Calculate the reply */
+ memcpy(plainauth, userp, ulen);
+ plainauth[ulen] = '\0';
+ memcpy(plainauth + ulen + 1, userp, ulen);
+ plainauth[2 * ulen + 1] = '\0';
+ memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
+
+ /* Base64 encode the reply */
+ result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
+ outlen);
+ Curl_safefree(plainauth);
+ return result;
+}
+
+/*
+ * Curl_sasl_create_login_message()
+ *
+ * This is used to generate an already encoded LOGIN message containing the
+ * user name or password ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * valuep [in] - The user name or user's password.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
+ const char *valuep, char **outptr,
+ size_t *outlen)
+{
+ size_t vlen = strlen(valuep);
+
+ if(!vlen) {
+ /* Calculate an empty reply */
+ *outptr = strdup("=");
+ if(*outptr) {
+ *outlen = (size_t) 1;
+ return CURLE_OK;
+ }
+
+ *outlen = 0;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Base64 encode the value */
+ return Curl_base64_encode(data, valuep, vlen, outptr, outlen);
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ /*
+ * Curl_sasl_decode_cram_md5_message()
+ *
+ * This is used to decode an already encoded CRAM-MD5 challenge message.
+ *
+ * Parameters:
+ *
+ * chlg64 [in] - Pointer to the base64 encoded challenge message.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr,
+ size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t chlg64len = strlen(chlg64);
+
+ *outptr = NULL;
+ *outlen = 0;
+
+ /* Decode the challenge if necessary */
+ if(chlg64len && *chlg64 != '=')
+ result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen);
+
+ return result;
+ }
+
+ /*
+ * Curl_sasl_create_cram_md5_message()
+ *
+ * This is used to generate an already encoded CRAM-MD5 response message ready
+ * for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg [in] - The challenge.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
+ const char *chlg,
+ const char *userp,
+ const char *passwdp,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t chlglen = 0;
+ HMAC_context *ctxt;
+ unsigned char digest[MD5_DIGEST_LEN];
+ char *response;
+
+ if(chlg)
+ chlglen = strlen(chlg);
+
+ /* Compute the digest using the password as the key */
+ ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
+ (const unsigned char *) passwdp,
+ curlx_uztoui(strlen(passwdp)));
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Update the digest with the given challenge */
+ if(chlglen > 0)
+ Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
+ curlx_uztoui(chlglen));
+
+ /* Finalise the digest */
+ Curl_HMAC_final(ctxt, digest);
+
+ /* Generate the response */
+ response = aprintf(
+ "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ userp, digest[0], digest[1], digest[2], digest[3], digest[4],
+ digest[5], digest[6], digest[7], digest[8], digest[9], digest[10],
+ digest[11], digest[12], digest[13], digest[14], digest[15]);
+ if(!response)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, response, 0, outptr, outlen);
+
+ Curl_safefree(response);
+
+ return result;
+}
+
+#ifndef USE_WINDOWS_SSPI
+/*
+ * sasl_decode_digest_md5_message()
+ *
+ * This is used internally to decode an already encoded DIGEST-MD5 challenge
+ * message into the seperate attributes.
+ *
+ * Parameters:
+ *
+ * chlg64 [in] - Pointer to the base64 encoded challenge message.
+ * nonce [in/out] - The buffer where the nonce will be stored.
+ * nlen [in] - The length of the nonce buffer.
+ * realm [in/out] - The buffer where the realm will be stored.
+ * rlen [in] - The length of the realm buffer.
+ * alg [in/out] - The buffer where the algorithm will be stored.
+ * alen [in] - The length of the algorithm buffer.
+ * qop [in/out] - The buffer where the qop-options will be stored.
+ * qlen [in] - The length of the qop buffer.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode sasl_decode_digest_md5_message(const char *chlg64,
+ char *nonce, size_t nlen,
+ char *realm, size_t rlen,
+ char *alg, size_t alen,
+ char *qop, size_t qlen)
+{
+ CURLcode result = CURLE_OK;
+ unsigned char *chlg = NULL;
+ size_t chlglen = 0;
+ size_t chlg64len = strlen(chlg64);
+
+ /* Decode the base-64 encoded challenge message */
+ if(chlg64len && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Retrieve nonce string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "nonce=\"", nonce, nlen, '\"')) {
+ Curl_safefree(chlg);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Retrieve realm string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "realm=\"", realm, rlen, '\"')) {
+ /* Challenge does not have a realm, set empty string [RFC2831] page 6 */
+ strcpy(realm, "");
+ }
+
+ /* Retrieve algorithm string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "algorithm=", alg, alen, ',')) {
+ Curl_safefree(chlg);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Retrieve qop-options string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "qop=\"", qop, qlen, '\"')) {
+ Curl_safefree(chlg);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ Curl_safefree(chlg);
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_sasl_create_digest_md5_message()
+ *
+ * This is used to generate an already encoded DIGEST-MD5 response message
+ * ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg64 [in] - Pointer to the base64 encoded challenge message.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * service [in] - The service type such as www, smtp, pop or imap.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
+ const char *chlg64,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t i;
+ MD5_context *ctxt;
+ char *response = NULL;
+ unsigned char digest[MD5_DIGEST_LEN];
+ char HA1_hex[2 * MD5_DIGEST_LEN + 1];
+ char HA2_hex[2 * MD5_DIGEST_LEN + 1];
+ char resp_hash_hex[2 * MD5_DIGEST_LEN + 1];
+ char nonce[64];
+ char realm[128];
+ char algorithm[64];
+ char qop_options[64];
+ int qop_values;
+ char cnonce[33];
+ unsigned int entropy[4];
+ char nonceCount[] = "00000001";
+ char method[] = "AUTHENTICATE";
+ char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
+ char *spn = NULL;
+
+ /* Decode the challange message */
+ result = sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
+ realm, sizeof(realm),
+ algorithm, sizeof(algorithm),
+ qop_options, sizeof(qop_options));
+ if(result)
+ return result;
+
+ /* We only support md5 sessions */
+ if(strcmp(algorithm, "md5-sess") != 0)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Get the qop-values from the qop-options */
+ result = sasl_digest_get_qop_values(qop_options, &qop_values);
+ if(result)
+ return result;
+
+ /* We only support auth quality-of-protection */
+ if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Generate 16 bytes of random data */
+ entropy[0] = Curl_rand(data);
+ entropy[1] = Curl_rand(data);
+ entropy[2] = Curl_rand(data);
+ entropy[3] = Curl_rand(data);
+
+ /* Convert the random data into a 32 byte hex string */
+ snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
+ entropy[0], entropy[1], entropy[2], entropy[3]);
+
+ /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_MD5_update(ctxt, (const unsigned char *) userp,
+ curlx_uztoui(strlen(userp)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) realm,
+ curlx_uztoui(strlen(realm)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) passwdp,
+ curlx_uztoui(strlen(passwdp)));
+ Curl_MD5_final(ctxt, digest);
+
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN);
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) nonce,
+ curlx_uztoui(strlen(nonce)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) cnonce,
+ curlx_uztoui(strlen(cnonce)));
+ Curl_MD5_final(ctxt, digest);
+
+ /* Convert calculated 16 octet hex into 32 bytes string */
+ for(i = 0; i < MD5_DIGEST_LEN; i++)
+ snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
+
+ /* Generate our SPN */
+ spn = Curl_sasl_build_spn(service, realm);
+ if(!spn)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Calculate H(A2) */
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt) {
+ Curl_safefree(spn);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_MD5_update(ctxt, (const unsigned char *) method,
+ curlx_uztoui(strlen(method)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) spn,
+ curlx_uztoui(strlen(spn)));
+ Curl_MD5_final(ctxt, digest);
+
+ for(i = 0; i < MD5_DIGEST_LEN; i++)
+ snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]);
+
+ /* Now calculate the response hash */
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt) {
+ Curl_safefree(spn);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN);
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) nonce,
+ curlx_uztoui(strlen(nonce)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+
+ Curl_MD5_update(ctxt, (const unsigned char *) nonceCount,
+ curlx_uztoui(strlen(nonceCount)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) cnonce,
+ curlx_uztoui(strlen(cnonce)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+ Curl_MD5_update(ctxt, (const unsigned char *) qop,
+ curlx_uztoui(strlen(qop)));
+ Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
+
+ Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN);
+ Curl_MD5_final(ctxt, digest);
+
+ for(i = 0; i < MD5_DIGEST_LEN; i++)
+ snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
+
+ /* Generate the response */
+ response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
+ "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s,"
+ "qop=%s",
+ userp, realm, nonce,
+ cnonce, nonceCount, spn, resp_hash_hex, qop);
+ Curl_safefree(spn);
+ if(!response)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, response, 0, outptr, outlen);
+
+ Curl_safefree(response);
+
+ return result;
+}
+#endif /* !USE_WINDOWS_SSPI */
+
+#endif /* CURL_DISABLE_CRYPTO_AUTH */
+
+#ifdef USE_NTLM
+/*
+ * Curl_sasl_create_ntlm_type1_message()
+ *
+ * This is used to generate an already encoded NTLM type-1 message ready for
+ * sending to the recipient.
+ *
+ * Note: This is a simple wrapper of the NTLM function which means that any
+ * SASL based protocols don't have to include the NTLM functions directly.
+ *
+ * Parameters:
+ *
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr, size_t *outlen)
+{
+ return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr, outlen);
+}
+
+/*
+ * Curl_sasl_decode_ntlm_type2_message()
+ *
+ * This is used to decode an already encoded NTLM type-2 message.
+ *
+ * Parameters:
+ *
+ * data [in] - Pointer to session handle.
+ * type2msg [in] - Pointer to the base64 encoded type-2 message.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
+ const char *type2msg,
+ struct ntlmdata *ntlm)
+{
+#ifdef USE_NSS
+ CURLcode result;
+
+ /* make sure the crypto backend is initialized */
+ result = Curl_nss_force_init(data);
+ if(result)
+ return result;
+#endif
+
+ return Curl_ntlm_decode_type2_message(data, type2msg, ntlm);
+}
+
+/*
+ * Curl_sasl_create_ntlm_type3_message()
+ *
+ * This is used to generate an already encoded NTLM type-3 message ready for
+ * sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - Pointer to session handle.
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * ntlm [in/out] - The ntlm data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr, size_t *outlen)
+{
+ return Curl_ntlm_create_type3_message(data, userp, passwdp, ntlm, outptr,
+ outlen);
+}
+#endif /* USE_NTLM */
+
+/*
+ * Curl_sasl_create_xoauth2_message()
+ *
+ * This is used to generate an already encoded OAuth 2.0 message ready for
+ * sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * user [in] - The user name.
+ * bearer [in] - The bearer token.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
+ const char *user,
+ const char *bearer,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ char *xoauth = NULL;
+
+ /* Generate the message */
+ xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
+ if(!xoauth)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Base64 encode the reply */
+ result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen);
+
+ Curl_safefree(xoauth);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_cleanup()
+ *
+ * This is used to cleanup any libraries or curl modules used by the sasl
+ * functions.
+ *
+ * Parameters:
+ *
+ * conn [in] - Pointer to the connection data.
+ * authused [in] - The authentication mechanism used.
+ */
+void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
+{
+#if defined(USE_WINDOWS_SSPI)
+ /* Cleanup the gssapi structure */
+ if(authused == SASL_MECH_GSSAPI) {
+ Curl_sasl_gssapi_cleanup(&conn->krb5);
+ }
+#ifdef USE_NTLM
+ /* Cleanup the ntlm structure */
+ else if(authused == SASL_MECH_NTLM) {
+ Curl_ntlm_sspi_cleanup(&conn->ntlm);
+ }
+#endif
+#else
+ /* Reserved for future use */
+ (void)conn;
+ (void)authused;
+#endif
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_sasl.h b/external/libcurl_android/jni/libcurl/lib/curl_sasl.h
new file mode 100755
index 00000000..e56fa1a5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_sasl.h
@@ -0,0 +1,158 @@
+#ifndef HEADER_CURL_SASL_H
+#define HEADER_CURL_SASL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+struct SessionHandle;
+struct connectdata;
+struct ntlmdata;
+
+#if defined(USE_WINDOWS_SSPI)
+struct kerberos5data;
+#endif
+
+/* Authentication mechanism values */
+#define SASL_AUTH_NONE 0
+#define SASL_AUTH_ANY ~0U
+
+/* Authentication mechanism flags */
+#define SASL_MECH_LOGIN (1 << 0)
+#define SASL_MECH_PLAIN (1 << 1)
+#define SASL_MECH_CRAM_MD5 (1 << 2)
+#define SASL_MECH_DIGEST_MD5 (1 << 3)
+#define SASL_MECH_GSSAPI (1 << 4)
+#define SASL_MECH_EXTERNAL (1 << 5)
+#define SASL_MECH_NTLM (1 << 6)
+#define SASL_MECH_XOAUTH2 (1 << 7)
+
+/* Authentication mechanism strings */
+#define SASL_MECH_STRING_LOGIN "LOGIN"
+#define SASL_MECH_STRING_PLAIN "PLAIN"
+#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5"
+#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5"
+#define SASL_MECH_STRING_GSSAPI "GSSAPI"
+#define SASL_MECH_STRING_EXTERNAL "EXTERNAL"
+#define SASL_MECH_STRING_NTLM "NTLM"
+#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
+
+/* This is used to test whether the line starts with the given mechanism */
+#define sasl_mech_equal(line, wordlen, mech) \
+ (wordlen == (sizeof(mech) - 1) / sizeof(char) && \
+ !memcmp(line, mech, wordlen))
+
+/* This is used to build a SPN string */
+#if !defined(USE_WINDOWS_SSPI)
+char *Curl_sasl_build_spn(const char *service, const char *instance);
+#else
+TCHAR *Curl_sasl_build_spn(const char *service, const char *instance);
+#endif
+
+/* This is used to generate a base64 encoded PLAIN authentication message */
+CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ char **outptr, size_t *outlen);
+
+/* This is used to generate a base64 encoded LOGIN authentication message
+ containing either the user name or password details */
+CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
+ const char *valuep, char **outptr,
+ size_t *outlen);
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+/* This is used to decode a base64 encoded CRAM-MD5 challange message */
+CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr,
+ size_t *outlen);
+
+/* This is used to generate a base64 encoded CRAM-MD5 response message */
+CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
+ const char *chlg,
+ const char *user,
+ const char *passwdp,
+ char **outptr, size_t *outlen);
+
+/* This is used to generate a base64 encoded DIGEST-MD5 response message */
+CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
+ const char *chlg64,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ char **outptr, size_t *outlen);
+#endif
+
+#ifdef USE_NTLM
+/* This is used to generate a base64 encoded NTLM type-1 message */
+CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr,
+ size_t *outlen);
+
+/* This is used to decode a base64 encoded NTLM type-2 message */
+CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
+ const char *type2msg,
+ struct ntlmdata *ntlm);
+
+/* This is used to generate a base64 encoded NTLM type-3 message */
+CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ struct ntlmdata *ntlm,
+ char **outptr, size_t *outlen);
+
+#endif /* USE_NTLM */
+
+#if defined(USE_WINDOWS_SSPI)
+/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token
+ message */
+CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ const bool mutual,
+ const char *chlg64,
+ struct kerberos5data *krb5,
+ char **outptr, size_t *outlen);
+
+/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security
+ token message */
+CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
+ const char *input,
+ struct kerberos5data *krb5,
+ char **outptr,
+ size_t *outlen);
+#endif
+
+/* This is used to generate a base64 encoded XOAUTH2 authentication message
+ containing the user name and bearer token */
+CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
+ const char *user,
+ const char *bearer,
+ char **outptr, size_t *outlen);
+
+/* This is used to cleanup any libraries or curl modules used by the sasl
+ functions */
+void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);
+
+#endif /* HEADER_CURL_SASL_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_sasl_sspi.c b/external/libcurl_android/jni/libcurl/lib/curl_sasl_sspi.c
new file mode 100755
index 00000000..df4da964
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_sasl_sspi.c
@@ -0,0 +1,696 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2014, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_WINDOWS_SSPI)
+
+#include <curl/curl.h>
+
+#include "curl_sasl.h"
+#include "urldata.h"
+#include "curl_base64.h"
+#include "warnless.h"
+#include "curl_memory.h"
+#include "curl_multibyte.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5);
+
+/*
+ * Curl_sasl_build_spn()
+ *
+ * This is used to build a SPN string in the format service/host.
+ *
+ * Parameters:
+ *
+ * serivce [in] - The service type such as www, smtp, pop or imap.
+ * instance [in] - The instance name such as the host nme or realm.
+ *
+ * Returns a pointer to the newly allocated SPN.
+ */
+TCHAR *Curl_sasl_build_spn(const char *service, const char *host)
+{
+ char *utf8_spn = NULL;
+ TCHAR *tchar_spn = NULL;
+
+ /* Note: We could use DsMakeSPN() or DsClientMakeSpnForTargetServer() rather
+ than doing this ourselves but the first is only available in Windows XP
+ and Windows Server 2003 and the latter is only available in Windows 2000
+ but not Windows95/98/ME or Windows NT4.0 unless the Active Directory
+ Client Extensions are installed. As such it is far simpler for us to
+ formulate the SPN instead. */
+
+ /* Allocate our UTF8 based SPN */
+ utf8_spn = aprintf("%s/%s", service, host);
+ if(!utf8_spn) {
+ return NULL;
+ }
+
+ /* Allocate our TCHAR based SPN */
+ tchar_spn = Curl_convert_UTF8_to_tchar(utf8_spn);
+ if(!tchar_spn) {
+ Curl_safefree(utf8_spn);
+
+ return NULL;
+ }
+
+ /* Release the UTF8 variant when operating with Unicode */
+ if(utf8_spn != tchar_spn)
+ Curl_safefree(utf8_spn);
+
+ /* Return our newly allocated SPN */
+ return tchar_spn;
+}
+
+#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+/*
+ * Curl_sasl_create_digest_md5_message()
+ *
+ * This is used to generate an already encoded DIGEST-MD5 response message
+ * ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg64 [in] - Pointer to the base64 encoded challenge message.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * service [in] - The service type such as www, smtp, pop or imap.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
+ const char *chlg64,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ TCHAR *spn = NULL;
+ size_t chlglen = 0;
+ size_t resp_max = 0;
+ unsigned char *chlg = NULL;
+ unsigned char *resp = NULL;
+ CredHandle handle;
+ CtxtHandle ctx;
+ PSecPkgInfo SecurityPackage;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SecBuffer chlg_buf;
+ SecBuffer resp_buf;
+ SecBufferDesc chlg_desc;
+ SecBufferDesc resp_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
+
+ /* Decode the base-64 encoded challenge message */
+ if(strlen(chlg64) && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Ensure we have some login credientials as DigestSSP cannot use the current
+ Windows user like NTLMSSP can */
+ if(!userp || !*userp) {
+ Curl_safefree(chlg);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Query the security package for DigestSSP */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT("WDigest"),
+ &SecurityPackage);
+ if(status != SEC_E_OK) {
+ Curl_safefree(chlg);
+
+ return CURLE_NOT_BUILT_IN;
+ }
+
+ resp_max = SecurityPackage->cbMaxToken;
+
+ /* Release the package buffer as it is not required anymore */
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+
+ /* Allocate our response buffer */
+ resp = malloc(resp_max);
+ if(!resp) {
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Generate our SPN */
+ spn = Curl_sasl_build_spn(service, data->easy_conn->host.name);
+ if(!spn) {
+ Curl_safefree(resp);
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Populate our identity structure */
+ result = Curl_create_sspi_identity(userp, passwdp, &identity);
+ if(result) {
+ Curl_safefree(spn);
+ Curl_safefree(resp);
+ Curl_safefree(chlg);
+
+ return result;
+ }
+
+ /* Acquire our credientials handle */
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT("WDigest"),
+ SECPKG_CRED_OUTBOUND, NULL,
+ &identity, NULL, NULL,
+ &handle, &tsDummy);
+
+ if(status != SEC_E_OK) {
+ Curl_sspi_free_identity(&identity);
+ Curl_safefree(spn);
+ Curl_safefree(resp);
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Setup the challenge "input" security buffer */
+ chlg_desc.ulVersion = SECBUFFER_VERSION;
+ chlg_desc.cBuffers = 1;
+ chlg_desc.pBuffers = &chlg_buf;
+ chlg_buf.BufferType = SECBUFFER_TOKEN;
+ chlg_buf.pvBuffer = chlg;
+ chlg_buf.cbBuffer = curlx_uztoul(chlglen);
+
+ /* Setup the response "output" security buffer */
+ resp_desc.ulVersion = SECBUFFER_VERSION;
+ resp_desc.cBuffers = 1;
+ resp_desc.pBuffers = &resp_buf;
+ resp_buf.BufferType = SECBUFFER_TOKEN;
+ resp_buf.pvBuffer = resp;
+ resp_buf.cbBuffer = curlx_uztoul(resp_max);
+
+ /* Generate our challenge-response message */
+ status = s_pSecFn->InitializeSecurityContext(&handle, NULL, spn, 0, 0, 0,
+ &chlg_desc, 0, &ctx,
+ &resp_desc, &attrs, &tsDummy);
+
+ if(status == SEC_I_COMPLETE_AND_CONTINUE ||
+ status == SEC_I_CONTINUE_NEEDED)
+ s_pSecFn->CompleteAuthToken(&handle, &resp_desc);
+ else if(status != SEC_E_OK) {
+ s_pSecFn->FreeCredentialsHandle(&handle);
+ Curl_sspi_free_identity(&identity);
+ Curl_safefree(spn);
+ Curl_safefree(resp);
+ Curl_safefree(chlg);
+
+ return CURLE_RECV_ERROR;
+ }
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *)resp, resp_buf.cbBuffer, outptr,
+ outlen);
+
+ /* Free our handles */
+ s_pSecFn->DeleteSecurityContext(&ctx);
+ s_pSecFn->FreeCredentialsHandle(&handle);
+
+ /* Free the identity structure */
+ Curl_sspi_free_identity(&identity);
+
+ /* Free the SPN */
+ Curl_safefree(spn);
+
+ /* Free the response buffer */
+ Curl_safefree(resp);
+
+ /* Free the decoeded challenge message */
+ Curl_safefree(chlg);
+
+ return result;
+}
+
+#endif /* !CURL_DISABLE_CRYPTO_AUTH */
+
+/*
+ * Curl_sasl_create_gssapi_user_message()
+ *
+ * This is used to generate an already encoded GSSAPI (Kerberos V5) user token
+ * message ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * userp [in] - The user name.
+ * passdwp [in] - The user's password.
+ * service [in] - The service type such as www, smtp, pop or imap.
+ * mutual_auth [in] - Flag specifing whether or not mutual authentication
+ * is enabled.
+ * chlg64 [in] - Pointer to the optional base64 encoded challenge
+ * message.
+ * krb5 [in/out] - The gssapi data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_gssapi_user_message(struct SessionHandle *data,
+ const char *userp,
+ const char *passwdp,
+ const char *service,
+ const bool mutual_auth,
+ const char *chlg64,
+ struct kerberos5data *krb5,
+ char **outptr, size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t chlglen = 0;
+ unsigned char *chlg = NULL;
+ CtxtHandle context;
+ PSecPkgInfo SecurityPackage;
+ SecBuffer chlg_buf;
+ SecBuffer resp_buf;
+ SecBufferDesc chlg_desc;
+ SecBufferDesc resp_desc;
+ SECURITY_STATUS status;
+ unsigned long attrs;
+ TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */
+
+ if(!krb5->credentials) {
+ /* Query the security package for Kerberos */
+ status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT("Kerberos"),
+ &SecurityPackage);
+ if(status != SEC_E_OK) {
+ return CURLE_NOT_BUILT_IN;
+ }
+
+ krb5->token_max = SecurityPackage->cbMaxToken;
+
+ /* Release the package buffer as it is not required anymore */
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+
+ /* Generate our SPN */
+ krb5->spn = Curl_sasl_build_spn(service, data->easy_conn->host.name);
+ if(!krb5->spn)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(userp && *userp) {
+ /* Populate our identity structure */
+ result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity);
+ if(result)
+ return result;
+
+ /* Allow proper cleanup of the identity structure */
+ krb5->p_identity = &krb5->identity;
+
+ /* Allocate our response buffer */
+ krb5->output_token = malloc(krb5->token_max);
+ if(!krb5->output_token)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else
+ /* Use the current Windows user */
+ krb5->p_identity = NULL;
+
+ /* Allocate our credentials handle */
+ krb5->credentials = malloc(sizeof(CredHandle));
+ if(!krb5->credentials)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(krb5->credentials, 0, sizeof(CredHandle));
+
+ /* Acquire our credientials handle */
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT("Kerberos"),
+ SECPKG_CRED_OUTBOUND, NULL,
+ krb5->p_identity, NULL, NULL,
+ krb5->credentials, &tsDummy);
+ if(status != SEC_E_OK)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Allocate our new context handle */
+ krb5->context = malloc(sizeof(CtxtHandle));
+ if(!krb5->context)
+ return CURLE_OUT_OF_MEMORY;
+
+ memset(krb5->context, 0, sizeof(CtxtHandle));
+ }
+ else {
+ /* Decode the base-64 encoded challenge message */
+ if(strlen(chlg64) && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Setup the challenge "input" security buffer */
+ chlg_desc.ulVersion = SECBUFFER_VERSION;
+ chlg_desc.cBuffers = 1;
+ chlg_desc.pBuffers = &chlg_buf;
+ chlg_buf.BufferType = SECBUFFER_TOKEN;
+ chlg_buf.pvBuffer = chlg;
+ chlg_buf.cbBuffer = curlx_uztoul(chlglen);
+ }
+
+ /* Setup the response "output" security buffer */
+ resp_desc.ulVersion = SECBUFFER_VERSION;
+ resp_desc.cBuffers = 1;
+ resp_desc.pBuffers = &resp_buf;
+ resp_buf.BufferType = SECBUFFER_TOKEN;
+ resp_buf.pvBuffer = krb5->output_token;
+ resp_buf.cbBuffer = curlx_uztoul(krb5->token_max);
+
+ /* Generate our challenge-response message */
+ status = s_pSecFn->InitializeSecurityContext(krb5->credentials,
+ chlg ? krb5->context : NULL,
+ krb5->spn,
+ (mutual_auth ?
+ ISC_REQ_MUTUAL_AUTH : 0),
+ 0, SECURITY_NATIVE_DREP,
+ chlg ? &chlg_desc : NULL, 0,
+ &context,
+ &resp_desc, &attrs,
+ &tsDummy);
+
+ if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ Curl_safefree(chlg);
+
+ return CURLE_RECV_ERROR;
+ }
+
+ if(memcmp(&context, krb5->context, sizeof(context))) {
+ s_pSecFn->DeleteSecurityContext(krb5->context);
+
+ memcpy(krb5->context, &context, sizeof(context));
+ }
+
+ if(resp_buf.cbBuffer) {
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *)resp_buf.pvBuffer,
+ resp_buf.cbBuffer, outptr, outlen);
+ }
+
+ /* Free the decoded challenge */
+ Curl_safefree(chlg);
+
+ return result;
+}
+
+/*
+ * Curl_sasl_create_gssapi_security_message()
+ *
+ * This is used to generate an already encoded GSSAPI (Kerberos V5) security
+ * token message ready for sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data [in] - The session handle.
+ * chlg64 [in] - Pointer to the optional base64 encoded challenge message.
+ * krb5 [in/out] - The gssapi data struct being used and modified.
+ * outptr [in/out] - The address where a pointer to newly allocated memory
+ * holding the result will be stored upon completion.
+ * outlen [out] - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_sasl_create_gssapi_security_message(struct SessionHandle *data,
+ const char *chlg64,
+ struct kerberos5data *krb5,
+ char **outptr,
+ size_t *outlen)
+{
+ CURLcode result = CURLE_OK;
+ size_t offset = 0;
+ size_t chlglen = 0;
+ size_t messagelen = 0;
+ size_t appdatalen = 0;
+ unsigned char *chlg = NULL;
+ unsigned char *trailer = NULL;
+ unsigned char *message = NULL;
+ unsigned char *padding = NULL;
+ unsigned char *appdata = NULL;
+ SecBuffer input_buf[2];
+ SecBuffer wrap_buf[3];
+ SecBufferDesc input_desc;
+ SecBufferDesc wrap_desc;
+ unsigned long indata = 0;
+ unsigned long outdata = 0;
+ unsigned long qop = 0;
+ unsigned long sec_layer = 0;
+ unsigned long max_size = 0;
+ SecPkgContext_Sizes sizes;
+ SecPkgCredentials_Names names;
+ SECURITY_STATUS status;
+
+ /* TODO: Verify the unicodeness of this function */
+
+ /* Decode the base-64 encoded input message */
+ if(strlen(chlg64) && *chlg64 != '=') {
+ result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ if(result)
+ return result;
+ }
+
+ /* Ensure we have a valid challenge message */
+ if(!chlg)
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Get our response size information */
+ status = s_pSecFn->QueryContextAttributes(krb5->context,
+ SECPKG_ATTR_SIZES,
+ &sizes);
+ if(status != SEC_E_OK) {
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Get the fully qualified username back from the context */
+ status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials,
+ SECPKG_CRED_ATTR_NAMES,
+ &names);
+ if(status != SEC_E_OK) {
+ Curl_safefree(chlg);
+
+ return CURLE_RECV_ERROR;
+ }
+
+ /* Setup the "input" security buffer */
+ input_desc.ulVersion = SECBUFFER_VERSION;
+ input_desc.cBuffers = 2;
+ input_desc.pBuffers = input_buf;
+ input_buf[0].BufferType = SECBUFFER_STREAM;
+ input_buf[0].pvBuffer = chlg;
+ input_buf[0].cbBuffer = curlx_uztoul(chlglen);
+ input_buf[1].BufferType = SECBUFFER_DATA;
+ input_buf[1].pvBuffer = NULL;
+ input_buf[1].cbBuffer = 0;
+
+ /* Decrypt in the inbound challenge obtaining the qop */
+ status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop);
+ if(status != SEC_E_OK) {
+ Curl_safefree(chlg);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Not 4 octets long to fail as per RFC4752 Section 3.1 */
+ if(input_buf[1].cbBuffer != 4) {
+ Curl_safefree(chlg);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Copy the data out into a coinput_bufnvenient variable and free the SSPI
+ allocated buffer as it is not required anymore */
+ memcpy(&indata, input_buf[1].pvBuffer, 4);
+ s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
+
+ /* Extract the security layer */
+ sec_layer = indata & 0x000000FF;
+ if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) {
+ Curl_safefree(chlg);
+
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ /* Extract the maximum message size the server can receive */
+ max_size = ntohl(indata & 0xFFFFFF00);
+ if(max_size > 0) {
+ /* The server has told us it supports a maximum receive buffer, however, as
+ we don't require one unless we are encrypting data we, tell the server
+ our receive buffer is zero. */
+ max_size = 0;
+ }
+
+ outdata = htonl(max_size) | sec_layer;
+
+ /* Allocate the trailer */
+ trailer = malloc(sizes.cbSecurityTrailer);
+ if(!trailer) {
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Allocate our message */
+ messagelen = 4 + strlen(names.sUserName) + 1;
+ message = malloc(messagelen);
+ if(!message) {
+ Curl_safefree(trailer);
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Populate the message with the security layer, client supported receive
+ message size and authorization identity including the 0x00 based
+ terminator. Note: Dispite RFC4752 Section 3.1 stating "The authorization
+ identity is not terminated with the zero-valued (%x00) octet." it seems
+ necessary to include it. */
+ memcpy(message, &outdata, 4);
+ strcpy((char *)message + 4, names.sUserName);
+
+ /* Allocate the padding */
+ padding = malloc(sizes.cbBlockSize);
+ if(!padding) {
+ Curl_safefree(message);
+ Curl_safefree(trailer);
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Setup the "authentication data" security buffer */
+ wrap_desc.ulVersion = SECBUFFER_VERSION;
+ wrap_desc.cBuffers = 3;
+ wrap_desc.pBuffers = wrap_buf;
+ wrap_buf[0].BufferType = SECBUFFER_TOKEN;
+ wrap_buf[0].pvBuffer = trailer;
+ wrap_buf[0].cbBuffer = sizes.cbSecurityTrailer;
+ wrap_buf[1].BufferType = SECBUFFER_DATA;
+ wrap_buf[1].pvBuffer = message;
+ wrap_buf[1].cbBuffer = curlx_uztoul(messagelen);
+ wrap_buf[2].BufferType = SECBUFFER_PADDING;
+ wrap_buf[2].pvBuffer = padding;
+ wrap_buf[2].cbBuffer = sizes.cbBlockSize;
+
+ /* Encrypt the data */
+ status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT,
+ &wrap_desc, 0);
+ if(status != SEC_E_OK) {
+ Curl_safefree(padding);
+ Curl_safefree(message);
+ Curl_safefree(trailer);
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Allocate the encryption (wrap) buffer */
+ appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer +
+ wrap_buf[2].cbBuffer;
+ appdata = malloc(appdatalen);
+ if(!appdata) {
+ Curl_safefree(padding);
+ Curl_safefree(message);
+ Curl_safefree(trailer);
+ Curl_safefree(chlg);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Populate the encryption buffer */
+ memcpy(appdata, wrap_buf[0].pvBuffer, wrap_buf[0].cbBuffer);
+ offset += wrap_buf[0].cbBuffer;
+ memcpy(appdata + offset, wrap_buf[1].pvBuffer, wrap_buf[1].cbBuffer);
+ offset += wrap_buf[1].cbBuffer;
+ memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer);
+
+ /* Base64 encode the response */
+ result = Curl_base64_encode(data, (char *)appdata, appdatalen, outptr,
+ outlen);
+
+ /* Free all of our local buffers */
+ Curl_safefree(appdata);
+ Curl_safefree(padding);
+ Curl_safefree(message);
+ Curl_safefree(trailer);
+ Curl_safefree(chlg);
+
+ return result;
+}
+
+void Curl_sasl_gssapi_cleanup(struct kerberos5data *krb5)
+{
+ /* Free the context */
+ if(krb5->context) {
+ s_pSecFn->DeleteSecurityContext(krb5->context);
+ free(krb5->context);
+ krb5->context = NULL;
+ }
+
+ /* Free the credientials handle */
+ if(krb5->credentials) {
+ s_pSecFn->FreeCredentialsHandle(krb5->credentials);
+ free(krb5->credentials);
+ krb5->credentials = NULL;
+ }
+
+ /* Free our identity */
+ Curl_sspi_free_identity(krb5->p_identity);
+ krb5->p_identity = NULL;
+
+ /* Free the SPN and output token */
+ Curl_safefree(krb5->spn);
+ Curl_safefree(krb5->output_token);
+
+ /* Reset any variables */
+ krb5->token_max = 0;
+}
+
+#endif /* USE_WINDOWS_SSPI */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_sec.h b/external/libcurl_android/jni/libcurl/lib/curl_sec.h
new file mode 100755
index 00000000..82151e9c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_sec.h
@@ -0,0 +1,51 @@
+#ifndef HEADER_CURL_SECURITY_H
+#define HEADER_CURL_SECURITY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct Curl_sec_client_mech {
+ const char *name;
+ size_t size;
+ int (*init)(void *);
+ int (*auth)(void *, struct connectdata *);
+ void (*end)(void *);
+ int (*check_prot)(void *, int);
+ int (*overhead)(void *, int, int);
+ int (*encode)(void *, const void*, int, int, void**, struct connectdata *);
+ int (*decode)(void *, void*, int, int, struct connectdata *);
+};
+
+#define AUTH_OK 0
+#define AUTH_CONTINUE 1
+#define AUTH_ERROR 2
+
+#ifdef HAVE_GSSAPI
+int Curl_sec_read_msg (struct connectdata *conn, char *,
+ enum protection_level);
+void Curl_sec_end (struct connectdata *);
+CURLcode Curl_sec_login (struct connectdata *);
+int Curl_sec_request_prot (struct connectdata *conn, const char *level);
+
+extern struct Curl_sec_client_mech Curl_krb5_client_mech;
+#endif
+
+#endif /* HEADER_CURL_SECURITY_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_setup.h b/external/libcurl_android/jni/libcurl/lib/curl_setup.h
new file mode 100755
index 00000000..173731c4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_setup.h
@@ -0,0 +1,693 @@
+#ifndef HEADER_CURL_SETUP_H
+#define HEADER_CURL_SETUP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Define WIN32 when build target is Win32 API
+ */
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \
+ !defined(__SYMBIAN32__)
+#define WIN32
+#endif
+
+/*
+ * Include configuration script results or hand-crafted
+ * configuration file for platforms which lack config tool.
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "curl_config.h"
+
+#else /* HAVE_CONFIG_H */
+
+#ifdef _WIN32_WCE
+# include "config-win32ce.h"
+#else
+# ifdef WIN32
+# include "config-win32.h"
+# endif
+#endif
+
+#if defined(macintosh) && defined(__MRC__)
+# include "config-mac.h"
+#endif
+
+#ifdef __riscos__
+# include "config-riscos.h"
+#endif
+
+#ifdef __AMIGA__
+# include "config-amigaos.h"
+#endif
+
+#ifdef __SYMBIAN32__
+# include "config-symbian.h"
+#endif
+
+#ifdef __OS400__
+# include "config-os400.h"
+#endif
+
+#ifdef TPF
+# include "config-tpf.h"
+#endif
+
+#ifdef __VXWORKS__
+# include "config-vxworks.h"
+#endif
+
+#endif /* HAVE_CONFIG_H */
+
+/* ================================================================ */
+/* Definition of preprocessor macros/symbols which modify compiler */
+/* behavior or generated code characteristics must be done here, */
+/* as appropriate, before any system header file is included. It is */
+/* also possible to have them defined in the config file included */
+/* before this point. As a result of all this we frown inclusion of */
+/* system header files in our config files, avoid this at any cost. */
+/* ================================================================ */
+
+/*
+ * AIX 4.3 and newer needs _THREAD_SAFE defined to build
+ * proper reentrant code. Others may also need it.
+ */
+
+#ifdef NEED_THREAD_SAFE
+# ifndef _THREAD_SAFE
+# define _THREAD_SAFE
+# endif
+#endif
+
+/*
+ * Tru64 needs _REENTRANT set for a few function prototypes and
+ * things to appear in the system header files. Unixware needs it
+ * to build proper reentrant code. Others may also need it.
+ */
+
+#ifdef NEED_REENTRANT
+# ifndef _REENTRANT
+# define _REENTRANT
+# endif
+#endif
+
+/* Solaris needs this to get a POSIX-conformant getpwuid_r */
+#if defined(sun) || defined(__sun)
+# ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+# endif
+#endif
+
+/* ================================================================ */
+/* If you need to include a system header file for your platform, */
+/* please, do it beyond the point further indicated in this file. */
+/* ================================================================ */
+
+/*
+ * libcurl's external interface definitions are also used internally,
+ * and might also include required system header files to define them.
+ */
+
+#include <curl/curlbuild.h>
+
+/*
+ * Compile time sanity checks must also be done when building the library.
+ */
+
+#include <curl/curlrules.h>
+
+/*
+ * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro
+ */
+
+#ifdef SIZEOF_CURL_OFF_T
+# error "SIZEOF_CURL_OFF_T shall not be defined!"
+ Error Compilation_aborted_SIZEOF_CURL_OFF_T_shall_not_be_defined
+#endif
+
+/*
+ * Disable other protocols when http is the only one desired.
+ */
+
+#ifdef HTTP_ONLY
+# ifndef CURL_DISABLE_TFTP
+# define CURL_DISABLE_TFTP
+# endif
+# ifndef CURL_DISABLE_FTP
+# define CURL_DISABLE_FTP
+# endif
+# ifndef CURL_DISABLE_LDAP
+# define CURL_DISABLE_LDAP
+# endif
+# ifndef CURL_DISABLE_TELNET
+# define CURL_DISABLE_TELNET
+# endif
+# ifndef CURL_DISABLE_DICT
+# define CURL_DISABLE_DICT
+# endif
+# ifndef CURL_DISABLE_FILE
+# define CURL_DISABLE_FILE
+# endif
+# ifndef CURL_DISABLE_RTSP
+# define CURL_DISABLE_RTSP
+# endif
+# ifndef CURL_DISABLE_POP3
+# define CURL_DISABLE_POP3
+# endif
+# ifndef CURL_DISABLE_IMAP
+# define CURL_DISABLE_IMAP
+# endif
+# ifndef CURL_DISABLE_SMTP
+# define CURL_DISABLE_SMTP
+# endif
+# ifndef CURL_DISABLE_RTSP
+# define CURL_DISABLE_RTSP
+# endif
+# ifndef CURL_DISABLE_RTMP
+# define CURL_DISABLE_RTMP
+# endif
+# ifndef CURL_DISABLE_GOPHER
+# define CURL_DISABLE_GOPHER
+# endif
+#endif
+
+/*
+ * When http is disabled rtsp is not supported.
+ */
+
+#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP)
+# define CURL_DISABLE_RTSP
+#endif
+
+/* ================================================================ */
+/* No system header file shall be included in this file before this */
+/* point. The only allowed ones are those included from curlbuild.h */
+/* ================================================================ */
+
+/*
+ * OS/400 setup file includes some system headers.
+ */
+
+#ifdef __OS400__
+# include "setup-os400.h"
+#endif
+
+/*
+ * VMS setup file includes some system headers.
+ */
+
+#ifdef __VMS
+# include "setup-vms.h"
+#endif
+
+/*
+ * Include header files for windows builds before redefining anything.
+ * Use this preprocessor block only to include or exclude windows.h,
+ * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs
+ * to any other further and independent block. Under Cygwin things work
+ * just as under linux (e.g. <sys/socket.h>) and the winsock headers should
+ * never be included when __CYGWIN__ is defined. configure script takes
+ * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H,
+ * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
+ */
+
+#ifdef HAVE_WINDOWS_H
+# if defined(UNICODE) && !defined(_UNICODE)
+# define _UNICODE
+# endif
+# if defined(_UNICODE) && !defined(UNICODE)
+# define UNICODE
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+# ifdef HAVE_WINSOCK2_H
+# include <winsock2.h>
+# ifdef HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+# endif
+# else
+# ifdef HAVE_WINSOCK_H
+# include <winsock.h>
+# endif
+# endif
+# include <tchar.h>
+# ifdef UNICODE
+ typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
+# endif
+#endif
+
+/*
+ * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
+ * define USE_WINSOCK to 1 if we have and use WINSOCK API, else
+ * undefine USE_WINSOCK.
+ */
+
+#undef USE_WINSOCK
+
+#ifdef HAVE_WINSOCK2_H
+# define USE_WINSOCK 2
+#else
+# ifdef HAVE_WINSOCK_H
+# define USE_WINSOCK 1
+# endif
+#endif
+
+#ifdef USE_LWIPSOCK
+# include <lwip/init.h>
+# include <lwip/sockets.h>
+# include <lwip/netdb.h>
+#endif
+
+#ifdef HAVE_EXTRA_STRICMP_H
+# include <extra/stricmp.h>
+#endif
+
+#ifdef HAVE_EXTRA_STRDUP_H
+# include <extra/strdup.h>
+#endif
+
+#ifdef TPF
+# include <strings.h> /* for bzero, strcasecmp, and strncasecmp */
+# include <string.h> /* for strcpy and strlen */
+# include <stdlib.h> /* for rand and srand */
+# include <sys/socket.h> /* for select and ioctl*/
+# include <netdb.h> /* for in_addr_t definition */
+# include <tpf/sysapi.h> /* for tpf_process_signals */
+ /* change which select is used for libcurl */
+# define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e)
+#endif
+
+#ifdef __VXWORKS__
+# include <sockLib.h> /* for generic BSD socket functions */
+# include <ioLib.h> /* for basic I/O interface functions */
+#endif
+
+#ifdef __AMIGA__
+# ifndef __ixemul__
+# include <exec/types.h>
+# include <exec/execbase.h>
+# include <proto/exec.h>
+# include <proto/dos.h>
+# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
+# endif
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#ifdef __TANDEM /* for nsr-tandem-nsk systems */
+#include <floss.h>
+#endif
+
+#ifndef STDC_HEADERS /* no standard C headers! */
+#include <curl/stdcheaders.h>
+#endif
+
+#ifdef __POCC__
+# include <sys/types.h>
+# include <unistd.h>
+# define sys_nerr EILSEQ
+#endif
+
+/*
+ * Salford-C kludge section (mostly borrowed from wxWidgets).
+ */
+#ifdef __SALFORDC__
+ #pragma suppress 353 /* Possible nested comments */
+ #pragma suppress 593 /* Define not used */
+ #pragma suppress 61 /* enum has no name */
+ #pragma suppress 106 /* unnamed, unused parameter */
+ #include <clib.h>
+#endif
+
+/*
+ * Large file (>2Gb) support using WIN32 functions.
+ */
+
+#ifdef USE_WIN32_LARGE_FILES
+# include <io.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# undef lseek
+# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence)
+# undef fstat
+# define fstat(fdes,stp) _fstati64(fdes, stp)
+# undef stat
+# define stat(fname,stp) _stati64(fname, stp)
+# define struct_stat struct _stati64
+# define LSEEK_ERROR (__int64)-1
+#endif
+
+/*
+ * Small file (<2Gb) support using WIN32 functions.
+ */
+
+#ifdef USE_WIN32_SMALL_FILES
+# include <io.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# ifndef _WIN32_WCE
+# undef lseek
+# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence)
+# define fstat(fdes,stp) _fstat(fdes, stp)
+# define stat(fname,stp) _stat(fname, stp)
+# define struct_stat struct _stat
+# endif
+# define LSEEK_ERROR (long)-1
+#endif
+
+#ifndef struct_stat
+# define struct_stat struct stat
+#endif
+
+#ifndef LSEEK_ERROR
+# define LSEEK_ERROR (off_t)-1
+#endif
+
+/*
+ * Default sizeof(off_t) in case it hasn't been defined in config file.
+ */
+
+#ifndef SIZEOF_OFF_T
+# if defined(__VMS) && !defined(__VAX)
+# if defined(_LARGEFILE)
+# define SIZEOF_OFF_T 8
+# endif
+# elif defined(__OS400__) && defined(__ILEC400__)
+# if defined(_LARGE_FILES)
+# define SIZEOF_OFF_T 8
+# endif
+# elif defined(__MVS__) && defined(__IBMC__)
+# if defined(_LP64) || defined(_LARGE_FILES)
+# define SIZEOF_OFF_T 8
+# endif
+# elif defined(__370__) && defined(__IBMC__)
+# if defined(_LP64) || defined(_LARGE_FILES)
+# define SIZEOF_OFF_T 8
+# endif
+# endif
+# ifndef SIZEOF_OFF_T
+# define SIZEOF_OFF_T 4
+# endif
+#endif
+
+/*
+ * Arg 2 type for gethostname in case it hasn't been defined in config file.
+ */
+
+#ifndef GETHOSTNAME_TYPE_ARG2
+# ifdef USE_WINSOCK
+# define GETHOSTNAME_TYPE_ARG2 int
+# else
+# define GETHOSTNAME_TYPE_ARG2 size_t
+# endif
+#endif
+
+/* Below we define some functions. They should
+
+ 4. set the SIGALRM signal timeout
+ 5. set dir/file naming defines
+ */
+
+#ifdef WIN32
+
+# define DIR_CHAR "\\"
+# define DOT_CHAR "_"
+
+#else /* WIN32 */
+
+# ifdef MSDOS /* Watt-32 */
+
+# include <sys/ioctl.h>
+# define select(n,r,w,x,t) select_s(n,r,w,x,t)
+# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z))
+# include <tcp.h>
+# ifdef word
+# undef word
+# endif
+# ifdef byte
+# undef byte
+# endif
+
+# endif /* MSDOS */
+
+# ifdef __minix
+ /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */
+ extern char * strtok_r(char *s, const char *delim, char **last);
+ extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp);
+# endif
+
+# define DIR_CHAR "/"
+# ifndef DOT_CHAR
+# define DOT_CHAR "."
+# endif
+
+# ifdef MSDOS
+# undef DOT_CHAR
+# define DOT_CHAR "_"
+# endif
+
+# ifndef fileno /* sunos 4 have this as a macro! */
+ int fileno( FILE *stream);
+# endif
+
+#endif /* WIN32 */
+
+/*
+ * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
+ * defined in ws2tcpip.h as well as to provide IPv6 support.
+ */
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# if !defined(HAVE_WS2TCPIP_H) || \
+ ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
+# undef HAVE_GETADDRINFO_THREADSAFE
+# undef HAVE_FREEADDRINFO
+# undef HAVE_GETADDRINFO
+# undef HAVE_GETNAMEINFO
+# undef ENABLE_IPV6
+# endif
+#endif
+
+/* ---------------------------------------------------------------- */
+/* resolver specialty compile-time defines */
+/* CURLRES_* defines to use in the host*.c sources */
+/* ---------------------------------------------------------------- */
+
+/*
+ * lcc-win32 doesn't have _beginthreadex(), lacks threads support.
+ */
+
+#if defined(__LCC__) && defined(WIN32)
+# undef USE_THREADS_POSIX
+# undef USE_THREADS_WIN32
+#endif
+
+/*
+ * MSVC threads support requires a multi-threaded runtime library.
+ * _beginthreadex() is not available in single-threaded ones.
+ */
+
+#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
+# undef USE_THREADS_POSIX
+# undef USE_THREADS_WIN32
+#endif
+
+/*
+ * Mutually exclusive CURLRES_* definitions.
+ */
+
+#ifdef USE_ARES
+# define CURLRES_ASYNCH
+# define CURLRES_ARES
+/* now undef the stock libc functions just to avoid them being used */
+# undef HAVE_GETADDRINFO
+# undef HAVE_GETHOSTBYNAME
+#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+# define CURLRES_ASYNCH
+# define CURLRES_THREADED
+#else
+# define CURLRES_SYNCH
+#endif
+
+#ifdef ENABLE_IPV6
+# define CURLRES_IPV6
+#else
+# define CURLRES_IPV4
+#endif
+
+/* ---------------------------------------------------------------- */
+
+/*
+ * When using WINSOCK, TELNET protocol requires WINSOCK2 API.
+ */
+
+#if defined(USE_WINSOCK) && (USE_WINSOCK != 2)
+# define CURL_DISABLE_TELNET 1
+#endif
+
+/*
+ * msvc 6.0 does not have struct sockaddr_storage and
+ * does not define IPPROTO_ESP in winsock2.h. But both
+ * are available if PSDK is properly installed.
+ */
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
+# undef HAVE_STRUCT_SOCKADDR_STORAGE
+# endif
+#endif
+
+/*
+ * Intentionally fail to build when using msvc 6.0 without PSDK installed.
+ * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK
+ * in lib/config-win32.h although absolutely discouraged and unsupported.
+ */
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
+# if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
+# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \
+ "Windows Server 2003 PSDK"
+# else
+# define CURL_DISABLE_LDAP 1
+# endif
+# endif
+#endif
+
+#ifdef NETWARE
+int netware_init(void);
+#ifndef __NOVELL_LIBC__
+#include <sys/bsdskt.h>
+#include <sys/timeval.h>
+#endif
+#endif
+
+#if defined(HAVE_LIBIDN) && defined(HAVE_TLD_H)
+/* The lib was present and the tld.h header (which is missing in libidn 0.3.X
+ but we only work with libidn 0.4.1 or later) */
+#define USE_LIBIDN
+#endif
+
+#ifndef SIZEOF_TIME_T
+/* assume default size of time_t to be 32 bit */
+#define SIZEOF_TIME_T 4
+#endif
+
+#define LIBIDN_REQUIRED_VERSION "0.4.1"
+
+#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || \
+ defined(USE_QSOSSL) || defined(USE_POLARSSL) || defined(USE_AXTLS) || \
+ defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
+ defined(USE_DARWINSSL) || defined(USE_GSKIT)
+#define USE_SSL /* SSL support has been enabled */
+#endif
+
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
+ (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
+#define USE_SPNEGO
+#endif
+
+/* Single point where USE_NTLM definition might be done */
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM) && \
+ !defined(CURL_DISABLE_CRYPTO_AUTH)
+#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || \
+ defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL)
+#define USE_NTLM
+#endif
+#endif
+
+/* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */
+#if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE)
+#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")
+#endif
+
+/*
+ * Provide a mechanism to silence picky compilers, such as gcc 4.6+.
+ * Parameters should of course normally not be unused, but for example when
+ * we have multiple implementations of the same interface it may happen.
+ */
+
+#if defined(__GNUC__) && ((__GNUC__ >= 3) || \
+ ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7)))
+# define UNUSED_PARAM __attribute__((__unused__))
+#else
+# define UNUSED_PARAM /*NOTHING*/
+#endif
+
+/*
+ * Include macros and defines that should only be processed once.
+ */
+
+#ifndef HEADER_CURL_SETUP_ONCE_H
+#include "curl_setup_once.h"
+#endif
+
+/*
+ * Definition of our NOP statement Object-like macro
+ */
+
+#ifndef Curl_nop_stmt
+# define Curl_nop_stmt do { } WHILE_FALSE
+#endif
+
+/*
+ * Ensure that Winsock and lwIP TCP/IP stacks are not mixed.
+ */
+
+#if defined(__LWIP_OPT_H__)
+# if defined(SOCKET) || \
+ defined(USE_WINSOCK) || \
+ defined(HAVE_WINSOCK_H) || \
+ defined(HAVE_WINSOCK2_H) || \
+ defined(HAVE_WS2TCPIP_H)
+# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!"
+# endif
+#endif
+
+/*
+ * Portable symbolic names for Winsock shutdown() mode flags.
+ */
+
+#ifdef USE_WINSOCK
+# define SHUT_RD 0x00
+# define SHUT_WR 0x01
+# define SHUT_RDWR 0x02
+#endif
+
+/* Define S_ISREG if not defined by system headers, f.e. MSVC */
+#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+/* Define S_ISDIR if not defined by system headers, f.e. MSVC */
+#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+#endif /* HEADER_CURL_SETUP_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_setup_once.h b/external/libcurl_android/jni/libcurl/lib/curl_setup_once.h
new file mode 100755
index 00000000..69d6d479
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_setup_once.h
@@ -0,0 +1,551 @@
+#ifndef HEADER_CURL_SETUP_ONCE_H
+#define HEADER_CURL_SETUP_ONCE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+
+/*
+ * Inclusion of common header files.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef NEED_MALLOC_H
+#include <malloc.h>
+#endif
+
+#ifdef NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#else
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#endif
+
+#ifdef WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T)
+#include <stdbool.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef __hpux
+# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
+# ifdef _APP32_64BIT_OFF_T
+# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T
+# undef _APP32_64BIT_OFF_T
+# else
+# undef OLD_APP32_64BIT_OFF_T
+# endif
+# endif
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef __hpux
+# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
+# ifdef OLD_APP32_64BIT_OFF_T
+# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T
+# undef OLD_APP32_64BIT_OFF_T
+# endif
+# endif
+#endif
+
+
+/*
+ * Definition of timeval struct for platforms that don't have it.
+ */
+
+#ifndef HAVE_STRUCT_TIMEVAL
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+#endif
+
+
+/*
+ * If we have the MSG_NOSIGNAL define, make sure we use
+ * it as the fourth argument of function send()
+ */
+
+#ifdef HAVE_MSG_NOSIGNAL
+#define SEND_4TH_ARG MSG_NOSIGNAL
+#else
+#define SEND_4TH_ARG 0
+#endif
+
+
+#if defined(__minix)
+/* Minix doesn't support recv on TCP sockets */
+#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \
+ (RECV_TYPE_ARG2)(y), \
+ (RECV_TYPE_ARG3)(z))
+
+#elif defined(HAVE_RECV)
+/*
+ * The definitions for the return type and arguments types
+ * of functions recv() and send() belong and come from the
+ * configuration file. Do not define them in any other place.
+ *
+ * HAVE_RECV is defined if you have a function named recv()
+ * which is used to read incoming data from sockets. If your
+ * function has another name then don't define HAVE_RECV.
+ *
+ * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2,
+ * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also
+ * be defined.
+ *
+ * HAVE_SEND is defined if you have a function named send()
+ * which is used to write outgoing data on a connected socket.
+ * If yours has another name then don't define HAVE_SEND.
+ *
+ * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2,
+ * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and
+ * SEND_TYPE_RETV must also be defined.
+ */
+
+#if !defined(RECV_TYPE_ARG1) || \
+ !defined(RECV_TYPE_ARG2) || \
+ !defined(RECV_TYPE_ARG3) || \
+ !defined(RECV_TYPE_ARG4) || \
+ !defined(RECV_TYPE_RETV)
+ /* */
+ Error Missing_definition_of_return_and_arguments_types_of_recv
+ /* */
+#else
+#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
+ (RECV_TYPE_ARG2)(y), \
+ (RECV_TYPE_ARG3)(z), \
+ (RECV_TYPE_ARG4)(0))
+#endif
+#else /* HAVE_RECV */
+#ifndef sread
+ /* */
+ Error Missing_definition_of_macro_sread
+ /* */
+#endif
+#endif /* HAVE_RECV */
+
+
+#if defined(__minix)
+/* Minix doesn't support send on TCP sockets */
+#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \
+ (SEND_TYPE_ARG2)(y), \
+ (SEND_TYPE_ARG3)(z))
+
+#elif defined(HAVE_SEND)
+#if !defined(SEND_TYPE_ARG1) || \
+ !defined(SEND_QUAL_ARG2) || \
+ !defined(SEND_TYPE_ARG2) || \
+ !defined(SEND_TYPE_ARG3) || \
+ !defined(SEND_TYPE_ARG4) || \
+ !defined(SEND_TYPE_RETV)
+ /* */
+ Error Missing_definition_of_return_and_arguments_types_of_send
+ /* */
+#else
+#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
+ (SEND_TYPE_ARG2)(y), \
+ (SEND_TYPE_ARG3)(z), \
+ (SEND_TYPE_ARG4)(SEND_4TH_ARG))
+#endif
+#else /* HAVE_SEND */
+#ifndef swrite
+ /* */
+ Error Missing_definition_of_macro_swrite
+ /* */
+#endif
+#endif /* HAVE_SEND */
+
+
+#if 0
+#if defined(HAVE_RECVFROM)
+/*
+ * Currently recvfrom is only used on udp sockets.
+ */
+#if !defined(RECVFROM_TYPE_ARG1) || \
+ !defined(RECVFROM_TYPE_ARG2) || \
+ !defined(RECVFROM_TYPE_ARG3) || \
+ !defined(RECVFROM_TYPE_ARG4) || \
+ !defined(RECVFROM_TYPE_ARG5) || \
+ !defined(RECVFROM_TYPE_ARG6) || \
+ !defined(RECVFROM_TYPE_RETV)
+ /* */
+ Error Missing_definition_of_return_and_arguments_types_of_recvfrom
+ /* */
+#else
+#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \
+ (RECVFROM_TYPE_ARG2 *)(b), \
+ (RECVFROM_TYPE_ARG3) (bl), \
+ (RECVFROM_TYPE_ARG4) (0), \
+ (RECVFROM_TYPE_ARG5 *)(f), \
+ (RECVFROM_TYPE_ARG6 *)(fl))
+#endif
+#else /* HAVE_RECVFROM */
+#ifndef sreadfrom
+ /* */
+ Error Missing_definition_of_macro_sreadfrom
+ /* */
+#endif
+#endif /* HAVE_RECVFROM */
+
+
+#ifdef RECVFROM_TYPE_ARG6_IS_VOID
+# define RECVFROM_ARG6_T int
+#else
+# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6
+#endif
+#endif /* if 0 */
+
+
+/*
+ * Function-like macro definition used to close a socket.
+ */
+
+#if defined(HAVE_CLOSESOCKET)
+# define sclose(x) closesocket((x))
+#elif defined(HAVE_CLOSESOCKET_CAMEL)
+# define sclose(x) CloseSocket((x))
+#elif defined(HAVE_CLOSE_S)
+# define sclose(x) close_s((x))
+#elif defined(USE_LWIPSOCK)
+# define sclose(x) lwip_close((x))
+#else
+# define sclose(x) close((x))
+#endif
+
+/*
+ * Stack-independent version of fcntl() on sockets:
+ */
+#if defined(USE_LWIPSOCK)
+# define sfcntl lwip_fcntl
+#else
+# define sfcntl fcntl
+#endif
+
+/*
+ * Uppercase macro versions of ANSI/ISO is*() functions/macros which
+ * avoid negative number inputs with argument byte codes > 127.
+ */
+
+#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
+#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
+#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
+#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
+#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
+#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
+#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
+#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
+#define ISLOWER(x) (islower((int) ((unsigned char)x)))
+#define ISASCII(x) (isascii((int) ((unsigned char)x)))
+
+#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
+ (((unsigned char)x) == '\t'))
+
+#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
+
+
+/*
+ * 'bool' stuff compatible with HP-UX headers.
+ */
+
+#if defined(__hpux) && !defined(HAVE_BOOL_T)
+ typedef int bool;
+# define false 0
+# define true 1
+# define HAVE_BOOL_T
+#endif
+
+
+/*
+ * 'bool' exists on platforms with <stdbool.h>, i.e. C99 platforms.
+ * On non-C99 platforms there's no bool, so define an enum for that.
+ * On C99 platforms 'false' and 'true' also exist. Enum uses a
+ * global namespace though, so use bool_false and bool_true.
+ */
+
+#ifndef HAVE_BOOL_T
+ typedef enum {
+ bool_false = 0,
+ bool_true = 1
+ } bool;
+
+/*
+ * Use a define to let 'true' and 'false' use those enums. There
+ * are currently no use of true and false in libcurl proper, but
+ * there are some in the examples. This will cater for any later
+ * code happening to use true and false.
+ */
+# define false bool_false
+# define true bool_true
+# define HAVE_BOOL_T
+#endif
+
+
+/*
+ * Redefine TRUE and FALSE too, to catch current use. With this
+ * change, 'bool found = 1' will give a warning on MIPSPro, but
+ * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro,
+ * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too.
+ */
+
+#ifndef TRUE
+#define TRUE true
+#endif
+#ifndef FALSE
+#define FALSE false
+#endif
+
+
+/*
+ * Macro WHILE_FALSE may be used to build single-iteration do-while loops,
+ * avoiding compiler warnings. Mostly intended for other macro definitions.
+ */
+
+#define WHILE_FALSE while(0)
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# undef WHILE_FALSE
+# if (_MSC_VER < 1500)
+# define WHILE_FALSE while(1, 0)
+# else
+# define WHILE_FALSE \
+__pragma(warning(push)) \
+__pragma(warning(disable:4127)) \
+while(0) \
+__pragma(warning(pop))
+# endif
+#endif
+
+
+/*
+ * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
+ */
+
+#ifndef HAVE_SIG_ATOMIC_T
+typedef int sig_atomic_t;
+#define HAVE_SIG_ATOMIC_T
+#endif
+
+
+/*
+ * Convenience SIG_ATOMIC_T definition
+ */
+
+#ifdef HAVE_SIG_ATOMIC_T_VOLATILE
+#define SIG_ATOMIC_T static sig_atomic_t
+#else
+#define SIG_ATOMIC_T static volatile sig_atomic_t
+#endif
+
+
+/*
+ * Default return type for signal handlers.
+ */
+
+#ifndef RETSIGTYPE
+#define RETSIGTYPE void
+#endif
+
+
+/*
+ * Macro used to include code only in debug builds.
+ */
+
+#ifdef DEBUGBUILD
+#define DEBUGF(x) x
+#else
+#define DEBUGF(x) do { } WHILE_FALSE
+#endif
+
+
+/*
+ * Macro used to include assertion code only in debug builds.
+ */
+
+#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H)
+#define DEBUGASSERT(x) assert(x)
+#else
+#define DEBUGASSERT(x) do { } WHILE_FALSE
+#endif
+
+
+/*
+ * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno
+ * (or equivalent) on this platform to hide platform details to code using it.
+ */
+
+#ifdef USE_WINSOCK
+#define SOCKERRNO ((int)WSAGetLastError())
+#define SET_SOCKERRNO(x) (WSASetLastError((int)(x)))
+#else
+#define SOCKERRNO (errno)
+#define SET_SOCKERRNO(x) (errno = (x))
+#endif
+
+
+/*
+ * Macro ERRNO / SET_ERRNO() returns / sets the NOT *socket-related* errno
+ * (or equivalent) on this platform to hide platform details to code using it.
+ */
+
+#if defined(WIN32) && !defined(USE_LWIPSOCK)
+#define ERRNO ((int)GetLastError())
+#define SET_ERRNO(x) (SetLastError((DWORD)(x)))
+#else
+#define ERRNO (errno)
+#define SET_ERRNO(x) (errno = (x))
+#endif
+
+
+/*
+ * Portable error number symbolic names defined to Winsock error codes.
+ */
+
+#ifdef USE_WINSOCK
+#undef EBADF /* override definition in errno.h */
+#define EBADF WSAEBADF
+#undef EINTR /* override definition in errno.h */
+#define EINTR WSAEINTR
+#undef EINVAL /* override definition in errno.h */
+#define EINVAL WSAEINVAL
+#undef EWOULDBLOCK /* override definition in errno.h */
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef EINPROGRESS /* override definition in errno.h */
+#define EINPROGRESS WSAEINPROGRESS
+#undef EALREADY /* override definition in errno.h */
+#define EALREADY WSAEALREADY
+#undef ENOTSOCK /* override definition in errno.h */
+#define ENOTSOCK WSAENOTSOCK
+#undef EDESTADDRREQ /* override definition in errno.h */
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#undef EMSGSIZE /* override definition in errno.h */
+#define EMSGSIZE WSAEMSGSIZE
+#undef EPROTOTYPE /* override definition in errno.h */
+#define EPROTOTYPE WSAEPROTOTYPE
+#undef ENOPROTOOPT /* override definition in errno.h */
+#define ENOPROTOOPT WSAENOPROTOOPT
+#undef EPROTONOSUPPORT /* override definition in errno.h */
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#undef EOPNOTSUPP /* override definition in errno.h */
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#undef EAFNOSUPPORT /* override definition in errno.h */
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#undef EADDRINUSE /* override definition in errno.h */
+#define EADDRINUSE WSAEADDRINUSE
+#undef EADDRNOTAVAIL /* override definition in errno.h */
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#undef ENETDOWN /* override definition in errno.h */
+#define ENETDOWN WSAENETDOWN
+#undef ENETUNREACH /* override definition in errno.h */
+#define ENETUNREACH WSAENETUNREACH
+#undef ENETRESET /* override definition in errno.h */
+#define ENETRESET WSAENETRESET
+#undef ECONNABORTED /* override definition in errno.h */
+#define ECONNABORTED WSAECONNABORTED
+#undef ECONNRESET /* override definition in errno.h */
+#define ECONNRESET WSAECONNRESET
+#undef ENOBUFS /* override definition in errno.h */
+#define ENOBUFS WSAENOBUFS
+#undef EISCONN /* override definition in errno.h */
+#define EISCONN WSAEISCONN
+#undef ENOTCONN /* override definition in errno.h */
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#undef ETIMEDOUT /* override definition in errno.h */
+#define ETIMEDOUT WSAETIMEDOUT
+#undef ECONNREFUSED /* override definition in errno.h */
+#define ECONNREFUSED WSAECONNREFUSED
+#undef ELOOP /* override definition in errno.h */
+#define ELOOP WSAELOOP
+#ifndef ENAMETOOLONG /* possible previous definition in errno.h */
+#define ENAMETOOLONG WSAENAMETOOLONG
+#endif
+#define EHOSTDOWN WSAEHOSTDOWN
+#undef EHOSTUNREACH /* override definition in errno.h */
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#ifndef ENOTEMPTY /* possible previous definition in errno.h */
+#define ENOTEMPTY WSAENOTEMPTY
+#endif
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+#endif
+
+/*
+ * Macro argv_item_t hides platform details to code using it.
+ */
+
+#ifdef __VMS
+#define argv_item_t __char_ptr32
+#else
+#define argv_item_t char *
+#endif
+
+
+/*
+ * We use this ZERO_NULL to avoid picky compiler warnings,
+ * when assigning a NULL pointer to a function pointer var.
+ */
+
+#define ZERO_NULL 0
+
+
+#endif /* HEADER_CURL_SETUP_ONCE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_sspi.c b/external/libcurl_android/jni/libcurl/lib/curl_sspi.c
new file mode 100755
index 00000000..f09d2882
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_sspi.c
@@ -0,0 +1,257 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_WINDOWS_SSPI
+
+#include <curl/curl.h>
+
+#include "curl_sspi.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* We use our own typedef here since some headers might lack these */
+typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID);
+
+/* See definition of SECURITY_ENTRYPOINT in sspi.h */
+#ifdef UNICODE
+# ifdef _WIN32_WCE
+# define SECURITYENTRYPOINT L"InitSecurityInterfaceW"
+# else
+# define SECURITYENTRYPOINT "InitSecurityInterfaceW"
+# endif
+#else
+# define SECURITYENTRYPOINT "InitSecurityInterfaceA"
+#endif
+
+/* Handle of security.dll or secur32.dll, depending on Windows version */
+HMODULE s_hSecDll = NULL;
+
+/* Pointer to SSPI dispatch table */
+PSecurityFunctionTable s_pSecFn = NULL;
+
+/*
+ * Curl_sspi_global_init()
+ *
+ * This is used to load the Security Service Provider Interface (SSPI)
+ * dynamic link library portably across all Windows versions, without
+ * the need to directly link libcurl, nor the application using it, at
+ * build time.
+ *
+ * Once this function has been executed, Windows SSPI functions can be
+ * called through the Security Service Provider Interface dispatch table.
+ */
+CURLcode Curl_sspi_global_init(void)
+{
+ bool securityDll = FALSE;
+ INITSECURITYINTERFACE_FN pInitSecurityInterface;
+
+ /* If security interface is not yet initialized try to do this */
+ if(!s_hSecDll) {
+ /* Security Service Provider Interface (SSPI) functions are located in
+ * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
+ * have both these DLLs (security.dll forwards calls to secur32.dll) */
+ DWORD majorVersion = 4;
+ DWORD platformId = VER_PLATFORM_WIN32_NT;
+
+#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
+ (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
+ OSVERSIONINFO osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+
+ /* Find out Windows version */
+ if(!GetVersionEx(&osver))
+ return CURLE_FAILED_INIT;
+
+ /* Verify the major version number == 4 and platform id == WIN_NT */
+ if(osver.dwMajorVersion == majorVersion &&
+ osver.dwPlatformId == platformId)
+ securityDll = TRUE;
+#else
+ ULONGLONG majorVersionMask;
+ ULONGLONG platformIdMask;
+ OSVERSIONINFOEX osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ osver.dwMajorVersion = majorVersion;
+ osver.dwPlatformId = platformId;
+ majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
+ platformIdMask = VerSetConditionMask(0, VER_PLATFORMID, VER_EQUAL);
+
+ /* Verify the major version number == 4 and platform id == WIN_NT */
+ if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask) &&
+ VerifyVersionInfo(&osver, VER_PLATFORMID, platformIdMask))
+ securityDll = TRUE;
+#endif
+
+ /* Load SSPI dll into the address space of the calling process */
+ if(securityDll)
+ s_hSecDll = LoadLibrary(TEXT("security.dll"));
+ else
+ s_hSecDll = LoadLibrary(TEXT("secur32.dll"));
+ if(!s_hSecDll)
+ return CURLE_FAILED_INIT;
+
+ /* Get address of the InitSecurityInterfaceA function from the SSPI dll */
+ pInitSecurityInterface = (INITSECURITYINTERFACE_FN)
+ GetProcAddress(s_hSecDll, SECURITYENTRYPOINT);
+ if(!pInitSecurityInterface)
+ return CURLE_FAILED_INIT;
+
+ /* Get pointer to Security Service Provider Interface dispatch table */
+ s_pSecFn = pInitSecurityInterface();
+ if(!s_pSecFn)
+ return CURLE_FAILED_INIT;
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_sspi_global_cleanup()
+ *
+ * This deinitializes the Security Service Provider Interface from libcurl.
+ */
+
+void Curl_sspi_global_cleanup(void)
+{
+ if(s_hSecDll) {
+ FreeLibrary(s_hSecDll);
+ s_hSecDll = NULL;
+ s_pSecFn = NULL;
+ }
+}
+
+/*
+ * Curl_create_sspi_identity()
+ *
+ * This is used to populate a SSPI identity structure based on the supplied
+ * username and password.
+ *
+ * Parameters:
+ *
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * identity [in/out] - The identity structure.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
+ SEC_WINNT_AUTH_IDENTITY *identity)
+{
+ xcharp_u useranddomain;
+ xcharp_u user, dup_user;
+ xcharp_u domain, dup_domain;
+ xcharp_u passwd, dup_passwd;
+ size_t domlen = 0;
+
+ domain.const_tchar_ptr = TEXT("");
+
+ /* Initialize the identity */
+ memset(identity, 0, sizeof(*identity));
+
+ useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp);
+ if(!useranddomain.tchar_ptr)
+ return CURLE_OUT_OF_MEMORY;
+
+ user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\'));
+ if(!user.const_tchar_ptr)
+ user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/'));
+
+ if(user.tchar_ptr) {
+ domain.tchar_ptr = useranddomain.tchar_ptr;
+ domlen = user.tchar_ptr - useranddomain.tchar_ptr;
+ user.tchar_ptr++;
+ }
+ else {
+ user.tchar_ptr = useranddomain.tchar_ptr;
+ domain.const_tchar_ptr = TEXT("");
+ domlen = 0;
+ }
+
+ /* Setup the identity's user and length */
+ dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
+ if(!dup_user.tchar_ptr) {
+ Curl_unicodefree(useranddomain.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ identity->User = dup_user.tbyte_ptr;
+ identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr));
+ dup_user.tchar_ptr = NULL;
+
+ /* Setup the identity's domain and length */
+ dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
+ if(!dup_domain.tchar_ptr) {
+ Curl_unicodefree(useranddomain.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
+ *(dup_domain.tchar_ptr + domlen) = TEXT('\0');
+ identity->Domain = dup_domain.tbyte_ptr;
+ identity->DomainLength = curlx_uztoul(domlen);
+ dup_domain.tchar_ptr = NULL;
+
+ Curl_unicodefree(useranddomain.tchar_ptr);
+
+ /* Setup ntlm identity's password and length */
+ passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp);
+ if(!passwd.tchar_ptr)
+ return CURLE_OUT_OF_MEMORY;
+ dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
+ if(!dup_passwd.tchar_ptr) {
+ Curl_unicodefree(passwd.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ identity->Password = dup_passwd.tbyte_ptr;
+ identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
+ dup_passwd.tchar_ptr = NULL;
+
+ Curl_unicodefree(passwd.tchar_ptr);
+
+ /* Setup the identity's flags */
+ identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;
+
+ return CURLE_OK;
+}
+
+void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity)
+{
+ if(identity) {
+ Curl_safefree(identity->User);
+ Curl_safefree(identity->Password);
+ Curl_safefree(identity->Domain);
+ }
+}
+
+#endif /* USE_WINDOWS_SSPI */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_sspi.h b/external/libcurl_android/jni/libcurl/lib/curl_sspi.h
new file mode 100755
index 00000000..5ab17d5f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_sspi.h
@@ -0,0 +1,315 @@
+#ifndef HEADER_CURL_SSPI_H
+#define HEADER_CURL_SSPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_WINDOWS_SSPI
+
+#include <curl/curl.h>
+
+/*
+ * When including the following three headers, it is mandatory to define either
+ * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code.
+ */
+
+#undef SECURITY_WIN32
+#undef SECURITY_KERNEL
+#define SECURITY_WIN32 1
+#include <security.h>
+#include <sspi.h>
+#include <rpc.h>
+
+CURLcode Curl_sspi_global_init(void);
+void Curl_sspi_global_cleanup(void);
+
+/* This is used to generate an SSPI identity structure */
+CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
+ SEC_WINNT_AUTH_IDENTITY *identity);
+
+/* This is used to free an SSPI identity structure */
+void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity);
+
+/* Forward-declaration of global variables defined in curl_sspi.c */
+
+extern HMODULE s_hSecDll;
+extern PSecurityFunctionTable s_pSecFn;
+
+/* Provide some definitions missing in old headers */
+
+#ifndef SEC_E_INSUFFICIENT_MEMORY
+# define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L)
+#endif
+#ifndef SEC_E_INVALID_HANDLE
+# define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L)
+#endif
+#ifndef SEC_E_UNSUPPORTED_FUNCTION
+# define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L)
+#endif
+#ifndef SEC_E_TARGET_UNKNOWN
+# define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L)
+#endif
+#ifndef SEC_E_INTERNAL_ERROR
+# define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L)
+#endif
+#ifndef SEC_E_SECPKG_NOT_FOUND
+# define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L)
+#endif
+#ifndef SEC_E_NOT_OWNER
+# define SEC_E_NOT_OWNER ((HRESULT)0x80090306L)
+#endif
+#ifndef SEC_E_CANNOT_INSTALL
+# define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L)
+#endif
+#ifndef SEC_E_INVALID_TOKEN
+# define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L)
+#endif
+#ifndef SEC_E_CANNOT_PACK
+# define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L)
+#endif
+#ifndef SEC_E_QOP_NOT_SUPPORTED
+# define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL)
+#endif
+#ifndef SEC_E_NO_IMPERSONATION
+# define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL)
+#endif
+#ifndef SEC_E_LOGON_DENIED
+# define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL)
+#endif
+#ifndef SEC_E_UNKNOWN_CREDENTIALS
+# define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL)
+#endif
+#ifndef SEC_E_NO_CREDENTIALS
+# define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL)
+#endif
+#ifndef SEC_E_MESSAGE_ALTERED
+# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL)
+#endif
+#ifndef SEC_E_OUT_OF_SEQUENCE
+# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L)
+#endif
+#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY
+# define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L)
+#endif
+#ifndef SEC_E_BAD_PKGID
+# define SEC_E_BAD_PKGID ((HRESULT)0x80090316L)
+#endif
+#ifndef SEC_E_CONTEXT_EXPIRED
+# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L)
+#endif
+#ifndef SEC_E_INCOMPLETE_MESSAGE
+# define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L)
+#endif
+#ifndef SEC_E_INCOMPLETE_CREDENTIALS
+# define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L)
+#endif
+#ifndef SEC_E_BUFFER_TOO_SMALL
+# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L)
+#endif
+#ifndef SEC_E_WRONG_PRINCIPAL
+# define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L)
+#endif
+#ifndef SEC_E_TIME_SKEW
+# define SEC_E_TIME_SKEW ((HRESULT)0x80090324L)
+#endif
+#ifndef SEC_E_UNTRUSTED_ROOT
+# define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L)
+#endif
+#ifndef SEC_E_ILLEGAL_MESSAGE
+# define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L)
+#endif
+#ifndef SEC_E_CERT_UNKNOWN
+# define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L)
+#endif
+#ifndef SEC_E_CERT_EXPIRED
+# define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L)
+#endif
+#ifndef SEC_E_ENCRYPT_FAILURE
+# define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L)
+#endif
+#ifndef SEC_E_DECRYPT_FAILURE
+# define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L)
+#endif
+#ifndef SEC_E_ALGORITHM_MISMATCH
+# define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L)
+#endif
+#ifndef SEC_E_SECURITY_QOS_FAILED
+# define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L)
+#endif
+#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED
+# define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L)
+#endif
+#ifndef SEC_E_NO_TGT_REPLY
+# define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L)
+#endif
+#ifndef SEC_E_NO_IP_ADDRESSES
+# define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L)
+#endif
+#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE
+# define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L)
+#endif
+#ifndef SEC_E_CRYPTO_SYSTEM_INVALID
+# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L)
+#endif
+#ifndef SEC_E_MAX_REFERRALS_EXCEEDED
+# define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L)
+#endif
+#ifndef SEC_E_MUST_BE_KDC
+# define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L)
+#endif
+#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED
+# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL)
+#endif
+#ifndef SEC_E_TOO_MANY_PRINCIPALS
+# define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL)
+#endif
+#ifndef SEC_E_NO_PA_DATA
+# define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL)
+#endif
+#ifndef SEC_E_PKINIT_NAME_MISMATCH
+# define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL)
+#endif
+#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED
+# define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL)
+#endif
+#ifndef SEC_E_SHUTDOWN_IN_PROGRESS
+# define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL)
+#endif
+#ifndef SEC_E_KDC_INVALID_REQUEST
+# define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L)
+#endif
+#ifndef SEC_E_KDC_UNABLE_TO_REFER
+# define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L)
+#endif
+#ifndef SEC_E_KDC_UNKNOWN_ETYPE
+# define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L)
+#endif
+#ifndef SEC_E_UNSUPPORTED_PREAUTH
+# define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L)
+#endif
+#ifndef SEC_E_DELEGATION_REQUIRED
+# define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L)
+#endif
+#ifndef SEC_E_BAD_BINDINGS
+# define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L)
+#endif
+#ifndef SEC_E_MULTIPLE_ACCOUNTS
+# define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L)
+#endif
+#ifndef SEC_E_NO_KERB_KEY
+# define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L)
+#endif
+#ifndef SEC_E_CERT_WRONG_USAGE
+# define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L)
+#endif
+#ifndef SEC_E_DOWNGRADE_DETECTED
+# define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L)
+#endif
+#ifndef SEC_E_SMARTCARD_CERT_REVOKED
+# define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L)
+#endif
+#ifndef SEC_E_ISSUING_CA_UNTRUSTED
+# define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L)
+#endif
+#ifndef SEC_E_REVOCATION_OFFLINE_C
+# define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L)
+#endif
+#ifndef SEC_E_PKINIT_CLIENT_FAILURE
+# define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L)
+#endif
+#ifndef SEC_E_SMARTCARD_CERT_EXPIRED
+# define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L)
+#endif
+#ifndef SEC_E_NO_S4U_PROT_SUPPORT
+# define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L)
+#endif
+#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE
+# define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L)
+#endif
+#ifndef SEC_E_REVOCATION_OFFLINE_KDC
+# define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L)
+#endif
+#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC
+# define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L)
+#endif
+#ifndef SEC_E_KDC_CERT_EXPIRED
+# define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL)
+#endif
+#ifndef SEC_E_KDC_CERT_REVOKED
+# define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL)
+#endif
+#ifndef SEC_E_INVALID_PARAMETER
+# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL)
+#endif
+#ifndef SEC_E_DELEGATION_POLICY
+# define SEC_E_DELEGATION_POLICY ((HRESULT)0x8009035EL)
+#endif
+#ifndef SEC_E_POLICY_NLTM_ONLY
+# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL)
+#endif
+
+#ifndef SEC_I_CONTINUE_NEEDED
+# define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L)
+#endif
+#ifndef SEC_I_COMPLETE_NEEDED
+# define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L)
+#endif
+#ifndef SEC_I_COMPLETE_AND_CONTINUE
+# define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L)
+#endif
+#ifndef SEC_I_LOCAL_LOGON
+# define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L)
+#endif
+#ifndef SEC_I_CONTEXT_EXPIRED
+# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L)
+#endif
+#ifndef SEC_I_INCOMPLETE_CREDENTIALS
+# define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L)
+#endif
+#ifndef SEC_I_RENEGOTIATE
+# define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L)
+#endif
+#ifndef SEC_I_NO_LSA_CONTEXT
+# define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L)
+#endif
+#ifndef SEC_I_SIGNATURE_NEEDED
+# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
+#endif
+
+#ifdef UNICODE
+# define SECFLAG_WINNT_AUTH_IDENTITY \
+ (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE
+#else
+# define SECFLAG_WINNT_AUTH_IDENTITY \
+ (unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI
+#endif
+
+/*
+ * Definitions required from ntsecapi.h are directly provided below this point
+ * to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h
+ */
+#define KERB_WRAP_NO_ENCRYPT 0x80000001
+
+#endif /* USE_WINDOWS_SSPI */
+
+#endif /* HEADER_CURL_SSPI_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_threads.c b/external/libcurl_android/jni/libcurl/lib/curl_threads.c
new file mode 100755
index 00000000..d40e024c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_threads.c
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_THREADS_POSIX)
+# ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+# endif
+#elif defined(USE_THREADS_WIN32)
+# ifdef HAVE_PROCESS_H
+# include <process.h>
+# endif
+#endif
+
+#include "curl_threads.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if defined(USE_THREADS_POSIX)
+
+struct curl_actual_call {
+ unsigned int (*func)(void *);
+ void *arg;
+};
+
+static void *curl_thread_create_thunk(void *arg)
+{
+ struct curl_actual_call * ac = arg;
+ unsigned int (*func)(void *) = ac->func;
+ void *real_arg = ac->arg;
+
+ free(ac);
+
+ (*func)(real_arg);
+
+ return 0;
+}
+
+curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
+{
+ curl_thread_t t = malloc(sizeof(pthread_t));
+ struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
+ if(!(ac && t))
+ goto err;
+
+ ac->func = func;
+ ac->arg = arg;
+
+ if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0)
+ goto err;
+
+ return t;
+
+err:
+ Curl_safefree(t);
+ Curl_safefree(ac);
+ return curl_thread_t_null;
+}
+
+void Curl_thread_destroy(curl_thread_t hnd)
+{
+ if(hnd != curl_thread_t_null) {
+ pthread_detach(*hnd);
+ free(hnd);
+ }
+}
+
+int Curl_thread_join(curl_thread_t *hnd)
+{
+ int ret = (pthread_join(**hnd, NULL) == 0);
+
+ free(*hnd);
+ *hnd = curl_thread_t_null;
+
+ return ret;
+}
+
+#elif defined(USE_THREADS_WIN32)
+
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+ void *arg)
+{
+#ifdef _WIN32_WCE
+ return CreateThread(NULL, 0, func, arg, 0, NULL);
+#else
+ curl_thread_t t;
+ t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
+ if((t == 0) || (t == (curl_thread_t)-1L))
+ return curl_thread_t_null;
+ return t;
+#endif
+}
+
+void Curl_thread_destroy(curl_thread_t hnd)
+{
+ CloseHandle(hnd);
+}
+
+int Curl_thread_join(curl_thread_t *hnd)
+{
+ int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
+
+ Curl_thread_destroy(*hnd);
+
+ *hnd = curl_thread_t_null;
+
+ return ret;
+}
+
+#endif /* USE_THREADS_* */
diff --git a/external/libcurl_android/jni/libcurl/lib/curl_threads.h b/external/libcurl_android/jni/libcurl/lib/curl_threads.h
new file mode 100755
index 00000000..6457cbb1
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curl_threads.h
@@ -0,0 +1,57 @@
+#ifndef HEADER_CURL_THREADS_H
+#define HEADER_CURL_THREADS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(USE_THREADS_POSIX)
+# define CURL_STDCALL
+# define curl_mutex_t pthread_mutex_t
+# define curl_thread_t pthread_t *
+# define curl_thread_t_null (pthread_t *)0
+# define Curl_mutex_init(m) pthread_mutex_init(m, NULL)
+# define Curl_mutex_acquire(m) pthread_mutex_lock(m)
+# define Curl_mutex_release(m) pthread_mutex_unlock(m)
+# define Curl_mutex_destroy(m) pthread_mutex_destroy(m)
+#elif defined(USE_THREADS_WIN32)
+# define CURL_STDCALL __stdcall
+# define curl_mutex_t CRITICAL_SECTION
+# define curl_thread_t HANDLE
+# define curl_thread_t_null (HANDLE)0
+# define Curl_mutex_init(m) InitializeCriticalSection(m)
+# define Curl_mutex_acquire(m) EnterCriticalSection(m)
+# define Curl_mutex_release(m) LeaveCriticalSection(m)
+# define Curl_mutex_destroy(m) DeleteCriticalSection(m)
+#endif
+
+#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+ void *arg);
+
+void Curl_thread_destroy(curl_thread_t hnd);
+
+int Curl_thread_join(curl_thread_t *hnd);
+
+#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
+
+#endif /* HEADER_CURL_THREADS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/curlx.h b/external/libcurl_android/jni/libcurl/lib/curlx.h
new file mode 100755
index 00000000..9dc90a00
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/curlx.h
@@ -0,0 +1,119 @@
+#ifndef HEADER_CURL_CURLX_H
+#define HEADER_CURL_CURLX_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Defines protos and includes all header files that provide the curlx_*
+ * functions. The curlx_* functions are not part of the libcurl API, but are
+ * stand-alone functions whose sources can be built and linked by apps if need
+ * be.
+ */
+
+#include <curl/mprintf.h>
+/* this is still a public header file that provides the curl_mprintf()
+ functions while they still are offered publicly. They will be made library-
+ private one day */
+
+#include "strequal.h"
+/* "strequal.h" provides the strequal protos */
+
+#include "strtoofft.h"
+/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a
+ curl_off_t number from a given string.
+*/
+
+#include "timeval.h"
+/*
+ "timeval.h" sets up a 'struct timeval' even for platforms that otherwise
+ don't have one and has protos for these functions:
+
+ curlx_tvnow()
+ curlx_tvdiff()
+ curlx_tvdiff_secs()
+*/
+
+#include "nonblock.h"
+/* "nonblock.h" provides curlx_nonblock() */
+
+#include "warnless.h"
+/* "warnless.h" provides functions:
+
+ curlx_ultous()
+ curlx_ultouc()
+ curlx_uztosi()
+*/
+
+/* Now setup curlx_ * names for the functions that are to become curlx_ and
+ be removed from a future libcurl official API:
+ curlx_getenv
+ curlx_mprintf (and its variations)
+ curlx_strequal
+ curlx_strnequal
+
+*/
+
+#define curlx_getenv curl_getenv
+#define curlx_strequal curl_strequal
+#define curlx_strnequal curl_strnequal
+#define curlx_raw_equal Curl_raw_equal
+#define curlx_mvsnprintf curl_mvsnprintf
+#define curlx_msnprintf curl_msnprintf
+#define curlx_maprintf curl_maprintf
+#define curlx_mvaprintf curl_mvaprintf
+#define curlx_msprintf curl_msprintf
+#define curlx_mprintf curl_mprintf
+#define curlx_mfprintf curl_mfprintf
+#define curlx_mvsprintf curl_mvsprintf
+#define curlx_mvprintf curl_mvprintf
+#define curlx_mvfprintf curl_mvfprintf
+
+#ifdef ENABLE_CURLX_PRINTF
+/* If this define is set, we define all "standard" printf() functions to use
+ the curlx_* version instead. It makes the source code transparent and
+ easier to understand/patch. Undefine them first in case _MPRINTF_REPLACE
+ is set. */
+# undef printf
+# undef fprintf
+# undef sprintf
+# undef snprintf
+# undef vprintf
+# undef vfprintf
+# undef vsprintf
+# undef vsnprintf
+# undef aprintf
+# undef vaprintf
+
+# define printf curlx_mprintf
+# define fprintf curlx_mfprintf
+# define sprintf curlx_msprintf
+# define snprintf curlx_msnprintf
+# define vprintf curlx_mvprintf
+# define vfprintf curlx_mvfprintf
+# define vsprintf curlx_mvsprintf
+# define vsnprintf curlx_mvsnprintf
+# define aprintf curlx_maprintf
+# define vaprintf curlx_mvaprintf
+#endif /* ENABLE_CURLX_PRINTF */
+
+#endif /* HEADER_CURL_CURLX_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/dict.c b/external/libcurl_android/jni/libcurl/lib/dict.c
new file mode 100755
index 00000000..86ddfb9e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/dict.c
@@ -0,0 +1,283 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_DICT
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+
+#include "progress.h"
+#include "strequal.h"
+#include "dict.h"
+#include "rawstr.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode dict_do(struct connectdata *conn, bool *done);
+
+/*
+ * DICT protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_dict = {
+ "DICT", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ dict_do, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_DICT, /* defport */
+ CURLPROTO_DICT, /* protocol */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
+};
+
+static char *unescape_word(struct SessionHandle *data, const char *inputbuff)
+{
+ char *newp;
+ char *dictp;
+ char *ptr;
+ int len;
+ char byte;
+ int olen=0;
+
+ newp = curl_easy_unescape(data, inputbuff, 0, &len);
+ if(!newp)
+ return NULL;
+
+ dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
+ if(dictp) {
+ /* According to RFC2229 section 2.2, these letters need to be escaped with
+ \[letter] */
+ for(ptr = newp;
+ (byte = *ptr) != 0;
+ ptr++) {
+ if((byte <= 32) || (byte == 127) ||
+ (byte == '\'') || (byte == '\"') || (byte == '\\')) {
+ dictp[olen++] = '\\';
+ }
+ dictp[olen++] = byte;
+ }
+ dictp[olen]=0;
+ }
+ free(newp);
+ return dictp;
+}
+
+static CURLcode dict_do(struct connectdata *conn, bool *done)
+{
+ char *word;
+ char *eword;
+ char *ppath;
+ char *database = NULL;
+ char *strategy = NULL;
+ char *nthdef = NULL; /* This is not part of the protocol, but required
+ by RFC 2229 */
+ CURLcode result=CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+
+ char *path = data->state.path;
+ curl_off_t *bytecount = &data->req.bytecount;
+
+ *done = TRUE; /* unconditionally */
+
+ if(conn->bits.user_passwd) {
+ /* AUTH is missing */
+ }
+
+ if(Curl_raw_nequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
+ Curl_raw_nequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
+ Curl_raw_nequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
+
+ word = strchr(path, ':');
+ if(word) {
+ word++;
+ database = strchr(word, ':');
+ if(database) {
+ *database++ = (char)0;
+ strategy = strchr(database, ':');
+ if(strategy) {
+ *strategy++ = (char)0;
+ nthdef = strchr(strategy, ':');
+ if(nthdef) {
+ *nthdef = (char)0;
+ }
+ }
+ }
+ }
+
+ if((word == NULL) || (*word == (char)0)) {
+ infof(data, "lookup word is missing\n");
+ word=(char *)"default";
+ }
+ if((database == NULL) || (*database == (char)0)) {
+ database = (char *)"!";
+ }
+ if((strategy == NULL) || (*strategy == (char)0)) {
+ strategy = (char *)".";
+ }
+
+ eword = unescape_word(data, word);
+ if(!eword)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_sendf(sockfd, conn,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "MATCH "
+ "%s " /* database */
+ "%s " /* strategy */
+ "%s\r\n" /* word */
+ "QUIT\r\n",
+
+ database,
+ strategy,
+ eword
+ );
+
+ free(eword);
+
+ if(result) {
+ failf(data, "Failed sending DICT request");
+ return result;
+ }
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
+ -1, NULL); /* no upload */
+ }
+ else if(Curl_raw_nequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
+ Curl_raw_nequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
+ Curl_raw_nequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
+
+ word = strchr(path, ':');
+ if(word) {
+ word++;
+ database = strchr(word, ':');
+ if(database) {
+ *database++ = (char)0;
+ nthdef = strchr(database, ':');
+ if(nthdef) {
+ *nthdef = (char)0;
+ }
+ }
+ }
+
+ if((word == NULL) || (*word == (char)0)) {
+ infof(data, "lookup word is missing\n");
+ word=(char *)"default";
+ }
+ if((database == NULL) || (*database == (char)0)) {
+ database = (char *)"!";
+ }
+
+ eword = unescape_word(data, word);
+ if(!eword)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_sendf(sockfd, conn,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "DEFINE "
+ "%s " /* database */
+ "%s\r\n" /* word */
+ "QUIT\r\n",
+ database,
+ eword);
+
+ free(eword);
+
+ if(result) {
+ failf(data, "Failed sending DICT request");
+ return result;
+ }
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
+ -1, NULL); /* no upload */
+ }
+ else {
+
+ ppath = strchr(path, '/');
+ if(ppath) {
+ int i;
+
+ ppath++;
+ for(i = 0; ppath[i]; i++) {
+ if(ppath[i] == ':')
+ ppath[i] = ' ';
+ }
+ result = Curl_sendf(sockfd, conn,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "%s\r\n"
+ "QUIT\r\n", ppath);
+ if(result) {
+ failf(data, "Failed sending DICT request");
+ return result;
+ }
+
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL);
+ }
+ }
+
+ return CURLE_OK;
+}
+#endif /*CURL_DISABLE_DICT*/
diff --git a/external/libcurl_android/jni/libcurl/lib/dict.h b/external/libcurl_android/jni/libcurl/lib/dict.h
new file mode 100755
index 00000000..44fd9d49
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/dict.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_DICT_H
+#define HEADER_CURL_DICT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef CURL_DISABLE_DICT
+extern const struct Curl_handler Curl_handler_dict;
+#endif
+
+#endif /* HEADER_CURL_DICT_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/dotdot.c b/external/libcurl_android/jni/libcurl/lib/dotdot.c
new file mode 100755
index 00000000..ae169411
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/dotdot.c
@@ -0,0 +1,170 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "dotdot.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * "Remove Dot Segments"
+ * http://tools.ietf.org/html/rfc3986#section-5.2.4
+ */
+
+/*
+ * Curl_dedotdotify()
+ *
+ * This function gets a zero-terminated path with dot and dotdot sequences
+ * passed in and strips them off according to the rules in RFC 3986 section
+ * 5.2.4.
+ *
+ * The function handles a query part ('?' + stuff) appended but it expects
+ * that fragments ('#' + stuff) have already been cut off.
+ *
+ * RETURNS
+ *
+ * an allocated dedotdotified output string
+ */
+char *Curl_dedotdotify(const char *input)
+{
+ size_t inlen = strlen(input);
+ char *clone;
+ size_t clen = inlen; /* the length of the cloned input */
+ char *out = malloc(inlen+1);
+ char *outptr;
+ char *orgclone;
+ char *queryp;
+ if(!out)
+ return NULL; /* out of memory */
+
+ /* get a cloned copy of the input */
+ clone = strdup(input);
+ if(!clone) {
+ free(out);
+ return NULL;
+ }
+ orgclone = clone;
+ outptr = out;
+
+ /*
+ * To handle query-parts properly, we must find it and remove it during the
+ * dotdot-operation and then append it again at the end to the output
+ * string.
+ */
+ queryp = strchr(clone, '?');
+ if(queryp)
+ *queryp = 0;
+
+ do {
+
+ /* A. If the input buffer begins with a prefix of "../" or "./", then
+ remove that prefix from the input buffer; otherwise, */
+
+ if(!strncmp("./", clone, 2)) {
+ clone+=2;
+ clen-=2;
+ }
+ else if(!strncmp("../", clone, 3)) {
+ clone+=3;
+ clen-=3;
+ }
+
+ /* B. if the input buffer begins with a prefix of "/./" or "/.", where
+ "." is a complete path segment, then replace that prefix with "/" in
+ the input buffer; otherwise, */
+ else if(!strncmp("/./", clone, 3)) {
+ clone+=2;
+ clen-=2;
+ }
+ else if(!strcmp("/.", clone)) {
+ clone[1]='/';
+ clone++;
+ clen-=1;
+ }
+
+ /* C. if the input buffer begins with a prefix of "/../" or "/..", where
+ ".." is a complete path segment, then replace that prefix with "/" in
+ the input buffer and remove the last segment and its preceding "/" (if
+ any) from the output buffer; otherwise, */
+
+ else if(!strncmp("/../", clone, 4)) {
+ clone+=3;
+ clen-=3;
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr = 0; /* zero-terminate where it stops */
+ }
+ else if(!strcmp("/..", clone)) {
+ clone[2]='/';
+ clone+=2;
+ clen-=2;
+ /* remove the last segment from the output buffer */
+ while(outptr > out) {
+ outptr--;
+ if(*outptr == '/')
+ break;
+ }
+ *outptr = 0; /* zero-terminate where it stops */
+ }
+
+ /* D. if the input buffer consists only of "." or "..", then remove
+ that from the input buffer; otherwise, */
+
+ else if(!strcmp(".", clone) || !strcmp("..", clone)) {
+ *clone=0;
+ }
+
+ else {
+ /* E. move the first path segment in the input buffer to the end of
+ the output buffer, including the initial "/" character (if any) and
+ any subsequent characters up to, but not including, the next "/"
+ character or the end of the input buffer. */
+
+ do {
+ *outptr++ = *clone++;
+ clen--;
+ } while(*clone && (*clone != '/'));
+ *outptr = 0;
+ }
+
+ } while(*clone);
+
+ if(queryp) {
+ size_t qlen;
+ /* There was a query part, append that to the output. The 'clone' string
+ may now have been altered so we copy from the original input string
+ from the correct index. */
+ size_t oindex = queryp - orgclone;
+ qlen = strlen(&input[oindex]);
+ memcpy(outptr, &input[oindex], qlen+1); /* include the ending zero byte */
+ }
+
+ free(orgclone);
+ return out;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/dotdot.h b/external/libcurl_android/jni/libcurl/lib/dotdot.h
new file mode 100755
index 00000000..cd57822b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/dotdot.h
@@ -0,0 +1,25 @@
+#ifndef HEADER_CURL_DOTDOT_H
+#define HEADER_CURL_DOTDOT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+char *Curl_dedotdotify(const char *input);
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/easy.c b/external/libcurl_android/jni/libcurl/lib/easy.c
new file mode 100755
index 00000000..160712e8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/easy.c
@@ -0,0 +1,1182 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/*
+ * See comment in curl_memory.h for the explanation of this sanity check.
+ */
+
+#ifdef CURLX_NO_MEMORY_CALLBACKS
+#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined"
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "strequal.h"
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "vtls/vtls.h"
+#include "url.h"
+#include "getinfo.h"
+#include "hostip.h"
+#include "share.h"
+#include "strdup.h"
+#include "curl_memory.h"
+#include "progress.h"
+#include "easyif.h"
+#include "select.h"
+#include "sendf.h" /* for failf function prototype */
+#include "curl_ntlm.h"
+#include "connect.h" /* for Curl_getconnectinfo */
+#include "slist.h"
+#include "amigaos.h"
+#include "non-ascii.h"
+#include "warnless.h"
+#include "conncache.h"
+#include "multiif.h"
+#include "sigpipe.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
+ of win32_init() */
+static void win32_cleanup(void)
+{
+#ifdef USE_WINSOCK
+ WSACleanup();
+#endif
+#ifdef USE_WINDOWS_SSPI
+ Curl_sspi_global_cleanup();
+#endif
+}
+
+/* win32_init() performs win32 socket initialization to properly setup the
+ stack to allow networking */
+static CURLcode win32_init(void)
+{
+#ifdef USE_WINSOCK
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int res;
+
+#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
+ Error IPV6_requires_winsock2
+#endif
+
+ wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
+
+ res = WSAStartup(wVersionRequested, &wsaData);
+
+ if(res != 0)
+ /* Tell the user that we couldn't find a useable */
+ /* winsock.dll. */
+ return CURLE_FAILED_INIT;
+
+ /* Confirm that the Windows Sockets DLL supports what we need.*/
+ /* Note that if the DLL supports versions greater */
+ /* than wVersionRequested, it will still return */
+ /* wVersionRequested in wVersion. wHighVersion contains the */
+ /* highest supported version. */
+
+ if(LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
+ HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
+ /* Tell the user that we couldn't find a useable */
+
+ /* winsock.dll. */
+ WSACleanup();
+ return CURLE_FAILED_INIT;
+ }
+ /* The Windows Sockets DLL is acceptable. Proceed. */
+#elif defined(USE_LWIPSOCK)
+ lwip_init();
+#endif
+
+#ifdef USE_WINDOWS_SSPI
+ {
+ CURLcode err = Curl_sspi_global_init();
+ if(err != CURLE_OK)
+ return err;
+ }
+#endif
+
+ return CURLE_OK;
+}
+
+#ifdef USE_LIBIDN
+/*
+ * Initialise use of IDNA library.
+ * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
+ * idna_to_ascii_lz().
+ */
+static void idna_init (void)
+{
+#ifdef WIN32
+ char buf[60];
+ UINT cp = GetACP();
+
+ if(!getenv("CHARSET") && cp > 0) {
+ snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
+ putenv(buf);
+ }
+#else
+ /* to do? */
+#endif
+}
+#endif /* USE_LIBIDN */
+
+/* true globals -- for curl_global_init() and curl_global_cleanup() */
+static unsigned int initialized;
+static long init_flags;
+
+/*
+ * strdup (and other memory functions) is redefined in complicated
+ * ways, but at this point it must be defined as the system-supplied strdup
+ * so the callback pointer is initialized correctly.
+ */
+#if defined(_WIN32_WCE)
+#define system_strdup _strdup
+#elif !defined(HAVE_STRDUP)
+#define system_strdup curlx_strdup
+#else
+#define system_strdup strdup
+#endif
+
+#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
+#endif
+
+#ifndef __SYMBIAN32__
+/*
+ * If a memory-using function (like curl_getenv) is used before
+ * curl_global_init() is called, we need to have these pointers set already.
+ */
+curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
+curl_free_callback Curl_cfree = (curl_free_callback)free;
+curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
+curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
+curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
+#if defined(WIN32) && defined(UNICODE)
+curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
+#endif
+#else
+/*
+ * Symbian OS doesn't support initialization to code in writeable static data.
+ * Initialization will occur in the curl_global_init() call.
+ */
+curl_malloc_callback Curl_cmalloc;
+curl_free_callback Curl_cfree;
+curl_realloc_callback Curl_crealloc;
+curl_strdup_callback Curl_cstrdup;
+curl_calloc_callback Curl_ccalloc;
+#endif
+
+#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+# pragma warning(default:4232) /* MSVC extension, dllimport identity */
+#endif
+
+/**
+ * curl_global_init() globally initializes cURL given a bitwise set of the
+ * different features of what to initialize.
+ */
+CURLcode curl_global_init(long flags)
+{
+ if(initialized++)
+ return CURLE_OK;
+
+ /* Setup the default memory functions here (again) */
+ Curl_cmalloc = (curl_malloc_callback)malloc;
+ Curl_cfree = (curl_free_callback)free;
+ Curl_crealloc = (curl_realloc_callback)realloc;
+ Curl_cstrdup = (curl_strdup_callback)system_strdup;
+ Curl_ccalloc = (curl_calloc_callback)calloc;
+#if defined(WIN32) && defined(UNICODE)
+ Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
+#endif
+
+ if(flags & CURL_GLOBAL_SSL)
+ if(!Curl_ssl_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+
+ if(flags & CURL_GLOBAL_WIN32)
+ if(win32_init() != CURLE_OK) {
+ DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+
+#ifdef __AMIGA__
+ if(!Curl_amiga_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+#endif
+
+#ifdef NETWARE
+ if(netware_init()) {
+ DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
+ }
+#endif
+
+#ifdef USE_LIBIDN
+ idna_init();
+#endif
+
+ if(Curl_resolver_global_init() != CURLE_OK) {
+ DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+
+#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
+ if(libssh2_init(0)) {
+ DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
+ return CURLE_FAILED_INIT;
+ }
+#endif
+
+ if(flags & CURL_GLOBAL_ACK_EINTR)
+ Curl_ack_eintr = 1;
+
+ init_flags = flags;
+
+ return CURLE_OK;
+}
+
+/*
+ * curl_global_init_mem() globally initializes cURL and also registers the
+ * user provided callback routines.
+ */
+CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
+ curl_free_callback f, curl_realloc_callback r,
+ curl_strdup_callback s, curl_calloc_callback c)
+{
+ CURLcode code = CURLE_OK;
+
+ /* Invalid input, return immediately */
+ if(!m || !f || !r || !s || !c)
+ return CURLE_FAILED_INIT;
+
+ if(initialized) {
+ /* Already initialized, don't do it again, but bump the variable anyway to
+ work like curl_global_init() and require the same amount of cleanup
+ calls. */
+ initialized++;
+ return CURLE_OK;
+ }
+
+ /* Call the actual init function first */
+ code = curl_global_init(flags);
+ if(code == CURLE_OK) {
+ Curl_cmalloc = m;
+ Curl_cfree = f;
+ Curl_cstrdup = s;
+ Curl_crealloc = r;
+ Curl_ccalloc = c;
+ }
+
+ return code;
+}
+
+/**
+ * curl_global_cleanup() globally cleanups cURL, uses the value of
+ * "init_flags" to determine what needs to be cleaned up and what doesn't.
+ */
+void curl_global_cleanup(void)
+{
+ if(!initialized)
+ return;
+
+ if(--initialized)
+ return;
+
+ Curl_global_host_cache_dtor();
+
+ if(init_flags & CURL_GLOBAL_SSL)
+ Curl_ssl_cleanup();
+
+ Curl_resolver_global_cleanup();
+
+ if(init_flags & CURL_GLOBAL_WIN32)
+ win32_cleanup();
+
+ Curl_amiga_cleanup();
+
+#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT)
+ (void)libssh2_exit();
+#endif
+
+ init_flags = 0;
+}
+
+/*
+ * curl_easy_init() is the external interface to alloc, setup and init an
+ * easy handle that is returned. If anything goes wrong, NULL is returned.
+ */
+CURL *curl_easy_init(void)
+{
+ CURLcode res;
+ struct SessionHandle *data;
+
+ /* Make sure we inited the global SSL stuff */
+ if(!initialized) {
+ res = curl_global_init(CURL_GLOBAL_DEFAULT);
+ if(res) {
+ /* something in the global init failed, return nothing */
+ DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
+ return NULL;
+ }
+ }
+
+ /* We use curl_open() with undefined URL so far */
+ res = Curl_open(&data);
+ if(res != CURLE_OK) {
+ DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
+ return NULL;
+ }
+
+ return data;
+}
+
+/*
+ * curl_easy_setopt() is the external interface for setting options on an
+ * easy handle.
+ */
+
+#undef curl_easy_setopt
+CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
+{
+ va_list arg;
+ struct SessionHandle *data = curl;
+ CURLcode ret;
+
+ if(!curl)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ va_start(arg, tag);
+
+ ret = Curl_setopt(data, tag, arg);
+
+ va_end(arg);
+ return ret;
+}
+
+#ifdef CURLDEBUG
+
+struct socketmonitor {
+ struct socketmonitor *next; /* the next node in the list or NULL */
+ struct pollfd socket; /* socket info of what to monitor */
+};
+
+struct events {
+ long ms; /* timeout, run the timeout function when reached */
+ bool msbump; /* set TRUE when timeout is set by callback */
+ int num_sockets; /* number of nodes in the monitor list */
+ struct socketmonitor *list; /* list of sockets to monitor */
+ int running_handles; /* store the returned number */
+};
+
+/* events_timer
+ *
+ * Callback that gets called with a new value when the timeout should be
+ * updated.
+ */
+
+static int events_timer(CURLM *multi, /* multi handle */
+ long timeout_ms, /* see above */
+ void *userp) /* private callback pointer */
+{
+ struct events *ev = userp;
+ (void)multi;
+ if(timeout_ms == -1)
+ /* timeout removed */
+ timeout_ms = 0;
+ else if(timeout_ms == 0)
+ /* timeout is already reached! */
+ timeout_ms = 1; /* trigger asap */
+
+ ev->ms = timeout_ms;
+ ev->msbump = TRUE;
+ return 0;
+}
+
+
+/* poll2cselect
+ *
+ * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones
+ */
+static int poll2cselect(int pollmask)
+{
+ int omask=0;
+ if(pollmask & POLLIN)
+ omask |= CURL_CSELECT_IN;
+ if(pollmask & POLLOUT)
+ omask |= CURL_CSELECT_OUT;
+ if(pollmask & POLLERR)
+ omask |= CURL_CSELECT_ERR;
+ return omask;
+}
+
+
+/* socketcb2poll
+ *
+ * convert from libcurl' CURL_POLL_* bit definitions to poll()'s
+ */
+static short socketcb2poll(int pollmask)
+{
+ short omask=0;
+ if(pollmask & CURL_POLL_IN)
+ omask |= POLLIN;
+ if(pollmask & CURL_POLL_OUT)
+ omask |= POLLOUT;
+ return omask;
+}
+
+/* events_socket
+ *
+ * Callback that gets called with information about socket activity to
+ * monitor.
+ */
+static int events_socket(CURL *easy, /* easy handle */
+ curl_socket_t s, /* socket */
+ int what, /* see above */
+ void *userp, /* private callback
+ pointer */
+ void *socketp) /* private socket
+ pointer */
+{
+ struct events *ev = userp;
+ struct socketmonitor *m;
+ struct socketmonitor *prev=NULL;
+ (void)socketp;
+
+ m = ev->list;
+ while(m) {
+ if(m->socket.fd == s) {
+
+ if(what == CURL_POLL_REMOVE) {
+ struct socketmonitor *nxt = m->next;
+ /* remove this node from the list of monitored sockets */
+ if(prev)
+ prev->next = nxt;
+ else
+ ev->list = nxt;
+ free(m);
+ m = nxt;
+ infof(easy, "socket cb: socket %d REMOVED\n", s);
+ }
+ else {
+ /* The socket 's' is already being monitored, update the activity
+ mask. Convert from libcurl bitmask to the poll one. */
+ m->socket.events = socketcb2poll(what);
+ infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
+ what&CURL_POLL_IN?"IN":"",
+ what&CURL_POLL_OUT?"OUT":"");
+ }
+ break;
+ }
+ prev = m;
+ m = m->next; /* move to next node */
+ }
+ if(!m) {
+ if(what == CURL_POLL_REMOVE) {
+ /* this happens a bit too often, libcurl fix perhaps? */
+ /* fprintf(stderr,
+ "%s: socket %d asked to be REMOVED but not present!\n",
+ __func__, s); */
+ }
+ else {
+ m = malloc(sizeof(struct socketmonitor));
+ m->next = ev->list;
+ m->socket.fd = s;
+ m->socket.events = socketcb2poll(what);
+ m->socket.revents = 0;
+ ev->list = m;
+ infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
+ what&CURL_POLL_IN?"IN":"",
+ what&CURL_POLL_OUT?"OUT":"");
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * events_setup()
+ *
+ * Do the multi handle setups that only event-based transfers need.
+ */
+static void events_setup(CURLM *multi, struct events *ev)
+{
+ /* timer callback */
+ curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
+ curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
+
+ /* socket callback */
+ curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
+ curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
+}
+
+
+/* wait_or_timeout()
+ *
+ * waits for activity on any of the given sockets, or the timeout to trigger.
+ */
+
+static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
+{
+ bool done = FALSE;
+ CURLMcode mcode;
+ CURLcode rc = CURLE_OK;
+
+ while(!done) {
+ CURLMsg *msg;
+ struct socketmonitor *m;
+ struct pollfd *f;
+ struct pollfd fds[4];
+ int numfds=0;
+ int pollrc;
+ int i;
+ struct timeval before;
+ struct timeval after;
+
+ /* populate the fds[] array */
+ for(m = ev->list, f=&fds[0]; m; m = m->next) {
+ f->fd = m->socket.fd;
+ f->events = m->socket.events;
+ f->revents = 0;
+ /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
+ f++;
+ numfds++;
+ }
+
+ /* get the time stamp to use to figure out how long poll takes */
+ before = curlx_tvnow();
+
+ /* wait for activity or timeout */
+ pollrc = Curl_poll(fds, numfds, (int)ev->ms);
+
+ after = curlx_tvnow();
+
+ ev->msbump = FALSE; /* reset here */
+
+ if(0 == pollrc) {
+ /* timeout! */
+ ev->ms = 0;
+ /* fprintf(stderr, "call curl_multi_socket_action( TIMEOUT )\n"); */
+ mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
+ &ev->running_handles);
+ }
+ else if(pollrc > 0) {
+ /* loop over the monitored sockets to see which ones had activity */
+ for(i = 0; i< numfds; i++) {
+ if(fds[i].revents) {
+ /* socket activity, tell libcurl */
+ int act = poll2cselect(fds[i].revents); /* convert */
+ infof(multi->easyp, "call curl_multi_socket_action( socket %d )\n",
+ fds[i].fd);
+ mcode = curl_multi_socket_action(multi, fds[i].fd, act,
+ &ev->running_handles);
+ }
+ }
+
+ if(!ev->msbump)
+ /* If nothing updated the timeout, we decrease it by the spent time.
+ * If it was updated, it has the new timeout time stored already.
+ */
+ ev->ms += curlx_tvdiff(after, before);
+
+ }
+ if(mcode)
+ return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
+
+ /* we don't really care about the "msgs_in_queue" value returned in the
+ second argument */
+ msg = curl_multi_info_read(multi, &pollrc);
+ if(msg) {
+ rc = msg->data.result;
+ done = TRUE;
+ }
+ }
+
+ return rc;
+}
+
+
+/* easy_events()
+ *
+ * Runs a transfer in a blocking manner using the events-based API
+ */
+static CURLcode easy_events(CURLM *multi)
+{
+ struct events evs= {2, FALSE, 0, NULL, 0};
+
+ /* if running event-based, do some further multi inits */
+ events_setup(multi, &evs);
+
+ return wait_or_timeout(multi, &evs);
+}
+#else /* CURLDEBUG */
+/* when not built with debug, this function doesn't exist */
+#define easy_events(x) CURLE_NOT_BUILT_IN
+#endif
+
+static CURLcode easy_transfer(CURLM *multi)
+{
+ bool done = FALSE;
+ CURLMcode mcode = CURLM_OK;
+ CURLcode code = CURLE_OK;
+ struct timeval before;
+ int without_fds = 0; /* count number of consecutive returns from
+ curl_multi_wait() without any filedescriptors */
+
+ while(!done && !mcode) {
+ int still_running = 0;
+ int ret;
+
+ before = curlx_tvnow();
+ mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret);
+
+ if(mcode == CURLM_OK) {
+ if(ret == -1) {
+ /* poll() failed not on EINTR, indicate a network problem */
+ code = CURLE_RECV_ERROR;
+ break;
+ }
+ else if(ret == 0) {
+ struct timeval after = curlx_tvnow();
+ /* If it returns without any filedescriptor instantly, we need to
+ avoid busy-looping during periods where it has nothing particular
+ to wait for */
+ if(curlx_tvdiff(after, before) <= 10) {
+ without_fds++;
+ if(without_fds > 2) {
+ int sleep_ms = without_fds < 10 ? (1 << (without_fds-1)): 1000;
+ Curl_wait_ms(sleep_ms);
+ }
+ }
+ else
+ /* it wasn't "instant", restart counter */
+ without_fds = 0;
+ }
+ else
+ /* got file descriptor, restart counter */
+ without_fds = 0;
+
+ mcode = curl_multi_perform(multi, &still_running);
+ }
+
+ /* only read 'still_running' if curl_multi_perform() return OK */
+ if((mcode == CURLM_OK) && !still_running) {
+ int rc;
+ CURLMsg *msg = curl_multi_info_read(multi, &rc);
+ if(msg) {
+ code = msg->data.result;
+ done = TRUE;
+ }
+ }
+ }
+
+ /* Make sure to return some kind of error if there was a multi problem */
+ if(mcode) {
+ return (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
+ /* The other multi errors should never happen, so return
+ something suitably generic */
+ CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ return code;
+}
+
+
+/*
+ * easy_perform() is the external interface that performs a blocking
+ * transfer as previously setup.
+ *
+ * CONCEPT: This function creates a multi handle, adds the easy handle to it,
+ * runs curl_multi_perform() until the transfer is done, then detaches the
+ * easy handle, destroys the multi handle and returns the easy handle's return
+ * code.
+ *
+ * REALITY: it can't just create and destroy the multi handle that easily. It
+ * needs to keep it around since if this easy handle is used again by this
+ * function, the same multi handle must be re-used so that the same pools and
+ * caches can be used.
+ *
+ * DEBUG: if 'events' is set TRUE, this function will use a replacement engine
+ * instead of curl_multi_perform() and use curl_multi_socket_action().
+ */
+static CURLcode easy_perform(struct SessionHandle *data, bool events)
+{
+ CURLM *multi;
+ CURLMcode mcode;
+ CURLcode code = CURLE_OK;
+ SIGPIPE_VARIABLE(pipe_st);
+
+ if(!data)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(data->multi) {
+ failf(data, "easy handle already used in multi handle");
+ return CURLE_FAILED_INIT;
+ }
+
+ if(data->multi_easy)
+ multi = data->multi_easy;
+ else {
+ /* this multi handle will only ever have a single easy handled attached
+ to it, so make it use minimal hashes */
+ multi = Curl_multi_handle(1, 3);
+ if(!multi)
+ return CURLE_OUT_OF_MEMORY;
+ data->multi_easy = multi;
+ }
+
+ /* Copy the MAXCONNECTS option to the multi handle */
+ curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
+
+ mcode = curl_multi_add_handle(multi, data);
+ if(mcode) {
+ curl_multi_cleanup(multi);
+ if(mcode == CURLM_OUT_OF_MEMORY)
+ return CURLE_OUT_OF_MEMORY;
+ else
+ return CURLE_FAILED_INIT;
+ }
+
+ sigpipe_ignore(data, &pipe_st);
+
+ /* assign this after curl_multi_add_handle() since that function checks for
+ it and rejects this handle otherwise */
+ data->multi = multi;
+
+ /* run the transfer */
+ code = events ? easy_events(multi) : easy_transfer(multi);
+
+ /* ignoring the return code isn't nice, but atm we can't really handle
+ a failure here, room for future improvement! */
+ (void)curl_multi_remove_handle(multi, data);
+
+ sigpipe_restore(&pipe_st);
+
+ /* The multi handle is kept alive, owned by the easy handle */
+ return code;
+}
+
+
+/*
+ * curl_easy_perform() is the external interface that performs a blocking
+ * transfer as previously setup.
+ */
+CURLcode curl_easy_perform(CURL *easy)
+{
+ return easy_perform(easy, FALSE);
+}
+
+#ifdef CURLDEBUG
+/*
+ * curl_easy_perform_ev() is the external interface that performs a blocking
+ * transfer using the event-based API internally.
+ */
+CURLcode curl_easy_perform_ev(CURL *easy)
+{
+ return easy_perform(easy, TRUE);
+}
+
+#endif
+
+/*
+ * curl_easy_cleanup() is the external interface to cleaning/freeing the given
+ * easy handle.
+ */
+void curl_easy_cleanup(CURL *curl)
+{
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+ SIGPIPE_VARIABLE(pipe_st);
+
+ if(!data)
+ return;
+
+ sigpipe_ignore(data, &pipe_st);
+ Curl_close(data);
+ sigpipe_restore(&pipe_st);
+}
+
+/*
+ * curl_easy_getinfo() is an external interface that allows an app to retrieve
+ * information from a performed transfer and similar.
+ */
+#undef curl_easy_getinfo
+CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
+{
+ va_list arg;
+ void *paramp;
+ CURLcode ret;
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+
+ va_start(arg, info);
+ paramp = va_arg(arg, void *);
+
+ ret = Curl_getinfo(data, info, paramp);
+
+ va_end(arg);
+ return ret;
+}
+
+/*
+ * curl_easy_duphandle() is an external interface to allow duplication of a
+ * given input easy handle. The returned handle will be a new working handle
+ * with all options set exactly as the input source handle.
+ */
+CURL *curl_easy_duphandle(CURL *incurl)
+{
+ struct SessionHandle *data=(struct SessionHandle *)incurl;
+
+ struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle));
+ if(NULL == outcurl)
+ goto fail;
+
+ /*
+ * We setup a few buffers we need. We should probably make them
+ * get setup on-demand in the code, as that would probably decrease
+ * the likeliness of us forgetting to init a buffer here in the future.
+ */
+ outcurl->state.headerbuff = malloc(HEADERSIZE);
+ if(!outcurl->state.headerbuff)
+ goto fail;
+ outcurl->state.headersize = HEADERSIZE;
+
+ /* copy all userdefined values */
+ if(Curl_dupset(outcurl, data) != CURLE_OK)
+ goto fail;
+
+ /* the connection cache is setup on demand */
+ outcurl->state.conn_cache = NULL;
+
+ outcurl->state.lastconnect = NULL;
+
+ outcurl->progress.flags = data->progress.flags;
+ 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,
+ data->cookies->filename,
+ outcurl->cookies,
+ data->set.cookiesession);
+ if(!outcurl->cookies)
+ goto fail;
+ }
+
+ /* duplicate all values in 'change' */
+ if(data->change.cookielist) {
+ outcurl->change.cookielist =
+ Curl_slist_duplicate(data->change.cookielist);
+ if(!outcurl->change.cookielist)
+ goto fail;
+ }
+
+ if(data->change.url) {
+ outcurl->change.url = strdup(data->change.url);
+ if(!outcurl->change.url)
+ goto fail;
+ outcurl->change.url_alloc = TRUE;
+ }
+
+ if(data->change.referer) {
+ outcurl->change.referer = strdup(data->change.referer);
+ if(!outcurl->change.referer)
+ goto fail;
+ outcurl->change.referer_alloc = TRUE;
+ }
+
+ /* Clone the resolver handle, if present, for the new handle */
+ if(Curl_resolver_duphandle(&outcurl->state.resolver,
+ data->state.resolver) != CURLE_OK)
+ goto fail;
+
+ Curl_convert_setup(outcurl);
+
+ outcurl->magic = CURLEASY_MAGIC_NUMBER;
+
+ /* we reach this point and thus we are OK */
+
+ return outcurl;
+
+ fail:
+
+ if(outcurl) {
+ curl_slist_free_all(outcurl->change.cookielist);
+ outcurl->change.cookielist = NULL;
+ Curl_safefree(outcurl->state.headerbuff);
+ Curl_safefree(outcurl->change.url);
+ Curl_safefree(outcurl->change.referer);
+ Curl_freeset(outcurl);
+ free(outcurl);
+ }
+
+ return NULL;
+}
+
+/*
+ * curl_easy_reset() is an external interface that allows an app to re-
+ * initialize a session handle to the default values.
+ */
+void curl_easy_reset(CURL *curl)
+{
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+
+ Curl_safefree(data->state.pathbuffer);
+
+ data->state.path = NULL;
+
+ Curl_free_request_state(data);
+
+ /* zero out UserDefined data: */
+ Curl_freeset(data);
+ memset(&data->set, 0, sizeof(struct UserDefined));
+ (void)Curl_init_userdefined(&data->set);
+
+ /* zero out Progress data: */
+ memset(&data->progress, 0, sizeof(struct Progress));
+
+ data->progress.flags |= PGRS_HIDE;
+ data->state.current_speed = -1; /* init to negative == impossible */
+}
+
+/*
+ * curl_easy_pause() allows an application to pause or unpause a specific
+ * transfer and direction. This function sets the full new state for the
+ * current connection this easy handle operates on.
+ *
+ * NOTE: if you have the receiving paused and you call this function to remove
+ * the pausing, you may get your write callback called at this point.
+ *
+ * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
+ */
+CURLcode curl_easy_pause(CURL *curl, int action)
+{
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+ struct SingleRequest *k = &data->req;
+ CURLcode result = CURLE_OK;
+
+ /* first switch off both pause bits */
+ int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
+
+ /* set the new desired pause bits */
+ newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
+ ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
+
+ /* put it back in the keepon */
+ k->keepon = newstate;
+
+ if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
+ /* we have a buffer for sending that we now seem to be able to deliver
+ since the receive pausing is lifted! */
+
+ /* get the pointer, type and length in local copies since the function may
+ return PAUSE again and then we'll get a new copy allocted and stored in
+ the tempwrite variables */
+ char *tempwrite = data->state.tempwrite;
+ char *freewrite = tempwrite; /* store this pointer to free it later */
+ size_t tempsize = data->state.tempwritesize;
+ int temptype = data->state.tempwritetype;
+ size_t chunklen;
+
+ /* clear tempwrite here just to make sure it gets cleared if there's no
+ further use of it, and make sure we don't clear it after the function
+ invoke as it may have been set to a new value by then */
+ data->state.tempwrite = NULL;
+
+ /* since the write callback API is define to never exceed
+ CURL_MAX_WRITE_SIZE bytes in a single call, and since we may in fact
+ have more data than that in our buffer here, we must loop sending the
+ data in multiple calls until there's no data left or we get another
+ pause returned.
+
+ A tricky part is that the function we call will "buffer" the data
+ itself when it pauses on a particular buffer, so we may need to do some
+ extra trickery if we get a pause return here.
+ */
+ do {
+ chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize;
+
+ result = Curl_client_write(data->easy_conn,
+ temptype, tempwrite, chunklen);
+ if(result)
+ /* failures abort the loop at once */
+ break;
+
+ if(data->state.tempwrite && (tempsize - chunklen)) {
+ /* Ouch, the reading is again paused and the block we send is now
+ "cached". If this is the final chunk we can leave it like this, but
+ if we have more chunks that are cached after this, we need to free
+ the newly cached one and put back a version that is truly the entire
+ contents that is saved for later
+ */
+ char *newptr;
+
+ /* note that tempsize is still the size as before the callback was
+ used, and thus the whole piece of data to keep */
+ newptr = realloc(data->state.tempwrite, tempsize);
+
+ if(!newptr) {
+ free(data->state.tempwrite); /* free old area */
+ data->state.tempwrite = NULL;
+ result = CURLE_OUT_OF_MEMORY;
+ /* tempwrite will be freed further down */
+ break;
+ }
+ data->state.tempwrite = newptr; /* store new pointer */
+ memcpy(newptr, tempwrite, tempsize);
+ data->state.tempwritesize = tempsize; /* store new size */
+ /* tempwrite will be freed further down */
+ break; /* go back to pausing until further notice */
+ }
+ else {
+ tempsize -= chunklen; /* left after the call above */
+ tempwrite += chunklen; /* advance the pointer */
+ }
+
+ } while((result == CURLE_OK) && tempsize);
+
+ free(freewrite); /* this is unconditionally no longer used */
+ }
+
+ /* if there's no error and we're not pausing both directions, we want
+ to have this handle checked soon */
+ if(!result &&
+ ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
+ (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
+ Curl_expire(data, 1); /* get this handle going again */
+
+ return result;
+}
+
+
+static CURLcode easy_connection(struct SessionHandle *data,
+ curl_socket_t *sfd,
+ struct connectdata **connp)
+{
+ if(data == NULL)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
+ if(!data->set.connect_only) {
+ failf(data, "CONNECT_ONLY is required!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
+ *sfd = Curl_getconnectinfo(data, connp);
+
+ if(*sfd == CURL_SOCKET_BAD) {
+ failf(data, "Failed to get recent socket");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Receives data from the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ * Returns CURLE_OK on success, error code on error.
+ */
+CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
+{
+ curl_socket_t sfd;
+ CURLcode ret;
+ ssize_t n1;
+ struct connectdata *c;
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+
+ ret = easy_connection(data, &sfd, &c);
+ if(ret)
+ return ret;
+
+ *n = 0;
+ ret = Curl_read(c, sfd, buffer, buflen, &n1);
+
+ if(ret != CURLE_OK)
+ return ret;
+
+ *n = (size_t)n1;
+
+ return CURLE_OK;
+}
+
+/*
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen,
+ size_t *n)
+{
+ curl_socket_t sfd;
+ CURLcode ret;
+ ssize_t n1;
+ struct connectdata *c = NULL;
+ struct SessionHandle *data = (struct SessionHandle *)curl;
+
+ ret = easy_connection(data, &sfd, &c);
+ if(ret)
+ return ret;
+
+ *n = 0;
+ ret = Curl_write(c, sfd, buffer, buflen, &n1);
+
+ if(n1 == -1)
+ return CURLE_SEND_ERROR;
+
+ /* detect EAGAIN */
+ if((CURLE_OK == ret) && (0 == n1))
+ return CURLE_AGAIN;
+
+ *n = (size_t)n1;
+
+ return ret;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/easyif.h b/external/libcurl_android/jni/libcurl/lib/easyif.h
new file mode 100755
index 00000000..043ff437
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/easyif.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_EASYIF_H
+#define HEADER_CURL_EASYIF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Prototypes for library-wide functions provided by easy.c
+ */
+#ifdef CURLDEBUG
+CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy);
+#endif
+
+#endif /* HEADER_CURL_EASYIF_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/escape.c b/external/libcurl_android/jni/libcurl/lib/escape.c
new file mode 100755
index 00000000..d7f8a8f5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/escape.c
@@ -0,0 +1,233 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Escape and unescape URL encoding in strings. The functions return a new
+ * allocated string or NULL if an error occurred. */
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "curl_memory.h"
+#include "urldata.h"
+#include "warnless.h"
+#include "non-ascii.h"
+#include "escape.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Portable character check (remember EBCDIC). Do not use isalnum() because
+ its behavior is altered by the current locale.
+ See http://tools.ietf.org/html/rfc3986#section-2.3
+*/
+static bool Curl_isunreserved(unsigned char in)
+{
+ switch (in) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ case '-': case '.': case '_': case '~':
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/* for ABI-compatibility with previous versions */
+char *curl_escape(const char *string, int inlength)
+{
+ return curl_easy_escape(NULL, string, inlength);
+}
+
+/* for ABI-compatibility with previous versions */
+char *curl_unescape(const char *string, int length)
+{
+ return curl_easy_unescape(NULL, string, length, NULL);
+}
+
+char *curl_easy_escape(CURL *handle, const char *string, int inlength)
+{
+ size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
+ char *ns;
+ char *testing_ptr = NULL;
+ unsigned char in; /* we need to treat the characters unsigned */
+ size_t newlen = alloc;
+ size_t strindex=0;
+ size_t length;
+ CURLcode res;
+
+ ns = malloc(alloc);
+ if(!ns)
+ return NULL;
+
+ length = alloc-1;
+ while(length--) {
+ in = *string;
+
+ if(Curl_isunreserved(in))
+ /* just copy this */
+ ns[strindex++]=in;
+ else {
+ /* encode it */
+ newlen += 2; /* the size grows with two, since this'll become a %XX */
+ if(newlen > alloc) {
+ alloc *= 2;
+ testing_ptr = realloc(ns, alloc);
+ if(!testing_ptr) {
+ free( ns );
+ return NULL;
+ }
+ else {
+ ns = testing_ptr;
+ }
+ }
+
+ res = Curl_convert_to_network(handle, &in, 1);
+ if(res) {
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ free(ns);
+ return NULL;
+ }
+
+ snprintf(&ns[strindex], 4, "%%%02X", in);
+
+ strindex+=3;
+ }
+ string++;
+ }
+ ns[strindex]=0; /* terminate it */
+ return ns;
+}
+
+/*
+ * Curl_urldecode() URL decodes the given string.
+ *
+ * Optionally detects control characters (byte codes lower than 32) in the
+ * data and rejects such data.
+ *
+ * Returns a pointer to a malloced string in *ostring with length given in
+ * *olen. If length == 0, the length is assumed to be strlen(string).
+ *
+ */
+CURLcode Curl_urldecode(struct SessionHandle *data,
+ const char *string, size_t length,
+ char **ostring, size_t *olen,
+ bool reject_ctrl)
+{
+ size_t alloc = (length?length:strlen(string))+1;
+ char *ns = malloc(alloc);
+ unsigned char in;
+ size_t strindex=0;
+ unsigned long hex;
+ CURLcode res;
+
+ if(!ns)
+ return CURLE_OUT_OF_MEMORY;
+
+ while(--alloc > 0) {
+ in = *string;
+ if(('%' == in) && (alloc > 2) &&
+ ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
+ /* this is two hexadecimal digits following a '%' */
+ char hexstr[3];
+ char *ptr;
+ hexstr[0] = string[1];
+ hexstr[1] = string[2];
+ hexstr[2] = 0;
+
+ hex = strtoul(hexstr, &ptr, 16);
+
+ in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
+
+ res = Curl_convert_from_network(data, &in, 1);
+ if(res) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(ns);
+ return res;
+ }
+
+ string+=2;
+ alloc-=2;
+ }
+ if(reject_ctrl && (in < 0x20)) {
+ free(ns);
+ return CURLE_URL_MALFORMAT;
+ }
+
+ ns[strindex++] = in;
+ string++;
+ }
+ ns[strindex]=0; /* terminate it */
+
+ if(olen)
+ /* store output size */
+ *olen = strindex;
+
+ /* store output string */
+ *ostring = ns;
+
+ return CURLE_OK;
+}
+
+/*
+ * Unescapes the given URL escaped string of given length. Returns a
+ * pointer to a malloced string with length given in *olen.
+ * If length == 0, the length is assumed to be strlen(string).
+ * If olen == NULL, no output length is stored.
+ */
+char *curl_easy_unescape(CURL *handle, const char *string, int length,
+ int *olen)
+{
+ char *str = NULL;
+ size_t inputlen = length;
+ size_t outputlen;
+ CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen,
+ FALSE);
+ if(res)
+ return NULL;
+ if(olen)
+ *olen = curlx_uztosi(outputlen);
+ return str;
+}
+
+/* For operating systems/environments that use different malloc/free
+ systems for the app and for this library, we provide a free that uses
+ the library's memory system */
+void curl_free(void *p)
+{
+ if(p)
+ free(p);
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/escape.h b/external/libcurl_android/jni/libcurl/lib/escape.h
new file mode 100755
index 00000000..731b1365
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/escape.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_ESCAPE_H
+#define HEADER_CURL_ESCAPE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/* Escape and unescape URL encoding in strings. The functions return a new
+ * allocated string or NULL if an error occurred. */
+
+CURLcode Curl_urldecode(struct SessionHandle *data,
+ const char *string, size_t length,
+ char **ostring, size_t *olen,
+ bool reject_crlf);
+
+#endif /* HEADER_CURL_ESCAPE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/file.c b/external/libcurl_android/jni/libcurl/lib/file.c
new file mode 100755
index 00000000..73df42e0
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/file.c
@@ -0,0 +1,583 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FILE
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "strtoofft.h"
+#include "urldata.h"
+#include <curl/curl.h>
+#include "progress.h"
+#include "sendf.h"
+#include "escape.h"
+#include "file.h"
+#include "speedcheck.h"
+#include "getinfo.h"
+#include "transfer.h"
+#include "url.h"
+#include "curl_memory.h"
+#include "parsedate.h" /* for the week day and month names */
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \
+ defined(__SYMBIAN32__)
+#define DOS_FILESYSTEM 1
+#endif
+
+#ifdef OPEN_NEEDS_ARG3
+# define open_readonly(p,f) open((p),(f),(0))
+#else
+# define open_readonly(p,f) open((p),(f))
+#endif
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode file_do(struct connectdata *, bool *done);
+static CURLcode file_done(struct connectdata *conn,
+ CURLcode status, bool premature);
+static CURLcode file_connect(struct connectdata *conn, bool *done);
+static CURLcode file_disconnect(struct connectdata *conn,
+ bool dead_connection);
+static CURLcode file_setup_connection(struct connectdata *conn);
+
+/*
+ * FILE scheme handler.
+ */
+
+const struct Curl_handler Curl_handler_file = {
+ "FILE", /* scheme */
+ file_setup_connection, /* setup_connection */
+ file_do, /* do_it */
+ file_done, /* done */
+ ZERO_NULL, /* do_more */
+ file_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ file_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ 0, /* defport */
+ CURLPROTO_FILE, /* protocol */
+ PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */
+};
+
+
+static CURLcode file_setup_connection(struct connectdata *conn)
+{
+ /* allocate the FILE specific struct */
+ conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO));
+ if(!conn->data->req.protop)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+ /*
+ Check if this is a range download, and if so, set the internal variables
+ properly. This code is copied from the FTP implementation and might as
+ well be factored out.
+ */
+static CURLcode file_range(struct connectdata *conn)
+{
+ curl_off_t from, to;
+ curl_off_t totalsize=-1;
+ char *ptr;
+ char *ptr2;
+ struct SessionHandle *data = conn->data;
+
+ if(data->state.use_range && data->state.range) {
+ from=curlx_strtoofft(data->state.range, &ptr, 0);
+ while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+ ptr++;
+ to=curlx_strtoofft(ptr, &ptr2, 0);
+ if(ptr == ptr2) {
+ /* we didn't get any digit */
+ to=-1;
+ }
+ if((-1 == to) && (from>=0)) {
+ /* X - */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
+ from));
+ }
+ else if(from < 0) {
+ /* -Y */
+ data->req.maxdownload = -from;
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ -from));
+ }
+ else {
+ /* X-Y */
+ totalsize = to-from;
+ data->req.maxdownload = totalsize+1; /* include last byte */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, data->req.maxdownload));
+ }
+ DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
+ " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, to, data->req.maxdownload));
+ }
+ else
+ data->req.maxdownload = -1;
+ return CURLE_OK;
+}
+
+/*
+ * file_connect() gets called from Curl_protocol_connect() to allow us to
+ * do protocol-specific actions at connect-time. We emulate a
+ * connect-then-transfer protocol and "connect" to the file here
+ */
+static CURLcode file_connect(struct connectdata *conn, bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ char *real_path;
+ struct FILEPROTO *file = data->req.protop;
+ int fd;
+#ifdef DOS_FILESYSTEM
+ int i;
+ char *actual_path;
+#endif
+
+ real_path = curl_easy_unescape(data, data->state.path, 0, NULL);
+ if(!real_path)
+ return CURLE_OUT_OF_MEMORY;
+
+#ifdef DOS_FILESYSTEM
+ /* If the first character is a slash, and there's
+ something that looks like a drive at the beginning of
+ the path, skip the slash. If we remove the initial
+ slash in all cases, paths without drive letters end up
+ relative to the current directory which isn't how
+ browsers work.
+
+ Some browsers accept | instead of : as the drive letter
+ separator, so we do too.
+
+ On other platforms, we need the slash to indicate an
+ absolute pathname. On Windows, absolute paths start
+ with a drive letter.
+ */
+ actual_path = real_path;
+ if((actual_path[0] == '/') &&
+ actual_path[1] &&
+ (actual_path[2] == ':' || actual_path[2] == '|')) {
+ actual_path[2] = ':';
+ actual_path++;
+ }
+
+ /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
+ for(i=0; actual_path[i] != '\0'; ++i)
+ if(actual_path[i] == '/')
+ actual_path[i] = '\\';
+
+ fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
+ file->path = actual_path;
+#else
+ fd = open_readonly(real_path, O_RDONLY);
+ file->path = real_path;
+#endif
+ file->freepath = real_path; /* free this when done */
+
+ file->fd = fd;
+ if(!data->set.upload && (fd == -1)) {
+ failf(data, "Couldn't open file %s", data->state.path);
+ file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
+ return CURLE_FILE_COULDNT_READ_FILE;
+ }
+ *done = TRUE;
+
+ return CURLE_OK;
+}
+
+static CURLcode file_done(struct connectdata *conn,
+ CURLcode status, bool premature)
+{
+ struct FILEPROTO *file = conn->data->req.protop;
+ (void)status; /* not used */
+ (void)premature; /* not used */
+
+ if(file) {
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1)
+ close(file->fd);
+ file->fd = -1;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode file_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ struct FILEPROTO *file = conn->data->req.protop;
+ (void)dead_connection; /* not used */
+
+ if(file) {
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1)
+ close(file->fd);
+ file->fd = -1;
+ }
+
+ return CURLE_OK;
+}
+
+#ifdef DOS_FILESYSTEM
+#define DIRSEP '\\'
+#else
+#define DIRSEP '/'
+#endif
+
+static CURLcode file_upload(struct connectdata *conn)
+{
+ struct FILEPROTO *file = conn->data->req.protop;
+ const char *dir = strchr(file->path, DIRSEP);
+ int fd;
+ int mode;
+ CURLcode res=CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *buf = data->state.buffer;
+ size_t nread;
+ size_t nwrite;
+ curl_off_t bytecount = 0;
+ struct timeval now = Curl_tvnow();
+ struct_stat file_stat;
+ const char* buf2;
+
+ /*
+ * Since FILE: doesn't do the full init, we need to provide some extra
+ * assignments here.
+ */
+ conn->fread_func = data->set.fread_func;
+ conn->fread_in = data->set.in;
+ conn->data->req.upload_fromhere = buf;
+
+ if(!dir)
+ return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
+
+ if(!dir[1])
+ return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
+
+#ifdef O_BINARY
+#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY
+#else
+#define MODE_DEFAULT O_WRONLY|O_CREAT
+#endif
+
+ if(data->state.resume_from)
+ mode = MODE_DEFAULT|O_APPEND;
+ else
+ mode = MODE_DEFAULT|O_TRUNC;
+
+ fd = open(file->path, mode, conn->data->set.new_file_perms);
+ if(fd < 0) {
+ failf(data, "Can't open %s for writing", file->path);
+ return CURLE_WRITE_ERROR;
+ }
+
+ if(-1 != data->state.infilesize)
+ /* known size of data to "upload" */
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+
+ /* treat the negative resume offset value as the case of "-" */
+ if(data->state.resume_from < 0) {
+ if(fstat(fd, &file_stat)) {
+ close(fd);
+ failf(data, "Can't get the size of %s", file->path);
+ return CURLE_WRITE_ERROR;
+ }
+ else
+ data->state.resume_from = (curl_off_t)file_stat.st_size;
+ }
+
+ while(res == CURLE_OK) {
+ int readcount;
+ res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
+ if(res)
+ break;
+
+ if(readcount <= 0) /* fix questionable compare error. curlvms */
+ break;
+
+ nread = (size_t)readcount;
+
+ /*skip bytes before resume point*/
+ if(data->state.resume_from) {
+ if((curl_off_t)nread <= data->state.resume_from ) {
+ data->state.resume_from -= nread;
+ nread = 0;
+ buf2 = buf;
+ }
+ else {
+ buf2 = buf + data->state.resume_from;
+ nread -= (size_t)data->state.resume_from;
+ data->state.resume_from = 0;
+ }
+ }
+ else
+ buf2 = buf;
+
+ /* write the data to the target */
+ nwrite = write(fd, buf2, nread);
+ if(nwrite != nread) {
+ res = CURLE_SEND_ERROR;
+ break;
+ }
+
+ bytecount += nread;
+
+ Curl_pgrsSetUploadCounter(data, bytecount);
+
+ if(Curl_pgrsUpdate(conn))
+ res = CURLE_ABORTED_BY_CALLBACK;
+ else
+ res = Curl_speedcheck(data, now);
+ }
+ if(!res && Curl_pgrsUpdate(conn))
+ res = CURLE_ABORTED_BY_CALLBACK;
+
+ close(fd);
+
+ return res;
+}
+
+/*
+ * file_do() is the protocol-specific function for the do-phase, separated
+ * from the connect-phase above. Other protocols merely setup the transfer in
+ * the do-phase, to have it done in the main transfer loop but since some
+ * platforms we support don't allow select()ing etc on file handles (as
+ * opposed to sockets) we instead perform the whole do-operation in this
+ * function.
+ */
+static CURLcode file_do(struct connectdata *conn, bool *done)
+{
+ /* This implementation ignores the host name in conformance with
+ RFC 1738. Only local files (reachable via the standard file system)
+ are supported. This means that files on remotely mounted directories
+ (via NFS, Samba, NT sharing) can be accessed through a file:// URL
+ */
+ CURLcode res = CURLE_OK;
+ struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
+ Windows version to have a different struct without
+ having to redefine the simple word 'stat' */
+ curl_off_t expected_size=0;
+ bool fstated=FALSE;
+ ssize_t nread;
+ struct SessionHandle *data = conn->data;
+ char *buf = data->state.buffer;
+ curl_off_t bytecount = 0;
+ int fd;
+ struct timeval now = Curl_tvnow();
+ struct FILEPROTO *file;
+
+ *done = TRUE; /* unconditionally */
+
+ Curl_initinfo(data);
+ Curl_pgrsStartNow(data);
+
+ if(data->set.upload)
+ return file_upload(conn);
+
+ file = conn->data->req.protop;
+
+ /* get the fd from the connection phase */
+ fd = file->fd;
+
+ /* VMS: This only works reliable for STREAMLF files */
+ if(-1 != fstat(fd, &statbuf)) {
+ /* we could stat it, then read out the size */
+ expected_size = statbuf.st_size;
+ /* and store the modification time */
+ data->info.filetime = (long)statbuf.st_mtime;
+ fstated = TRUE;
+ }
+
+ if(fstated && !data->state.range && data->set.timecondition) {
+ if(!Curl_meets_timecondition(data, (time_t)data->info.filetime)) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ }
+
+ /* If we have selected NOBODY and HEADER, it means that we only want file
+ information. Which for FILE can't be much more than the file size and
+ date. */
+ if(data->set.opt_no_body && data->set.include_header && fstated) {
+ CURLcode result;
+ snprintf(buf, sizeof(data->state.buffer),
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ if(result)
+ return result;
+
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH,
+ (char *)"Accept-ranges: bytes\r\n", 0);
+ if(result)
+ return result;
+
+ if(fstated) {
+ time_t filetime = (time_t)statbuf.st_mtime;
+ struct tm buffer;
+ const struct tm *tm = &buffer;
+ result = Curl_gmtime(filetime, &buffer);
+ if(result)
+ return result;
+
+ /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
+ snprintf(buf, BUFSIZE-1,
+ "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ }
+ /* if we fstat()ed the file, set the file size to make it available post-
+ transfer */
+ if(fstated)
+ Curl_pgrsSetDownloadSize(data, expected_size);
+ return result;
+ }
+
+ /* Check whether file range has been specified */
+ file_range(conn);
+
+ /* Adjust the start offset in case we want to get the N last bytes
+ * of the stream iff the filesize could be determined */
+ if(data->state.resume_from < 0) {
+ if(!fstated) {
+ failf(data, "Can't get the size of file.");
+ return CURLE_READ_ERROR;
+ }
+ else
+ data->state.resume_from += (curl_off_t)statbuf.st_size;
+ }
+
+ if(data->state.resume_from <= expected_size)
+ expected_size -= data->state.resume_from;
+ else {
+ failf(data, "failed to resume file:// transfer");
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+
+ /* A high water mark has been specified so we obey... */
+ if(data->req.maxdownload > 0)
+ expected_size = data->req.maxdownload;
+
+ if(fstated && (expected_size == 0))
+ return CURLE_OK;
+
+ /* The following is a shortcut implementation of file reading
+ this is both more efficient than the former call to download() and
+ it avoids problems with select() and recv() on file descriptors
+ in Winsock */
+ if(fstated)
+ Curl_pgrsSetDownloadSize(data, expected_size);
+
+ if(data->state.resume_from) {
+ if(data->state.resume_from !=
+ lseek(fd, data->state.resume_from, SEEK_SET))
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+
+ Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+
+ while(res == CURLE_OK) {
+ /* Don't fill a whole buffer if we want less than all data */
+ size_t bytestoread =
+ (expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ?
+ curlx_sotouz(expected_size) : BUFSIZE - 1;
+
+ nread = read(fd, buf, bytestoread);
+
+ if(nread > 0)
+ buf[nread] = 0;
+
+ if(nread <= 0 || expected_size == 0)
+ break;
+
+ bytecount += nread;
+ expected_size -= nread;
+
+ res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
+ if(res)
+ return res;
+
+ Curl_pgrsSetDownloadCounter(data, bytecount);
+
+ if(Curl_pgrsUpdate(conn))
+ res = CURLE_ABORTED_BY_CALLBACK;
+ else
+ res = Curl_speedcheck(data, now);
+ }
+ if(Curl_pgrsUpdate(conn))
+ res = CURLE_ABORTED_BY_CALLBACK;
+
+ return res;
+}
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/file.h b/external/libcurl_android/jni/libcurl/lib/file.h
new file mode 100755
index 00000000..997474bc
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/file.h
@@ -0,0 +1,41 @@
+#ifndef HEADER_CURL_FILE_H
+#define HEADER_CURL_FILE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+
+/****************************************************************************
+ * FILE unique setup
+ ***************************************************************************/
+struct FILEPROTO {
+ char *path; /* the path we operate on */
+ char *freepath; /* pointer to the allocated block we must free, this might
+ differ from the 'path' pointer */
+ int fd; /* open file descriptor to read from! */
+};
+
+#ifndef CURL_DISABLE_FILE
+extern const struct Curl_handler Curl_handler_file;
+#endif
+
+#endif /* HEADER_CURL_FILE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/fileinfo.c b/external/libcurl_android/jni/libcurl/lib/fileinfo.c
new file mode 100755
index 00000000..8c8ee981
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/fileinfo.c
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010-2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "strdup.h"
+#include "fileinfo.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+struct curl_fileinfo *Curl_fileinfo_alloc(void)
+{
+ struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo));
+ if(!tmp)
+ return NULL;
+ memset(tmp, 0, sizeof(struct curl_fileinfo));
+ return tmp;
+}
+
+void Curl_fileinfo_dtor(void *user, void *element)
+{
+ struct curl_fileinfo *finfo = element;
+ (void) user;
+ if(!finfo)
+ return;
+
+ Curl_safefree(finfo->b_data);
+
+ free(finfo);
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/fileinfo.h b/external/libcurl_android/jni/libcurl/lib/fileinfo.h
new file mode 100755
index 00000000..b0e5e59e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/fileinfo.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_FILEINFO_H
+#define HEADER_CURL_FILEINFO_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+struct curl_fileinfo *Curl_fileinfo_alloc(void);
+
+void Curl_fileinfo_dtor(void *, void *);
+
+struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src);
+
+#endif /* HEADER_CURL_FILEINFO_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/firefox-db2pem.sh b/external/libcurl_android/jni/libcurl/lib/firefox-db2pem.sh
new file mode 100755
index 00000000..14ac5760
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/firefox-db2pem.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# ***************************************************************************
+# * _ _ ____ _
+# * Project ___| | | | _ \| |
+# * / __| | | | |_) | |
+# * | (__| |_| | _ <| |___
+# * \___|\___/|_| \_\_____|
+# *
+# * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+# *
+# * This software is licensed as described in the file COPYING, which
+# * you should have received as part of this distribution. The terms
+# * are also available at http://curl.haxx.se/docs/copyright.html.
+# *
+# * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# * copies of the Software, and permit persons to whom the Software is
+# * furnished to do so, under the terms of the COPYING file.
+# *
+# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# * KIND, either express or implied.
+# *
+# ***************************************************************************
+# This shell script creates a fresh ca-bundle.crt file for use with libcurl.
+# It extracts all ca certs it finds in the local Firefox database and converts
+# them all into PEM format.
+#
+db=`ls -1d $HOME/.mozilla/firefox/*default`
+out=$1
+
+if test -z "$out"; then
+ out="ca-bundle.crt" # use a sensible default
+fi
+
+currentdate=`date`
+
+cat >$out <<EOF
+##
+## Bundle of CA Root Certificates
+##
+## Converted at: ${currentdate}
+## These were converted from the local Firefox directory by the db2pem script.
+##
+EOF
+
+
+certutil -L -h 'Builtin Object Token' -d $db | \
+grep ' *[CcGTPpu]*,[CcGTPpu]*,[CcGTPpu]* *$' | \
+sed -e 's/ *[CcGTPpu]*,[CcGTPpu]*,[CcGTPpu]* *$//' -e 's/\(.*\)/"\1"/' | \
+sort | \
+while read nickname; \
+ do echo $nickname | sed -e "s/Builtin Object Token://g"; \
+eval certutil -d $db -L -n "$nickname" -a ; \
+done >> $out
+
diff --git a/external/libcurl_android/jni/libcurl/lib/formdata.c b/external/libcurl_android/jni/libcurl/lib/formdata.c
new file mode 100755
index 00000000..3260928f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/formdata.c
@@ -0,0 +1,1596 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
+
+#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
+#include <libgen.h>
+#endif
+
+#include "urldata.h" /* for struct SessionHandle */
+#include "formdata.h"
+#include "vtls/vtls.h"
+#include "strequal.h"
+#include "curl_memory.h"
+#include "sendf.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#endif /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */
+
+#ifndef CURL_DISABLE_HTTP
+
+#ifndef HAVE_BASENAME
+static char *Curl_basename(char *path);
+#define basename(x) Curl_basename((x))
+#endif
+
+static size_t readfromfile(struct Form *form, char *buffer, size_t size);
+static char *formboundary(struct SessionHandle *data);
+
+/* What kind of Content-Type to use on un-specified files with unrecognized
+ extensions. */
+#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
+
+#define FORM_FILE_SEPARATOR ','
+#define FORM_TYPE_SEPARATOR ';'
+
+/***************************************************************************
+ *
+ * AddHttpPost()
+ *
+ * Adds a HttpPost structure to the list, if parent_post is given becomes
+ * a subpost of parent_post instead of a direct list element.
+ *
+ * Returns newly allocated HttpPost on success and NULL if malloc failed.
+ *
+ ***************************************************************************/
+static struct curl_httppost *
+AddHttpPost(char *name, size_t namelength,
+ char *value, size_t contentslength,
+ char *buffer, size_t bufferlength,
+ char *contenttype,
+ long flags,
+ struct curl_slist* contentHeader,
+ char *showfilename, char *userp,
+ struct curl_httppost *parent_post,
+ struct curl_httppost **httppost,
+ struct curl_httppost **last_post)
+{
+ struct curl_httppost *post;
+ post = calloc(1, sizeof(struct curl_httppost));
+ if(post) {
+ post->name = name;
+ post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
+ post->contents = value;
+ post->contentslength = (long)contentslength;
+ post->buffer = buffer;
+ post->bufferlength = (long)bufferlength;
+ post->contenttype = contenttype;
+ post->contentheader = contentHeader;
+ post->showfilename = showfilename;
+ post->userp = userp,
+ post->flags = flags;
+ }
+ else
+ return NULL;
+
+ if(parent_post) {
+ /* now, point our 'more' to the original 'more' */
+ post->more = parent_post->more;
+
+ /* then move the original 'more' to point to ourselves */
+ parent_post->more = post;
+ }
+ else {
+ /* make the previous point to this */
+ if(*last_post)
+ (*last_post)->next = post;
+ else
+ (*httppost) = post;
+
+ (*last_post) = post;
+ }
+ return post;
+}
+
+/***************************************************************************
+ *
+ * AddFormInfo()
+ *
+ * Adds a FormInfo structure to the list presented by parent_form_info.
+ *
+ * Returns newly allocated FormInfo on success and NULL if malloc failed/
+ * parent_form_info is NULL.
+ *
+ ***************************************************************************/
+static FormInfo * AddFormInfo(char *value,
+ char *contenttype,
+ FormInfo *parent_form_info)
+{
+ FormInfo *form_info;
+ form_info = calloc(1, sizeof(struct FormInfo));
+ if(form_info) {
+ if(value)
+ form_info->value = value;
+ if(contenttype)
+ form_info->contenttype = contenttype;
+ form_info->flags = HTTPPOST_FILENAME;
+ }
+ else
+ return NULL;
+
+ if(parent_form_info) {
+ /* now, point our 'more' to the original 'more' */
+ form_info->more = parent_form_info->more;
+
+ /* then move the original 'more' to point to ourselves */
+ parent_form_info->more = form_info;
+ }
+
+ return form_info;
+}
+
+/***************************************************************************
+ *
+ * ContentTypeForFilename()
+ *
+ * Provides content type for filename if one of the known types (else
+ * (either the prevtype or the default is returned).
+ *
+ * Returns some valid contenttype for filename.
+ *
+ ***************************************************************************/
+static const char *ContentTypeForFilename(const char *filename,
+ const char *prevtype)
+{
+ const char *contenttype = NULL;
+ unsigned int i;
+ /*
+ * No type was specified, we scan through a few well-known
+ * extensions and pick the first we match!
+ */
+ struct ContentType {
+ const char *extension;
+ const char *type;
+ };
+ static const struct ContentType ctts[]={
+ {".gif", "image/gif"},
+ {".jpg", "image/jpeg"},
+ {".jpeg", "image/jpeg"},
+ {".txt", "text/plain"},
+ {".html", "text/html"},
+ {".xml", "application/xml"}
+ };
+
+ if(prevtype)
+ /* default to the previously set/used! */
+ contenttype = prevtype;
+ else
+ contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
+
+ if(filename) { /* in case a NULL was passed in */
+ for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
+ if(strlen(filename) >= strlen(ctts[i].extension)) {
+ if(strequal(filename +
+ strlen(filename) - strlen(ctts[i].extension),
+ ctts[i].extension)) {
+ contenttype = ctts[i].type;
+ break;
+ }
+ }
+ }
+ }
+ /* we have a contenttype by now */
+ return contenttype;
+}
+
+/***************************************************************************
+ *
+ * memdup()
+ *
+ * Copies the 'source' data to a newly allocated buffer buffer (that is
+ * returned). Uses buffer_length if not null, else uses strlen to determine
+ * the length of the buffer to be copied
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+static char *memdup(const char *src, size_t buffer_length)
+{
+ size_t length;
+ bool add = FALSE;
+ char *buffer;
+
+ if(buffer_length)
+ length = buffer_length;
+ else if(src) {
+ length = strlen(src);
+ add = TRUE;
+ }
+ else
+ /* no length and a NULL src pointer! */
+ return strdup("");
+
+ buffer = malloc(length+add);
+ if(!buffer)
+ return NULL; /* fail */
+
+ memcpy(buffer, src, length);
+
+ /* if length unknown do null termination */
+ if(add)
+ buffer[length] = '\0';
+
+ return buffer;
+}
+
+/***************************************************************************
+ *
+ * FormAdd()
+ *
+ * Stores a formpost parameter and builds the appropriate linked list.
+ *
+ * Has two principal functionalities: using files and byte arrays as
+ * post parts. Byte arrays are either copied or just the pointer is stored
+ * (as the user requests) while for files only the filename and not the
+ * content is stored.
+ *
+ * While you may have only one byte array for each name, multiple filenames
+ * are allowed (and because of this feature CURLFORM_END is needed after
+ * using CURLFORM_FILE).
+ *
+ * Examples:
+ *
+ * Simple name/value pair with copied contents:
+ * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
+ *
+ * name/value pair where only the content pointer is remembered:
+ * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
+ * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
+ *
+ * storing a filename (CONTENTTYPE is optional!):
+ * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
+ * CURLFORM_END);
+ *
+ * storing multiple filenames:
+ * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
+ * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
+ *
+ * Returns:
+ * CURL_FORMADD_OK on success
+ * CURL_FORMADD_MEMORY if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
+ * CURL_FORMADD_NULL if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
+ * CURL_FORMADD_MEMORY if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
+ *
+ ***************************************************************************/
+
+static
+CURLFORMcode FormAdd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ va_list params)
+{
+ FormInfo *first_form, *current_form, *form = NULL;
+ CURLFORMcode return_value = CURL_FORMADD_OK;
+ const char *prevtype = NULL;
+ struct curl_httppost *post = NULL;
+ CURLformoption option;
+ struct curl_forms *forms = NULL;
+ char *array_value=NULL; /* value read from an array */
+
+ /* This is a state variable, that if TRUE means that we're parsing an
+ array that we got passed to us. If FALSE we're parsing the input
+ va_list arguments. */
+ bool array_state = FALSE;
+
+ /*
+ * We need to allocate the first struct to fill in.
+ */
+ first_form = calloc(1, sizeof(struct FormInfo));
+ if(!first_form)
+ return CURL_FORMADD_MEMORY;
+
+ current_form = first_form;
+
+ /*
+ * Loop through all the options set. Break if we have an error to report.
+ */
+ while(return_value == CURL_FORMADD_OK) {
+
+ /* first see if we have more parts of the array param */
+ if(array_state && forms) {
+ /* get the upcoming option from the given array */
+ option = forms->option;
+ array_value = (char *)forms->value;
+
+ forms++; /* advance this to next entry */
+ if(CURLFORM_END == option) {
+ /* end of array state */
+ array_state = FALSE;
+ continue;
+ }
+ }
+ else {
+ /* This is not array-state, get next option */
+ option = va_arg(params, CURLformoption);
+ if(CURLFORM_END == option)
+ break;
+ }
+
+ switch (option) {
+ case CURLFORM_ARRAY:
+ if(array_state)
+ /* we don't support an array from within an array */
+ return_value = CURL_FORMADD_ILLEGAL_ARRAY;
+ else {
+ forms = va_arg(params, struct curl_forms *);
+ if(forms)
+ array_state = TRUE;
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+
+ /*
+ * Set the Name property.
+ */
+ case CURLFORM_PTRNAME:
+#ifdef CURL_DOES_CONVERSIONS
+ /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
+ * the data in all cases so that we'll have safe memory for the eventual
+ * conversion.
+ */
+#else
+ current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
+#endif
+ case CURLFORM_COPYNAME:
+ if(current_form->name)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ char *name = array_state?
+ array_value:va_arg(params, char *);
+ if(name)
+ current_form->name = name; /* store for the moment */
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+ case CURLFORM_NAMELENGTH:
+ if(current_form->namelength)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else
+ current_form->namelength =
+ array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ break;
+
+ /*
+ * Set the contents property.
+ */
+ case CURLFORM_PTRCONTENTS:
+ current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
+ case CURLFORM_COPYCONTENTS:
+ if(current_form->value)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ char *value =
+ array_state?array_value:va_arg(params, char *);
+ if(value)
+ current_form->value = value; /* store for the moment */
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+ case CURLFORM_CONTENTSLENGTH:
+ if(current_form->contentslength)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else
+ current_form->contentslength =
+ array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ break;
+
+ /* Get contents from a given file name */
+ case CURLFORM_FILECONTENT:
+ if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ const char *filename = array_state?
+ array_value:va_arg(params, char *);
+ if(filename) {
+ current_form->value = strdup(filename);
+ if(!current_form->value)
+ return_value = CURL_FORMADD_MEMORY;
+ else {
+ current_form->flags |= HTTPPOST_READFILE;
+ current_form->value_alloc = TRUE;
+ }
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+
+ /* We upload a file */
+ case CURLFORM_FILE:
+ {
+ const char *filename = array_state?array_value:
+ va_arg(params, char *);
+
+ if(current_form->value) {
+ if(current_form->flags & HTTPPOST_FILENAME) {
+ if(filename) {
+ char *fname = strdup(filename);
+ if(!fname)
+ return_value = CURL_FORMADD_MEMORY;
+ else {
+ form = AddFormInfo(fname, NULL, current_form);
+ if(!form) {
+ Curl_safefree(fname);
+ return_value = CURL_FORMADD_MEMORY;
+ }
+ else {
+ form->value_alloc = TRUE;
+ current_form = form;
+ form = NULL;
+ }
+ }
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ else
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ }
+ else {
+ if(filename) {
+ current_form->value = strdup(filename);
+ if(!current_form->value)
+ return_value = CURL_FORMADD_MEMORY;
+ else {
+ current_form->flags |= HTTPPOST_FILENAME;
+ current_form->value_alloc = TRUE;
+ }
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+ }
+
+ case CURLFORM_BUFFERPTR:
+ current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
+ if(current_form->buffer)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ char *buffer =
+ array_state?array_value:va_arg(params, char *);
+ if(buffer) {
+ current_form->buffer = buffer; /* store for the moment */
+ current_form->value = buffer; /* make it non-NULL to be accepted
+ as fine */
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+
+ case CURLFORM_BUFFERLENGTH:
+ if(current_form->bufferlength)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else
+ current_form->bufferlength =
+ array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ break;
+
+ case CURLFORM_STREAM:
+ current_form->flags |= HTTPPOST_CALLBACK;
+ if(current_form->userp)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ char *userp =
+ array_state?array_value:va_arg(params, char *);
+ if(userp) {
+ current_form->userp = userp;
+ current_form->value = userp; /* this isn't strictly true but we
+ derive a value from this later on
+ and we need this non-NULL to be
+ accepted as a fine form part */
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+
+ case CURLFORM_CONTENTTYPE:
+ {
+ const char *contenttype =
+ array_state?array_value:va_arg(params, char *);
+ if(current_form->contenttype) {
+ if(current_form->flags & HTTPPOST_FILENAME) {
+ if(contenttype) {
+ char *type = strdup(contenttype);
+ if(!type)
+ return_value = CURL_FORMADD_MEMORY;
+ else {
+ form = AddFormInfo(NULL, type, current_form);
+ if(!form) {
+ Curl_safefree(type);
+ return_value = CURL_FORMADD_MEMORY;
+ }
+ else {
+ form->contenttype_alloc = TRUE;
+ current_form = form;
+ form = NULL;
+ }
+ }
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ else
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ }
+ else {
+ if(contenttype) {
+ current_form->contenttype = strdup(contenttype);
+ if(!current_form->contenttype)
+ return_value = CURL_FORMADD_MEMORY;
+ else
+ current_form->contenttype_alloc = TRUE;
+ }
+ else
+ return_value = CURL_FORMADD_NULL;
+ }
+ break;
+ }
+ case CURLFORM_CONTENTHEADER:
+ {
+ /* this "cast increases required alignment of target type" but
+ we consider it OK anyway */
+ struct curl_slist* list = array_state?
+ (struct curl_slist*)array_value:
+ va_arg(params, struct curl_slist*);
+
+ if(current_form->contentheader)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else
+ current_form->contentheader = list;
+
+ break;
+ }
+ case CURLFORM_FILENAME:
+ case CURLFORM_BUFFER:
+ {
+ const char *filename = array_state?array_value:
+ va_arg(params, char *);
+ if(current_form->showfilename)
+ return_value = CURL_FORMADD_OPTION_TWICE;
+ else {
+ current_form->showfilename = strdup(filename);
+ if(!current_form->showfilename)
+ return_value = CURL_FORMADD_MEMORY;
+ else
+ current_form->showfilename_alloc = TRUE;
+ }
+ break;
+ }
+ default:
+ return_value = CURL_FORMADD_UNKNOWN_OPTION;
+ break;
+ }
+ }
+
+ if(CURL_FORMADD_OK != return_value) {
+ /* On error, free allocated fields for all nodes of the FormInfo linked
+ list without deallocating nodes. List nodes are deallocated later on */
+ FormInfo *ptr;
+ for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
+ if(ptr->name_alloc) {
+ Curl_safefree(ptr->name);
+ ptr->name_alloc = FALSE;
+ }
+ if(ptr->value_alloc) {
+ Curl_safefree(ptr->value);
+ ptr->value_alloc = FALSE;
+ }
+ if(ptr->contenttype_alloc) {
+ Curl_safefree(ptr->contenttype);
+ ptr->contenttype_alloc = FALSE;
+ }
+ if(ptr->showfilename_alloc) {
+ Curl_safefree(ptr->showfilename);
+ ptr->showfilename_alloc = FALSE;
+ }
+ }
+ }
+
+ if(CURL_FORMADD_OK == return_value) {
+ /* go through the list, check for completeness and if everything is
+ * alright add the HttpPost item otherwise set return_value accordingly */
+
+ post = NULL;
+ for(form = first_form;
+ 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->buffer) &&
+ (form->flags & HTTPPOST_BUFFER) &&
+ (form->flags & HTTPPOST_PTRBUFFER) ) ||
+
+ ( (form->flags & HTTPPOST_READFILE) &&
+ (form->flags & HTTPPOST_PTRCONTENTS) )
+ ) {
+ return_value = CURL_FORMADD_INCOMPLETE;
+ break;
+ }
+ else {
+ if(((form->flags & HTTPPOST_FILENAME) ||
+ (form->flags & HTTPPOST_BUFFER)) &&
+ !form->contenttype ) {
+ char *f = form->flags & HTTPPOST_BUFFER?
+ form->showfilename : form->value;
+
+ /* our contenttype is missing */
+ form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
+ if(!form->contenttype) {
+ return_value = CURL_FORMADD_MEMORY;
+ break;
+ }
+ form->contenttype_alloc = TRUE;
+ }
+ if(!(form->flags & HTTPPOST_PTRNAME) &&
+ (form == first_form) ) {
+ /* Note that there's small risk that form->name is NULL here if the
+ app passed in a bad combo, so we better check for that first. */
+ if(form->name)
+ /* copy name (without strdup; possibly contains null characters) */
+ form->name = memdup(form->name, form->namelength);
+ if(!form->name) {
+ return_value = CURL_FORMADD_MEMORY;
+ break;
+ }
+ form->name_alloc = TRUE;
+ }
+ if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
+ HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
+ HTTPPOST_CALLBACK)) ) {
+ /* copy value (without strdup; possibly contains null characters) */
+ form->value = memdup(form->value, form->contentslength);
+ if(!form->value) {
+ return_value = CURL_FORMADD_MEMORY;
+ break;
+ }
+ form->value_alloc = TRUE;
+ }
+ post = AddHttpPost(form->name, form->namelength,
+ form->value, form->contentslength,
+ form->buffer, form->bufferlength,
+ form->contenttype, form->flags,
+ form->contentheader, form->showfilename,
+ form->userp,
+ post, httppost,
+ last_post);
+
+ if(!post) {
+ return_value = CURL_FORMADD_MEMORY;
+ break;
+ }
+
+ if(form->contenttype)
+ prevtype = form->contenttype;
+ }
+ }
+ if(CURL_FORMADD_OK != return_value) {
+ /* On error, free allocated fields for nodes of the FormInfo linked
+ list which are not already owned by the httppost linked list
+ without deallocating nodes. List nodes are deallocated later on */
+ FormInfo *ptr;
+ for(ptr = form; ptr != NULL; ptr = ptr->more) {
+ if(ptr->name_alloc) {
+ Curl_safefree(ptr->name);
+ ptr->name_alloc = FALSE;
+ }
+ if(ptr->value_alloc) {
+ Curl_safefree(ptr->value);
+ ptr->value_alloc = FALSE;
+ }
+ if(ptr->contenttype_alloc) {
+ Curl_safefree(ptr->contenttype);
+ ptr->contenttype_alloc = FALSE;
+ }
+ if(ptr->showfilename_alloc) {
+ Curl_safefree(ptr->showfilename);
+ ptr->showfilename_alloc = FALSE;
+ }
+ }
+ }
+ }
+
+ /* Always deallocate FormInfo linked list nodes without touching node
+ fields given that these have either been deallocated or are owned
+ now by the httppost linked list */
+ while(first_form) {
+ FormInfo *ptr = first_form->more;
+ Curl_safefree(first_form);
+ first_form = ptr;
+ }
+
+ return return_value;
+}
+
+/*
+ * curl_formadd() is a public API to add a section to the multipart formpost.
+ *
+ * @unittest: 1308
+ */
+
+CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...)
+{
+ va_list arg;
+ CURLFORMcode result;
+ va_start(arg, last_post);
+ result = FormAdd(httppost, last_post, arg);
+ va_end(arg);
+ return result;
+}
+
+#ifdef __VMS
+#include <fabdef.h>
+/*
+ * get_vms_file_size does what it takes to get the real size of the file
+ *
+ * For fixed files, find out the size of the EOF block and adjust.
+ *
+ * For all others, have to read the entire file in, discarding the contents.
+ * Most posted text files will be small, and binary files like zlib archives
+ * and CD/DVD images should be either a STREAM_LF format or a fixed format.
+ *
+ */
+curl_off_t VmsRealFileSize(const char * name,
+ const struct_stat * stat_buf)
+{
+ char buffer[8192];
+ curl_off_t count;
+ int ret_stat;
+ FILE * file;
+
+ file = fopen(name, "r");
+ if(file == NULL)
+ return 0;
+
+ count = 0;
+ ret_stat = 1;
+ while(ret_stat > 0) {
+ ret_stat = fread(buffer, 1, sizeof(buffer), file);
+ if(ret_stat != 0)
+ count += ret_stat;
+ }
+ fclose(file);
+
+ return count;
+}
+
+/*
+ *
+ * VmsSpecialSize checks to see if the stat st_size can be trusted and
+ * if not to call a routine to get the correct size.
+ *
+ */
+static curl_off_t VmsSpecialSize(const char * name,
+ const struct_stat * stat_buf)
+{
+ switch(stat_buf->st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ return VmsRealFileSize(name, stat_buf);
+ break;
+ default:
+ return stat_buf->st_size;
+ }
+}
+
+#endif
+
+#ifndef __VMS
+#define filesize(name, stat_data) (stat_data.st_size)
+#else
+ /* Getting the expected file size needs help on VMS */
+#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
+#endif
+
+/*
+ * AddFormData() adds a chunk of data to the FormData linked list.
+ *
+ * size is incremented by the chunk length, unless it is NULL
+ */
+static CURLcode AddFormData(struct FormData **formp,
+ enum formtype type,
+ const void *line,
+ size_t length,
+ curl_off_t *size)
+{
+ struct FormData *newform = malloc(sizeof(struct FormData));
+ if(!newform)
+ return CURLE_OUT_OF_MEMORY;
+ newform->next = NULL;
+
+ if(type <= FORM_CONTENT) {
+ /* we make it easier for plain strings: */
+ if(!length)
+ length = strlen((char *)line);
+
+ newform->line = malloc(length+1);
+ if(!newform->line) {
+ free(newform);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(newform->line, line, length);
+ newform->length = length;
+ newform->line[length]=0; /* zero terminate for easier debugging */
+ }
+ else
+ /* For callbacks and files we don't have any actual data so we just keep a
+ pointer to whatever this points to */
+ newform->line = (char *)line;
+
+ newform->type = type;
+
+ if(*formp) {
+ (*formp)->next = newform;
+ *formp = newform;
+ }
+ else
+ *formp = newform;
+
+ if(size) {
+ if(type != FORM_FILE)
+ /* for static content as well as callback data we add the size given
+ as input argument */
+ *size += length;
+ else {
+ /* Since this is a file to be uploaded here, add the size of the actual
+ file */
+ if(!strequal("-", newform->line)) {
+ struct_stat file;
+ if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
+ *size += filesize(newform->line, file);
+ else
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+ }
+ return CURLE_OK;
+}
+
+/*
+ * AddFormDataf() adds printf()-style formatted data to the formdata chain.
+ */
+
+static CURLcode AddFormDataf(struct FormData **formp,
+ curl_off_t *size,
+ const char *fmt, ...)
+{
+ char s[4096];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(s, sizeof(s), fmt, ap);
+ va_end(ap);
+
+ return AddFormData(formp, FORM_DATA, s, 0, size);
+}
+
+/*
+ * Curl_formclean() is used from http.c, this cleans a built FormData linked
+ * list
+ */
+void Curl_formclean(struct FormData **form_ptr)
+{
+ struct FormData *next, *form;
+
+ form = *form_ptr;
+ if(!form)
+ return;
+
+ do {
+ next=form->next; /* the following form line */
+ if(form->type <= FORM_CONTENT)
+ free(form->line); /* free the line */
+ free(form); /* free the struct */
+
+ } while((form = next) != NULL); /* continue */
+
+ *form_ptr = NULL;
+}
+
+/*
+ * curl_formget()
+ * Serialize a curl_httppost struct.
+ * Returns 0 on success.
+ *
+ * @unittest: 1308
+ */
+int curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append)
+{
+ CURLcode rc;
+ curl_off_t size;
+ struct FormData *data, *ptr;
+
+ rc = Curl_getformdata(NULL, &data, form, NULL, &size);
+ if(rc != CURLE_OK)
+ return (int)rc;
+
+ for(ptr = data; ptr; ptr = ptr->next) {
+ if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
+ char buffer[8192];
+ size_t nread;
+ struct Form temp;
+
+ Curl_FormInit(&temp, ptr);
+
+ do {
+ nread = readfromfile(&temp, buffer, sizeof(buffer));
+ if((nread == (size_t) -1) ||
+ (nread > sizeof(buffer)) ||
+ (nread != append(arg, buffer, nread))) {
+ if(temp.fp)
+ fclose(temp.fp);
+ Curl_formclean(&data);
+ return -1;
+ }
+ } while(nread);
+ }
+ else {
+ if(ptr->length != append(arg, ptr->line, ptr->length)) {
+ Curl_formclean(&data);
+ return -1;
+ }
+ }
+ }
+ Curl_formclean(&data);
+ return 0;
+}
+
+/*
+ * curl_formfree() is an external function to free up a whole form post
+ * chain
+ */
+void curl_formfree(struct curl_httppost *form)
+{
+ struct curl_httppost *next;
+
+ if(!form)
+ /* no form to free, just get out of this */
+ return;
+
+ do {
+ next=form->next; /* the following form line */
+
+ /* recurse to sub-contents */
+ if(form->more)
+ curl_formfree(form->more);
+
+ if(!(form->flags & HTTPPOST_PTRNAME) && form->name)
+ free(form->name); /* free the name */
+ if(!(form->flags &
+ (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) &&
+ form->contents)
+ free(form->contents); /* free the contents */
+ if(form->contenttype)
+ free(form->contenttype); /* free the content type */
+ if(form->showfilename)
+ free(form->showfilename); /* free the faked file name */
+ free(form); /* free the struct */
+
+ } while((form = next) != NULL); /* continue */
+}
+
+#ifndef HAVE_BASENAME
+/*
+ (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
+ Edition)
+
+ The basename() function shall take the pathname pointed to by path and
+ return a pointer to the final component of the pathname, deleting any
+ trailing '/' characters.
+
+ If the string pointed to by path consists entirely of the '/' character,
+ basename() shall return a pointer to the string "/". If the string pointed
+ to by path is exactly "//", it is implementation-defined whether '/' or "//"
+ is returned.
+
+ If path is a null pointer or points to an empty string, basename() shall
+ return a pointer to the string ".".
+
+ The basename() function may modify the string pointed to by path, and may
+ return a pointer to static storage that may then be overwritten by a
+ subsequent call to basename().
+
+ The basename() function need not be reentrant. A function that is not
+ required to be reentrant is not required to be thread-safe.
+
+*/
+static char *Curl_basename(char *path)
+{
+ /* Ignore all the details above for now and make a quick and simple
+ implementaion here */
+ char *s1;
+ char *s2;
+
+ s1=strrchr(path, '/');
+ s2=strrchr(path, '\\');
+
+ if(s1 && s2) {
+ path = (s1 > s2? s1 : s2)+1;
+ }
+ else if(s1)
+ path = s1 + 1;
+ else if(s2)
+ path = s2 + 1;
+
+ return path;
+}
+#endif
+
+static char *strippath(const char *fullfile)
+{
+ char *filename;
+ char *base;
+ filename = strdup(fullfile); /* duplicate since basename() may ruin the
+ buffer it works on */
+ if(!filename)
+ return NULL;
+ base = strdup(basename(filename));
+
+ free(filename); /* free temporary buffer */
+
+ return base; /* returns an allocated string or NULL ! */
+}
+
+static CURLcode formdata_add_filename(const struct curl_httppost *file,
+ struct FormData **form,
+ curl_off_t *size)
+{
+ CURLcode result = CURLE_OK;
+ char *filename = file->showfilename;
+ char *filebasename = NULL;
+ char *filename_escaped = NULL;
+
+ if(!filename) {
+ filebasename = strippath(file->contents);
+ if(!filebasename)
+ return CURLE_OUT_OF_MEMORY;
+ filename = filebasename;
+ }
+
+ if(strchr(filename, '\\') || strchr(filename, '"')) {
+ char *p0, *p1;
+
+ /* filename need be escaped */
+ filename_escaped = malloc(strlen(filename)*2+1);
+ if(!filename_escaped) {
+ Curl_safefree(filebasename);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ p0 = filename_escaped;
+ p1 = filename;
+ while(*p1) {
+ if(*p1 == '\\' || *p1 == '"')
+ *p0++ = '\\';
+ *p0++ = *p1++;
+ }
+ *p0 = '\0';
+ filename = filename_escaped;
+ }
+ result = AddFormDataf(form, size,
+ "; filename=\"%s\"",
+ filename);
+ Curl_safefree(filename_escaped);
+ Curl_safefree(filebasename);
+ return result;
+}
+
+/*
+ * Curl_getformdata() converts a linked list of "meta data" into a complete
+ * (possibly huge) multipart formdata. The input list is in 'post', while the
+ * output resulting linked lists gets stored in '*finalform'. *sizep will get
+ * the total size of the whole POST.
+ * A multipart/form_data content-type is built, unless a custom content-type
+ * is passed in 'custom_content_type'.
+ *
+ * This function will not do a failf() for the potential memory failures but
+ * should for all other errors it spots. Just note that this function MAY get
+ * a NULL pointer in the 'data' argument.
+ */
+
+CURLcode Curl_getformdata(struct SessionHandle *data,
+ struct FormData **finalform,
+ struct curl_httppost *post,
+ const char *custom_content_type,
+ curl_off_t *sizep)
+{
+ struct FormData *form = NULL;
+ struct FormData *firstform;
+ struct curl_httppost *file;
+ CURLcode result = CURLE_OK;
+
+ curl_off_t size = 0; /* support potentially ENORMOUS formposts */
+ char *boundary;
+ char *fileboundary = NULL;
+ struct curl_slist* curList;
+
+ *finalform = NULL; /* default form is empty */
+
+ if(!post)
+ return result; /* no input => no output! */
+
+ boundary = formboundary(data);
+ if(!boundary)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Make the first line of the output */
+ result = AddFormDataf(&form, NULL,
+ "%s; boundary=%s\r\n",
+ custom_content_type?custom_content_type:
+ "Content-Type: multipart/form-data",
+ boundary);
+
+ if(result) {
+ Curl_safefree(boundary);
+ return result;
+ }
+ /* we DO NOT include that line in the total size of the POST, since it'll be
+ part of the header! */
+
+ firstform = form;
+
+ do {
+
+ if(size) {
+ result = AddFormDataf(&form, &size, "\r\n");
+ if(result)
+ break;
+ }
+
+ /* boundary */
+ result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
+ if(result)
+ break;
+
+ /* Maybe later this should be disabled when a custom_content_type is
+ passed, since Content-Disposition is not meaningful for all multipart
+ types.
+ */
+ result = AddFormDataf(&form, &size,
+ "Content-Disposition: form-data; name=\"");
+ if(result)
+ break;
+
+ result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
+ &size);
+ if(result)
+ break;
+
+ result = AddFormDataf(&form, &size, "\"");
+ if(result)
+ break;
+
+ if(post->more) {
+ /* If used, this is a link to more file names, we must then do
+ the magic to include several files with the same field name */
+
+ Curl_safefree(fileboundary);
+ fileboundary = formboundary(data);
+ if(!fileboundary) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ result = AddFormDataf(&form, &size,
+ "\r\nContent-Type: multipart/mixed;"
+ " boundary=%s\r\n",
+ fileboundary);
+ if(result)
+ break;
+ }
+
+ file = post;
+
+ do {
+
+ /* If 'showfilename' is set, that is a faked name passed on to us
+ to use to in the formpost. If that is not set, the actually used
+ local file name should be added. */
+
+ if(post->more) {
+ /* if multiple-file */
+ result = AddFormDataf(&form, &size,
+ "\r\n--%s\r\nContent-Disposition: "
+ "attachment",
+ fileboundary);
+ if(result)
+ break;
+ result = formdata_add_filename(file, &form, &size);
+ if(result)
+ break;
+ }
+ else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
+ HTTPPOST_CALLBACK)) {
+ /* it should be noted that for the HTTPPOST_FILENAME and
+ HTTPPOST_CALLBACK cases the ->showfilename struct member is always
+ assigned at this point */
+ if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
+ result = formdata_add_filename(post, &form, &size);
+ }
+
+ if(result)
+ break;
+ }
+
+ if(file->contenttype) {
+ /* we have a specified type */
+ result = AddFormDataf(&form, &size,
+ "\r\nContent-Type: %s",
+ file->contenttype);
+ if(result)
+ break;
+ }
+
+ curList = file->contentheader;
+ while(curList) {
+ /* Process the additional headers specified for this form */
+ result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
+ if(result)
+ break;
+ curList = curList->next;
+ }
+ if(result)
+ break;
+
+ result = AddFormDataf(&form, &size, "\r\n\r\n");
+ if(result)
+ break;
+
+ if((post->flags & HTTPPOST_FILENAME) ||
+ (post->flags & HTTPPOST_READFILE)) {
+ /* we should include the contents from the specified file */
+ FILE *fileread;
+
+ fileread = strequal("-", file->contents)?
+ stdin:fopen(file->contents, "rb"); /* binary read for win32 */
+
+ /*
+ * VMS: This only allows for stream files on VMS. Stream files are
+ * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
+ * every record needs to have a \n appended & 1 added to SIZE
+ */
+
+ if(fileread) {
+ if(fileread != stdin) {
+ /* close the file */
+ fclose(fileread);
+ /* add the file name only - for later reading from this */
+ result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
+ }
+ else {
+ /* When uploading from stdin, we can't know the size of the file,
+ * thus must read the full file as before. We *could* use chunked
+ * transfer-encoding, but that only works for HTTP 1.1 and we
+ * can't be sure we work with such a server.
+ */
+ size_t nread;
+ char buffer[512];
+ while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
+ result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
+ if(result)
+ break;
+ }
+ }
+ }
+ else {
+ if(data)
+ failf(data, "couldn't open file \"%s\"", file->contents);
+ *finalform = NULL;
+ result = CURLE_READ_ERROR;
+ }
+ }
+ else if(post->flags & HTTPPOST_BUFFER)
+ /* include contents of buffer */
+ result = AddFormData(&form, FORM_CONTENT, post->buffer,
+ post->bufferlength, &size);
+ else if(post->flags & HTTPPOST_CALLBACK)
+ /* the contents should be read with the callback and the size
+ is set with the contentslength */
+ result = AddFormData(&form, FORM_CALLBACK, post->userp,
+ post->contentslength, &size);
+ else
+ /* include the contents we got */
+ result = AddFormData(&form, FORM_CONTENT, post->contents,
+ post->contentslength, &size);
+
+ file = file->more;
+ } while(file && !result); /* for each specified file for this field */
+
+ if(result)
+ break;
+
+ if(post->more) {
+ /* this was a multiple-file inclusion, make a termination file
+ boundary: */
+ result = AddFormDataf(&form, &size,
+ "\r\n--%s--",
+ fileboundary);
+ if(result)
+ break;
+ }
+
+ } while((post = post->next) != NULL); /* for each field */
+
+ /* end-boundary for everything */
+ if(CURLE_OK == result)
+ result = AddFormDataf(&form, &size,
+ "\r\n--%s--\r\n",
+ boundary);
+
+ if(result) {
+ Curl_formclean(&firstform);
+ Curl_safefree(fileboundary);
+ Curl_safefree(boundary);
+ return result;
+ }
+
+ *sizep = size;
+
+ Curl_safefree(fileboundary);
+ Curl_safefree(boundary);
+
+ *finalform = firstform;
+
+ return result;
+}
+
+/*
+ * Curl_FormInit() inits the struct 'form' points to with the 'formdata'
+ * and resets the 'sent' counter.
+ */
+int Curl_FormInit(struct Form *form, struct FormData *formdata )
+{
+ if(!formdata)
+ return 1; /* error */
+
+ form->data = formdata;
+ form->sent = 0;
+ form->fp = NULL;
+ form->fread_func = ZERO_NULL;
+
+ return 0;
+}
+
+#ifndef __VMS
+# define fopen_read fopen
+#else
+ /*
+ * vmsfopenread
+ *
+ * For upload to work as expected on VMS, different optional
+ * parameters must be added to the fopen command based on
+ * record format of the file.
+ *
+ */
+# define fopen_read vmsfopenread
+static FILE * vmsfopenread(const char *file, const char *mode) {
+ struct_stat statbuf;
+ int result;
+
+ result = stat(file, &statbuf);
+
+ switch (statbuf.st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ case FAB$C_STMCR:
+ return fopen(file, "r");
+ break;
+ default:
+ return fopen(file, "r", "rfm=stmlf", "ctx=stm");
+ }
+}
+#endif
+
+/*
+ * readfromfile()
+ *
+ * The read callback that this function may use can return a value larger than
+ * 'size' (which then this function returns) that indicates a problem and it
+ * must be properly dealt with
+ */
+static size_t readfromfile(struct Form *form, char *buffer,
+ size_t size)
+{
+ size_t nread;
+ bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
+
+ if(callback) {
+ if(form->fread_func == ZERO_NULL)
+ return 0;
+ else
+ nread = form->fread_func(buffer, 1, size, form->data->line);
+ }
+ else {
+ if(!form->fp) {
+ /* this file hasn't yet been opened */
+ form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
+ if(!form->fp)
+ return (size_t)-1; /* failure */
+ }
+ nread = fread(buffer, 1, size, form->fp);
+ }
+ if(!nread) {
+ /* this is the last chunk from the file, move on */
+ if(form->fp) {
+ fclose(form->fp);
+ form->fp = NULL;
+ }
+ form->data = form->data->next;
+ }
+
+ return nread;
+}
+
+/*
+ * Curl_FormReader() is the fread() emulation function that will be used to
+ * deliver the formdata to the transfer loop and then sent away to the peer.
+ */
+size_t Curl_FormReader(char *buffer,
+ size_t size,
+ size_t nitems,
+ FILE *mydata)
+{
+ struct Form *form;
+ size_t wantedsize;
+ size_t gotsize = 0;
+
+ form=(struct Form *)mydata;
+
+ wantedsize = size * nitems;
+
+ if(!form->data)
+ return 0; /* nothing, error, empty */
+
+ if((form->data->type == FORM_FILE) ||
+ (form->data->type == FORM_CALLBACK)) {
+ gotsize = readfromfile(form, buffer, wantedsize);
+
+ if(gotsize)
+ /* If positive or -1, return. If zero, continue! */
+ return gotsize;
+ }
+ do {
+
+ if((form->data->length - form->sent ) > wantedsize - gotsize) {
+
+ memcpy(buffer + gotsize , form->data->line + form->sent,
+ wantedsize - gotsize);
+
+ form->sent += wantedsize-gotsize;
+
+ return wantedsize;
+ }
+
+ memcpy(buffer+gotsize,
+ form->data->line + form->sent,
+ (form->data->length - form->sent) );
+ gotsize += form->data->length - form->sent;
+
+ form->sent = 0;
+
+ form->data = form->data->next; /* advance */
+
+ } while(form->data && (form->data->type < FORM_CALLBACK));
+ /* If we got an empty line and we have more data, we proceed to the next
+ line immediately to avoid returning zero before we've reached the end. */
+
+ return gotsize;
+}
+
+/*
+ * Curl_formpostheader() returns the first line of the formpost, the
+ * request-header part (which is not part of the request-body like the rest of
+ * the post).
+ */
+char *Curl_formpostheader(void *formp, size_t *len)
+{
+ char *header;
+ struct Form *form=(struct Form *)formp;
+
+ if(!form->data)
+ return 0; /* nothing, ERROR! */
+
+ header = form->data->line;
+ *len = form->data->length;
+
+ form->data = form->data->next; /* advance */
+
+ return header;
+}
+
+/*
+ * formboundary() creates a suitable boundary string and returns an allocated
+ * one.
+ */
+static char *formboundary(struct SessionHandle *data)
+{
+ /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
+ combinations */
+ return aprintf("------------------------%08x%08x",
+ Curl_rand(data), Curl_rand(data));
+}
+
+#else /* CURL_DISABLE_HTTP */
+CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...)
+{
+ (void)httppost;
+ (void)last_post;
+ return CURL_FORMADD_DISABLED;
+}
+
+int curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append)
+{
+ (void) form;
+ (void) arg;
+ (void) append;
+ return CURL_FORMADD_DISABLED;
+}
+
+void curl_formfree(struct curl_httppost *form)
+{
+ (void)form;
+ /* does nothing HTTP is disabled */
+}
+
+
+#endif /* !defined(CURL_DISABLE_HTTP) */
diff --git a/external/libcurl_android/jni/libcurl/lib/formdata.h b/external/libcurl_android/jni/libcurl/lib/formdata.h
new file mode 100755
index 00000000..22f504bb
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/formdata.h
@@ -0,0 +1,98 @@
+#ifndef HEADER_CURL_FORMDATA_H
+#define HEADER_CURL_FORMDATA_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+enum formtype {
+ FORM_DATA, /* form metadata (convert to network encoding if necessary) */
+ FORM_CONTENT, /* form content (never convert) */
+ FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback
+ */
+ FORM_FILE /* 'line' points to a file name we should read from
+ to create the form data (never convert) */
+};
+
+/* plain and simple linked list with lines to send */
+struct FormData {
+ struct FormData *next;
+ enum formtype type;
+ char *line;
+ size_t length;
+};
+
+struct Form {
+ struct FormData *data; /* current form line to send */
+ size_t sent; /* number of bytes of the current line that has
+ already been sent in a previous invoke */
+ FILE *fp; /* file to read from */
+ curl_read_callback fread_func; /* fread callback pointer */
+};
+
+/* used by FormAdd for temporary storage */
+typedef struct FormInfo {
+ char *name;
+ bool name_alloc;
+ size_t namelength;
+ char *value;
+ bool value_alloc;
+ size_t contentslength;
+ char *contenttype;
+ bool contenttype_alloc;
+ long flags;
+ char *buffer; /* pointer to existing buffer used for file upload */
+ size_t bufferlength;
+ char *showfilename; /* The file name to show. If not set, the actual
+ file name will be used */
+ bool showfilename_alloc;
+ char *userp; /* pointer for the read callback */
+ struct curl_slist* contentheader;
+ struct FormInfo *more;
+} FormInfo;
+
+int Curl_FormInit(struct Form *form, struct FormData *formdata );
+
+CURLcode Curl_getformdata(struct SessionHandle *data,
+ struct FormData **,
+ struct curl_httppost *post,
+ const char *custom_contenttype,
+ curl_off_t *size);
+
+/* fread() emulation */
+size_t Curl_FormReader(char *buffer,
+ size_t size,
+ size_t nitems,
+ FILE *mydata);
+
+/*
+ * Curl_formpostheader() returns the first line of the formpost, the
+ * request-header part (which is not part of the request-body like the rest of
+ * the post).
+ */
+char *Curl_formpostheader(void *formp, size_t *len);
+
+char *Curl_FormBoundary(void);
+
+void Curl_formclean(struct FormData **);
+
+CURLcode Curl_formconvert(struct SessionHandle *, struct FormData *);
+
+#endif /* HEADER_CURL_FORMDATA_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/ftp.c b/external/libcurl_android/jni/libcurl/lib/ftp.c
new file mode 100755
index 00000000..715afc2f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/ftp.c
@@ -0,0 +1,4585 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "if2ip.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "socks.h"
+#include "ftp.h"
+#include "fileinfo.h"
+#include "ftplistparser.h"
+#include "curl_sec.h"
+#include "strtoofft.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "inet_ntop.h"
+#include "inet_pton.h"
+#include "select.h"
+#include "parsedate.h" /* for the week day and month names */
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "speedcheck.h"
+#include "warnless.h"
+#include "http_proxy.h"
+#include "non-ascii.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN 16
+#endif
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt
+#endif
+
+/* Local API functions */
+#ifndef DEBUGBUILD
+static void _state(struct connectdata *conn,
+ ftpstate newstate);
+#define state(x,y) _state(x,y)
+#else
+static void _state(struct connectdata *conn,
+ ftpstate newstate,
+ int lineno);
+#define state(x,y) _state(x,y,__LINE__)
+#endif
+
+static CURLcode ftp_sendquote(struct connectdata *conn,
+ struct curl_slist *quote);
+static CURLcode ftp_quit(struct connectdata *conn);
+static CURLcode ftp_parse_url_path(struct connectdata *conn);
+static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void ftp_pasv_verbose(struct connectdata *conn,
+ Curl_addrinfo *ai,
+ char *newhost, /* ascii version */
+ int port);
+#endif
+static CURLcode ftp_state_prepare_transfer(struct connectdata *conn);
+static CURLcode ftp_state_mdtm(struct connectdata *conn);
+static CURLcode ftp_state_quote(struct connectdata *conn,
+ bool init, ftpstate instate);
+static CURLcode ftp_nb_type(struct connectdata *conn,
+ bool ascii, ftpstate newstate);
+static int ftp_need_type(struct connectdata *conn,
+ bool ascii);
+static CURLcode ftp_do(struct connectdata *conn, bool *done);
+static CURLcode ftp_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode ftp_connect(struct connectdata *conn, bool *done);
+static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
+static CURLcode ftp_do_more(struct connectdata *conn, int *completed);
+static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
+static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode ftp_doing(struct connectdata *conn,
+ bool *dophase_done);
+static CURLcode ftp_setup_connection(struct connectdata * conn);
+
+static CURLcode init_wc_data(struct connectdata *conn);
+static CURLcode wc_statemach(struct connectdata *conn);
+
+static void wc_data_dtor(void *ptr);
+
+static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize);
+
+static CURLcode ftp_readresp(curl_socket_t sockfd,
+ struct pingpong *pp,
+ int *ftpcode,
+ size_t *size);
+static CURLcode ftp_dophase_done(struct connectdata *conn,
+ bool connected);
+
+/* easy-to-use macro: */
+#define PPSENDF(x,y,z) if((result = Curl_pp_sendf(x,y,z)) != CURLE_OK) \
+ return result
+
+
+/*
+ * FTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ftp = {
+ "FTP", /* scheme */
+ ftp_setup_connection, /* setup_connection */
+ ftp_do, /* do_it */
+ ftp_done, /* done */
+ ftp_do_more, /* do_more */
+ ftp_connect, /* connect_it */
+ ftp_multi_statemach, /* connecting */
+ ftp_doing, /* doing */
+ ftp_getsock, /* proto_getsock */
+ ftp_getsock, /* doing_getsock */
+ ftp_domore_getsock, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ftp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_FTP, /* defport */
+ CURLPROTO_FTP, /* protocol */
+ PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD
+ | PROTOPT_NOURLQUERY /* flags */
+};
+
+
+#ifdef USE_SSL
+/*
+ * FTPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ftps = {
+ "FTPS", /* scheme */
+ ftp_setup_connection, /* setup_connection */
+ ftp_do, /* do_it */
+ ftp_done, /* done */
+ ftp_do_more, /* do_more */
+ ftp_connect, /* connect_it */
+ ftp_multi_statemach, /* connecting */
+ ftp_doing, /* doing */
+ ftp_getsock, /* proto_getsock */
+ ftp_getsock, /* doing_getsock */
+ ftp_domore_getsock, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ftp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_FTPS, /* defport */
+ CURLPROTO_FTPS, /* protocol */
+ PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
+ PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY /* flags */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed FTP protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_ftp_proxy = {
+ "FTP", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_FTP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+
+#ifdef USE_SSL
+/*
+ * HTTP-proxyed FTPS protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_ftps_proxy = {
+ "FTPS", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_FTPS, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+#endif
+#endif
+
+
+/*
+ * NOTE: back in the old days, we added code in the FTP code that made NOBODY
+ * requests on files respond with headers passed to the client/stdout that
+ * looked like HTTP ones.
+ *
+ * This approach is not very elegant, it causes confusion and is error-prone.
+ * It is subject for removal at the next (or at least a future) soname bump.
+ * Until then you can test the effects of the removal by undefining the
+ * following define named CURL_FTP_HTTPSTYLE_HEAD.
+ */
+#define CURL_FTP_HTTPSTYLE_HEAD 1
+
+static void freedirs(struct ftp_conn *ftpc)
+{
+ int i;
+ if(ftpc->dirs) {
+ for(i=0; i < ftpc->dirdepth; i++) {
+ if(ftpc->dirs[i]) {
+ free(ftpc->dirs[i]);
+ ftpc->dirs[i]=NULL;
+ }
+ }
+ free(ftpc->dirs);
+ ftpc->dirs = NULL;
+ ftpc->dirdepth = 0;
+ }
+ if(ftpc->file) {
+ free(ftpc->file);
+ ftpc->file = NULL;
+ }
+}
+
+/* Returns non-zero if the given string contains CR (\r) or LF (\n),
+ which are not allowed within RFC 959 <string>.
+ Note: The input string is in the client's encoding which might
+ not be ASCII, so escape sequences \r & \n must be used instead
+ of hex values 0x0d & 0x0a.
+*/
+static bool isBadFtpString(const char *string)
+{
+ return ((NULL != strchr(string, '\r')) ||
+ (NULL != strchr(string, '\n'))) ? TRUE : FALSE;
+}
+
+/***********************************************************************
+ *
+ * AcceptServerConnect()
+ *
+ * After connection request is received from the server this function is
+ * called to accept the connection and close the listening socket
+ *
+ */
+static CURLcode AcceptServerConnect(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sock = conn->sock[SECONDARYSOCKET];
+ curl_socket_t s = CURL_SOCKET_BAD;
+#ifdef ENABLE_IPV6
+ struct Curl_sockaddr_storage add;
+#else
+ struct sockaddr_in add;
+#endif
+ curl_socklen_t size = (curl_socklen_t) sizeof(add);
+
+ if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
+ size = sizeof(add);
+
+ s=accept(sock, (struct sockaddr *) &add, &size);
+ }
+ Curl_closesocket(conn, sock); /* close the first socket */
+
+ if(CURL_SOCKET_BAD == s) {
+ failf(data, "Error accept()ing server connect");
+ return CURLE_FTP_PORT_FAILED;
+ }
+ infof(data, "Connection accepted from server\n");
+
+ conn->sock[SECONDARYSOCKET] = s;
+ curlx_nonblock(s, TRUE); /* enable non-blocking */
+ conn->sock_accepted[SECONDARYSOCKET] = TRUE;
+
+ if(data->set.fsockopt) {
+ int error = 0;
+
+ /* activate callback for setting socket options */
+ error = data->set.fsockopt(data->set.sockopt_client,
+ s,
+ CURLSOCKTYPE_ACCEPT);
+
+ if(error) {
+ Curl_closesocket(conn, s); /* close the socket and bail out */
+ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+ }
+
+ return CURLE_OK;
+
+}
+
+/*
+ * ftp_timeleft_accept() returns the amount of milliseconds left allowed for
+ * waiting server to connect. If the value is negative, the timeout time has
+ * already elapsed.
+ *
+ * The start time is stored in progress.t_acceptdata - as set with
+ * Curl_pgrsTime(..., TIMER_STARTACCEPT);
+ *
+ */
+static long ftp_timeleft_accept(struct SessionHandle *data)
+{
+ long timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
+ long other;
+ struct timeval now;
+
+ if(data->set.accepttimeout > 0)
+ timeout_ms = data->set.accepttimeout;
+
+ now = Curl_tvnow();
+
+ /* check if the generic timeout possibly is set shorter */
+ other = Curl_timeleft(data, &now, FALSE);
+ if(other && (other < timeout_ms))
+ /* note that this also works fine for when other happens to be negative
+ due to it already having elapsed */
+ timeout_ms = other;
+ else {
+ /* subtract elapsed time */
+ timeout_ms -= Curl_tvdiff(now, data->progress.t_acceptdata);
+ if(!timeout_ms)
+ /* avoid returning 0 as that means no timeout! */
+ return -1;
+ }
+
+ return timeout_ms;
+}
+
+
+/***********************************************************************
+ *
+ * ReceivedServerConnect()
+ *
+ * After allowing server to connect to us from data port, this function
+ * checks both data connection for connection establishment and ctrl
+ * connection for a negative response regarding a failure in connecting
+ *
+ */
+static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
+ curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ int result;
+ long timeout_ms;
+ ssize_t nread;
+ int ftpcode;
+
+ *received = FALSE;
+
+ timeout_ms = ftp_timeleft_accept(data);
+ infof(data, "Checking for server connect\n");
+ if(timeout_ms < 0) {
+ /* if a timeout was already reached, bail out */
+ failf(data, "Accept timeout occurred while waiting server connect");
+ return CURLE_FTP_ACCEPT_TIMEOUT;
+ }
+
+ /* First check whether there is a cached response from server */
+ if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
+ /* Data connection could not be established, let's return */
+ infof(data, "There is negative response in cache while serv connect\n");
+ Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ return CURLE_FTP_ACCEPT_FAILED;
+ }
+
+ result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
+
+ /* see if the connection request is already here */
+ switch (result) {
+ case -1: /* error */
+ /* let's die here */
+ failf(data, "Error while waiting for server connect");
+ return CURLE_FTP_ACCEPT_FAILED;
+ case 0: /* Server connect is not received yet */
+ break; /* loop */
+ default:
+
+ if(result & CURL_CSELECT_IN2) {
+ infof(data, "Ready to accept data connection from server\n");
+ *received = TRUE;
+ }
+ else if(result & CURL_CSELECT_IN) {
+ infof(data, "Ctrl conn has data while waiting for data conn\n");
+ Curl_GetFTPResponse(&nread, conn, &ftpcode);
+
+ if(ftpcode/100 > 3)
+ return CURLE_FTP_ACCEPT_FAILED;
+
+ return CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+
+ break;
+ } /* switch() */
+
+ return CURLE_OK;
+}
+
+
+/***********************************************************************
+ *
+ * InitiateTransfer()
+ *
+ * After connection from server is accepted this function is called to
+ * setup transfer parameters and initiate the data transfer.
+ *
+ */
+static CURLcode InitiateTransfer(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ CURLcode result = CURLE_OK;
+
+ if(conn->ssl[SECONDARYSOCKET].use) {
+ /* since we only have a plaintext TCP connection here, we must now
+ * do the TLS stuff */
+ infof(data, "Doing the SSL/TLS handshake on the data stream\n");
+ result = Curl_ssl_connect(conn, SECONDARYSOCKET);
+ if(result)
+ return result;
+ }
+
+ if(conn->proto.ftpc.state_saved == FTP_STOR) {
+ *(ftp->bytecountp)=0;
+
+ /* When we know we're uploading a specified file, we can get the file
+ size prior to the actual upload. */
+
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+
+ /* set the SO_SNDBUF for the secondary socket for those who need it */
+ Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
+
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
+ SECONDARYSOCKET, ftp->bytecountp);
+ }
+ else {
+ /* FTP download: */
+ Curl_setup_transfer(conn, SECONDARYSOCKET,
+ conn->proto.ftpc.retr_size_saved, FALSE,
+ ftp->bytecountp, -1, NULL); /* no upload here */
+ }
+
+ conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
+ state(conn, FTP_STOP);
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * AllowServerConnect()
+ *
+ * When we've issue the PORT command, we have told the server to connect to
+ * us. This function checks whether data connection is established if so it is
+ * accepted.
+ *
+ */
+static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
+{
+ struct SessionHandle *data = conn->data;
+ long timeout_ms;
+ CURLcode ret = CURLE_OK;
+
+ *connected = FALSE;
+ infof(data, "Preparing for accepting server on data port\n");
+
+ /* Save the time we start accepting server connect */
+ Curl_pgrsTime(data, TIMER_STARTACCEPT);
+
+ timeout_ms = ftp_timeleft_accept(data);
+ if(timeout_ms < 0) {
+ /* if a timeout was already reached, bail out */
+ failf(data, "Accept timeout occurred while waiting server connect");
+ return CURLE_FTP_ACCEPT_TIMEOUT;
+ }
+
+ /* see if the connection request is already here */
+ ret = ReceivedServerConnect(conn, connected);
+ if(ret)
+ return ret;
+
+ if(*connected) {
+ ret = AcceptServerConnect(conn);
+ if(ret)
+ return ret;
+
+ ret = InitiateTransfer(conn);
+ if(ret)
+ return ret;
+ }
+ else {
+ /* Add timeout to multi handle and break out of the loop */
+ if(ret == CURLE_OK && *connected == FALSE) {
+ if(data->set.accepttimeout > 0)
+ Curl_expire(data, data->set.accepttimeout);
+ else
+ Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
+ }
+ }
+
+ return ret;
+}
+
+/* macro to check for a three-digit ftp status code at the start of the
+ given string */
+#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \
+ ISDIGIT(line[2]))
+
+/* macro to check for the last line in an FTP server response */
+#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
+
+static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len,
+ int *code)
+{
+ (void)conn;
+
+ if((len > 3) && LASTLINE(line)) {
+ *code = curlx_sltosi(strtol(line, NULL, 10));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static CURLcode ftp_readresp(curl_socket_t sockfd,
+ struct pingpong *pp,
+ int *ftpcode, /* return the ftp-code if done */
+ size_t *size) /* size of the response */
+{
+ struct connectdata *conn = pp->conn;
+ struct SessionHandle *data = conn->data;
+#ifdef HAVE_GSSAPI
+ char * const buf = data->state.buffer;
+#endif
+ CURLcode result = CURLE_OK;
+ int code;
+
+ result = Curl_pp_readresp(sockfd, pp, &code, size);
+
+#if defined(HAVE_GSSAPI)
+ /* handle the security-oriented responses 6xx ***/
+ /* FIXME: some errorchecking perhaps... ***/
+ switch(code) {
+ case 631:
+ code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
+ break;
+ case 632:
+ code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE);
+ break;
+ case 633:
+ code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL);
+ break;
+ default:
+ /* normal ftp stuff we pass through! */
+ break;
+ }
+#endif
+
+ /* store the latest code for later retrieval */
+ data->info.httpcode=code;
+
+ if(ftpcode)
+ *ftpcode = code;
+
+ if(421 == code) {
+ /* 421 means "Service not available, closing control connection." and FTP
+ * servers use it to signal that idle session timeout has been exceeded.
+ * If we ignored the response, it could end up hanging in some cases.
+ *
+ * This response code can come at any point so having it treated
+ * generically is a good idea.
+ */
+ infof(data, "We got a 421 - timeout!\n");
+ state(conn, FTP_STOP);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ return result;
+}
+
+/* --- parse FTP server responses --- */
+
+/*
+ * Curl_GetFTPResponse() is a BLOCKING function to read the full response
+ * from a server after a command.
+ *
+ */
+
+CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
+ struct connectdata *conn,
+ int *ftpcode) /* return the ftp-code */
+{
+ /*
+ * We cannot read just one byte per read() and then go back to select() as
+ * the OpenSSL read() doesn't grok that properly.
+ *
+ * Alas, read as much as possible, split up into lines, use the ending
+ * line in a response or continue reading. */
+
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+ long timeout; /* timeout in milliseconds */
+ long interval_ms;
+ struct SessionHandle *data = conn->data;
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ size_t nread;
+ int cache_skip=0;
+ int value_to_be_ignored=0;
+
+ if(ftpcode)
+ *ftpcode = 0; /* 0 for errors */
+ else
+ /* make the pointer point to something for the rest of this function */
+ ftpcode = &value_to_be_ignored;
+
+ *nreadp=0;
+
+ while(!*ftpcode && !result) {
+ /* check and reset timeout value every lap */
+ timeout = Curl_pp_state_timeout(pp);
+
+ if(timeout <=0 ) {
+ failf(data, "FTP response timeout");
+ return CURLE_OPERATION_TIMEDOUT; /* already too little time */
+ }
+
+ interval_ms = 1000; /* use 1 second timeout intervals */
+ if(timeout < interval_ms)
+ interval_ms = timeout;
+
+ /*
+ * Since this function is blocking, we need to wait here for input on the
+ * connection and only then we call the response reading function. We do
+ * timeout at least every second to make the timeout check run.
+ *
+ * A caution here is that the ftp_readresp() function has a cache that may
+ * contain pieces of a response from the previous invoke and we need to
+ * make sure we don't just wait for input while there is unhandled data in
+ * that cache. But also, if the cache is there, we call ftp_readresp() and
+ * the cache wasn't good enough to continue we must not just busy-loop
+ * around this function.
+ *
+ */
+
+ if(pp->cache && (cache_skip < 2)) {
+ /*
+ * There's a cache left since before. We then skipping the wait for
+ * socket action, unless this is the same cache like the previous round
+ * as then the cache was deemed not enough to act on and we then need to
+ * wait for more data anyway.
+ */
+ }
+ else {
+ switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) {
+ case -1: /* select() error, stop reading */
+ failf(data, "FTP response aborted due to select/poll error: %d",
+ SOCKERRNO);
+ return CURLE_RECV_ERROR;
+
+ case 0: /* timeout */
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ continue; /* just continue in our loop for the timeout duration */
+
+ default: /* for clarity */
+ break;
+ }
+ }
+ result = ftp_readresp(sockfd, pp, ftpcode, &nread);
+ if(result)
+ break;
+
+ if(!nread && pp->cache)
+ /* bump cache skip counter as on repeated skips we must wait for more
+ data */
+ cache_skip++;
+ else
+ /* when we got data or there is no cache left, we reset the cache skip
+ counter */
+ cache_skip=0;
+
+ *nreadp += nread;
+
+ } /* while there's buffer left and loop is requested */
+
+ pp->pending_resp = FALSE;
+
+ return result;
+}
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+static const char * const ftp_state_names[]={
+ "STOP",
+ "WAIT220",
+ "AUTH",
+ "USER",
+ "PASS",
+ "ACCT",
+ "PBSZ",
+ "PROT",
+ "CCC",
+ "PWD",
+ "SYST",
+ "NAMEFMT",
+ "QUOTE",
+ "RETR_PREQUOTE",
+ "STOR_PREQUOTE",
+ "POSTQUOTE",
+ "CWD",
+ "MKD",
+ "MDTM",
+ "TYPE",
+ "LIST_TYPE",
+ "RETR_TYPE",
+ "STOR_TYPE",
+ "SIZE",
+ "RETR_SIZE",
+ "STOR_SIZE",
+ "REST",
+ "RETR_REST",
+ "PORT",
+ "PRET",
+ "PASV",
+ "LIST",
+ "RETR",
+ "STOR",
+ "QUIT"
+};
+#endif
+
+/* This is the ONLY way to change FTP state! */
+static void _state(struct connectdata *conn,
+ ftpstate newstate
+#ifdef DEBUGBUILD
+ , int lineno
+#endif
+ )
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ if(ftpc->state != newstate)
+ infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
+ (void *)ftpc, lineno, ftp_state_names[ftpc->state],
+ ftp_state_names[newstate]);
+#endif
+ ftpc->state = newstate;
+}
+
+static CURLcode ftp_state_user(struct connectdata *conn)
+{
+ CURLcode result;
+ struct FTP *ftp = conn->data->req.protop;
+ /* send USER */
+ PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
+
+ state(conn, FTP_USER);
+ conn->data->state.ftp_trying_alternative = FALSE;
+
+ return CURLE_OK;
+}
+
+static CURLcode ftp_state_pwd(struct connectdata *conn)
+{
+ CURLcode result;
+
+ /* send PWD to discover our entry point */
+ PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD");
+ state(conn, FTP_PWD);
+
+ return CURLE_OK;
+}
+
+/* For the FTP "protocol connect" and "doing" phases only */
+static int ftp_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
+}
+
+/* For the FTP "DO_MORE" phase only */
+static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ /* When in DO_MORE state, we could be either waiting for us to connect to a
+ * remote site, or we could wait for that site to connect to us. Or just
+ * handle ordinary commands.
+ */
+
+ if(FTP_STOP == ftpc->state) {
+ int bits = GETSOCK_READSOCK(0);
+
+ /* if stopped and still in this state, then we're also waiting for a
+ connect on the secondary connection */
+ socks[0] = conn->sock[FIRSTSOCKET];
+
+ if(!conn->data->set.ftp_use_port) {
+ int s;
+ int i;
+ /* PORT is used to tell the server to connect to us, and during that we
+ don't do happy eyeballs, but we do if we connect to the server */
+ for(s=1, i=0; i<2; i++) {
+ if(conn->tempsock[i] != CURL_SOCKET_BAD) {
+ socks[s] = conn->tempsock[i];
+ bits |= GETSOCK_WRITESOCK(s++);
+ }
+ }
+ }
+ else {
+ socks[1] = conn->sock[SECONDARYSOCKET];
+ bits |= GETSOCK_WRITESOCK(1);
+ }
+
+ return bits;
+ }
+ else
+ return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
+}
+
+/* This is called after the FTP_QUOTE state is passed.
+
+ ftp_state_cwd() sends the range of CWD commands to the server to change to
+ the correct directory. It may also need to send MKD commands to create
+ missing ones, if that option is enabled.
+*/
+static CURLcode ftp_state_cwd(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(ftpc->cwddone)
+ /* already done and fine */
+ result = ftp_state_mdtm(conn);
+ else {
+ ftpc->count2 = 0; /* count2 counts failed CWDs */
+
+ /* count3 is set to allow a MKD to fail once. In the case when first CWD
+ fails and then MKD fails (due to another session raced it to create the
+ dir) this then allows for a second try to CWD to it */
+ ftpc->count3 = (conn->data->set.ftp_create_missing_dirs==2)?1:0;
+
+ if(conn->bits.reuse && ftpc->entrypath) {
+ /* This is a re-used connection. Since we change directory to where the
+ transfer is taking place, we must first get back to the original dir
+ where we ended up after login: */
+ ftpc->count1 = 0; /* we count this as the first path, then we add one
+ for all upcoming ones in the ftp->dirs[] array */
+ PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath);
+ state(conn, FTP_CWD);
+ }
+ else {
+ if(ftpc->dirdepth) {
+ ftpc->count1 = 1;
+ /* issue the first CWD, the rest is sent when the CWD responses are
+ received... */
+ PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->count1 -1]);
+ state(conn, FTP_CWD);
+ }
+ else {
+ /* No CWD necessary */
+ result = ftp_state_mdtm(conn);
+ }
+ }
+ }
+ return result;
+}
+
+typedef enum {
+ EPRT,
+ PORT,
+ DONE
+} ftpport;
+
+static CURLcode ftp_state_use_port(struct connectdata *conn,
+ ftpport fcmd) /* start with this */
+
+{
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct SessionHandle *data=conn->data;
+ curl_socket_t portsock= CURL_SOCKET_BAD;
+ char myhost[256] = "";
+
+ struct Curl_sockaddr_storage ss;
+ Curl_addrinfo *res, *ai;
+ curl_socklen_t sslen;
+ char hbuf[NI_MAXHOST];
+ struct sockaddr *sa=(struct sockaddr *)&ss;
+ struct sockaddr_in * const sa4 = (void *)sa;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 * const sa6 = (void *)sa;
+#endif
+ char tmp[1024];
+ static const char mode[][5] = { "EPRT", "PORT" };
+ int rc;
+ int error;
+ char *host = NULL;
+ char *string_ftpport = data->set.str[STRING_FTPPORT];
+ struct Curl_dns_entry *h=NULL;
+ unsigned short port_min = 0;
+ unsigned short port_max = 0;
+ unsigned short port;
+ bool possibly_non_local = TRUE;
+
+ char *addr = NULL;
+
+ /* Step 1, figure out what is requested,
+ * accepted format :
+ * (ipv4|ipv6|domain|interface)?(:port(-range)?)?
+ */
+
+ if(data->set.str[STRING_FTPPORT] &&
+ (strlen(data->set.str[STRING_FTPPORT]) > 1)) {
+
+#ifdef ENABLE_IPV6
+ size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ?
+ INET6_ADDRSTRLEN : strlen(string_ftpport);
+#else
+ size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ?
+ INET_ADDRSTRLEN : strlen(string_ftpport);
+#endif
+ char *ip_start = string_ftpport;
+ char *ip_end = NULL;
+ char *port_start = NULL;
+ char *port_sep = NULL;
+
+ addr = calloc(addrlen+1, 1);
+ if(!addr)
+ return CURLE_OUT_OF_MEMORY;
+
+#ifdef ENABLE_IPV6
+ if(*string_ftpport == '[') {
+ /* [ipv6]:port(-range) */
+ ip_start = string_ftpport + 1;
+ if((ip_end = strchr(string_ftpport, ']')) != NULL )
+ strncpy(addr, ip_start, ip_end - ip_start);
+ }
+ else
+#endif
+ if(*string_ftpport == ':') {
+ /* :port */
+ ip_end = string_ftpport;
+ }
+ else if((ip_end = strchr(string_ftpport, ':')) != NULL) {
+ /* either ipv6 or (ipv4|domain|interface):port(-range) */
+#ifdef ENABLE_IPV6
+ if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
+ /* ipv6 */
+ port_min = port_max = 0;
+ strcpy(addr, string_ftpport);
+ ip_end = NULL; /* this got no port ! */
+ }
+ else
+#endif
+ /* (ipv4|domain|interface):port(-range) */
+ strncpy(addr, string_ftpport, ip_end - ip_start );
+ }
+ else
+ /* ipv4|interface */
+ strcpy(addr, string_ftpport);
+
+ /* parse the port */
+ if(ip_end != NULL) {
+ if((port_start = strchr(ip_end, ':')) != NULL) {
+ port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
+ if((port_sep = strchr(port_start, '-')) != NULL) {
+ port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
+ }
+ else
+ port_max = port_min;
+ }
+ }
+
+ /* correct errors like:
+ * :1234-1230
+ * :-4711 , in this case port_min is (unsigned)-1,
+ * therefore port_min > port_max for all cases
+ * but port_max = (unsigned)-1
+ */
+ if(port_min > port_max )
+ port_min = port_max = 0;
+
+
+ if(*addr != '\0') {
+ /* attempt to get the address of the given interface name */
+ switch(Curl_if2ip(conn->ip_addr->ai_family, conn->scope, addr,
+ hbuf, sizeof(hbuf))) {
+ case IF2IP_NOT_FOUND:
+ /* not an interface, use the given string as host name instead */
+ host = addr;
+ break;
+ case IF2IP_AF_NOT_SUPPORTED:
+ return CURLE_FTP_PORT_FAILED;
+ case IF2IP_FOUND:
+ host = hbuf; /* use the hbuf for host name */
+ }
+ }
+ else
+ /* there was only a port(-range) given, default the host */
+ host = NULL;
+ } /* data->set.ftpport */
+
+ if(!host) {
+ /* not an interface and not a host name, get default by extracting
+ the IP from the control connection */
+
+ sslen = sizeof(ss);
+ if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
+ failf(data, "getsockname() failed: %s",
+ Curl_strerror(conn, SOCKERRNO) );
+ Curl_safefree(addr);
+ return CURLE_FTP_PORT_FAILED;
+ }
+ switch(sa->sa_family) {
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
+ break;
+#endif
+ default:
+ Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
+ break;
+ }
+ host = hbuf; /* use this host name */
+ possibly_non_local = FALSE; /* we know it is local now */
+ }
+
+ /* resolv ip/host to ip */
+ rc = Curl_resolv(conn, host, 0, &h);
+ if(rc == CURLRESOLV_PENDING)
+ (void)Curl_resolver_wait_resolv(conn, &h);
+ if(h) {
+ res = h->addr;
+ /* when we return from this function, we can forget about this entry
+ to we can unlock it now already */
+ Curl_resolv_unlock(data, h);
+ } /* (h) */
+ else
+ res = NULL; /* failure! */
+
+ if(res == NULL) {
+ failf(data, "failed to resolve the address provided to PORT: %s", host);
+ Curl_safefree(addr);
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ Curl_safefree(addr);
+ host = NULL;
+
+ /* step 2, create a socket for the requested address */
+
+ portsock = CURL_SOCKET_BAD;
+ error = 0;
+ for(ai = res; ai; ai = ai->ai_next) {
+ result = Curl_socket(conn, ai, NULL, &portsock);
+ if(result) {
+ error = SOCKERRNO;
+ continue;
+ }
+ break;
+ }
+ if(!ai) {
+ failf(data, "socket failure: %s", Curl_strerror(conn, error));
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ /* step 3, bind to a suitable local address */
+
+ memcpy(sa, ai->ai_addr, ai->ai_addrlen);
+ sslen = ai->ai_addrlen;
+
+ for(port = port_min; port <= port_max;) {
+ if(sa->sa_family == AF_INET)
+ sa4->sin_port = htons(port);
+#ifdef ENABLE_IPV6
+ else
+ sa6->sin6_port = htons(port);
+#endif
+ /* Try binding the given address. */
+ if(bind(portsock, sa, sslen) ) {
+ /* It failed. */
+ error = SOCKERRNO;
+ if(possibly_non_local && (error == EADDRNOTAVAIL)) {
+ /* The requested bind address is not local. Use the address used for
+ * the control connection instead and restart the port loop
+ */
+
+ infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
+ Curl_strerror(conn, error) );
+
+ sslen = sizeof(ss);
+ if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
+ failf(data, "getsockname() failed: %s",
+ Curl_strerror(conn, SOCKERRNO) );
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+ port = port_min;
+ possibly_non_local = FALSE; /* don't try this again */
+ continue;
+ }
+ else if(error != EADDRINUSE && error != EACCES) {
+ failf(data, "bind(port=%hu) failed: %s", port,
+ Curl_strerror(conn, error) );
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+ }
+ else
+ break;
+
+ port++;
+ }
+
+ /* maybe all ports were in use already*/
+ if(port > port_max) {
+ failf(data, "bind() failed, we ran out of ports!");
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ /* get the name again after the bind() so that we can extract the
+ port number it uses now */
+ sslen = sizeof(ss);
+ if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
+ failf(data, "getsockname() failed: %s",
+ Curl_strerror(conn, SOCKERRNO) );
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ /* step 4, listen on the socket */
+
+ if(listen(portsock, 1)) {
+ failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
+ Curl_closesocket(conn, portsock);
+ return CURLE_FTP_PORT_FAILED;
+ }
+
+ /* step 5, send the proper FTP command */
+
+ /* get a plain printable version of the numerical address to work with
+ below */
+ Curl_printable_address(ai, myhost, sizeof(myhost));
+
+#ifdef ENABLE_IPV6
+ if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
+ /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the
+ request and enable EPRT again! */
+ conn->bits.ftp_use_eprt = TRUE;
+#endif
+
+ for(; fcmd != DONE; fcmd++) {
+
+ if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
+ /* if disabled, goto next */
+ continue;
+
+ if((PORT == fcmd) && sa->sa_family != AF_INET)
+ /* PORT is ipv4 only */
+ continue;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ port = ntohs(sa4->sin_port);
+ break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ port = ntohs(sa6->sin6_port);
+ break;
+#endif
+ default:
+ continue; /* might as well skip this */
+ }
+
+ if(EPRT == fcmd) {
+ /*
+ * Two fine examples from RFC2428;
+ *
+ * EPRT |1|132.235.1.2|6275|
+ *
+ * EPRT |2|1080::8:800:200C:417A|5282|
+ */
+
+ result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
+ sa->sa_family == AF_INET?1:2,
+ myhost, port);
+ if(result) {
+ failf(data, "Failure sending EPRT command: %s",
+ curl_easy_strerror(result));
+ Curl_closesocket(conn, portsock);
+ /* don't retry using PORT */
+ ftpc->count1 = PORT;
+ /* bail out */
+ state(conn, FTP_STOP);
+ return result;
+ }
+ break;
+ }
+ else if(PORT == fcmd) {
+ char *source = myhost;
+ char *dest = tmp;
+
+ /* translate x.x.x.x to x,x,x,x */
+ while(source && *source) {
+ if(*source == '.')
+ *dest=',';
+ else
+ *dest = *source;
+ dest++;
+ source++;
+ }
+ *dest = 0;
+ snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
+
+ result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
+ if(result) {
+ failf(data, "Failure sending PORT command: %s",
+ curl_easy_strerror(result));
+ Curl_closesocket(conn, portsock);
+ /* bail out */
+ state(conn, FTP_STOP);
+ return result;
+ }
+ break;
+ }
+ }
+
+ /* store which command was sent */
+ ftpc->count1 = fcmd;
+
+ /* we set the secondary socket variable to this for now, it is only so that
+ the cleanup function will close it in case we fail before the true
+ secondary stuff is made */
+ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
+ Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ conn->sock[SECONDARYSOCKET] = portsock;
+
+ /* this tcpconnect assignment below is a hackish work-around to make the
+ multi interface with active FTP work - as it will not wait for a
+ (passive) connect in Curl_is_connected().
+
+ The *proper* fix is to make sure that the active connection from the
+ server is done in a non-blocking way. Currently, it is still BLOCKING.
+ */
+ conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
+
+ state(conn, FTP_PORT);
+ return result;
+}
+
+static CURLcode ftp_state_use_pasv(struct connectdata *conn)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result = CURLE_OK;
+ /*
+ Here's the excecutive summary on what to do:
+
+ PASV is RFC959, expect:
+ 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
+
+ LPSV is RFC1639, expect:
+ 228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)
+
+ EPSV is RFC2428, expect:
+ 229 Entering Extended Passive Mode (|||port|)
+
+ */
+
+ static const char mode[][5] = { "EPSV", "PASV" };
+ int modeoff;
+
+#ifdef PF_INET6
+ if(!conn->bits.ftp_use_epsv && conn->bits.ipv6)
+ /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the
+ request and enable EPSV again! */
+ conn->bits.ftp_use_epsv = TRUE;
+#endif
+
+ modeoff = conn->bits.ftp_use_epsv?0:1;
+
+ PPSENDF(&ftpc->pp, "%s", mode[modeoff]);
+
+ ftpc->count1 = modeoff;
+ state(conn, FTP_PASV);
+ infof(conn->data, "Connect data stream passively\n");
+
+ return result;
+}
+
+/*
+ * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc.
+ *
+ * REST is the last command in the chain of commands when a "head"-like
+ * request is made. Thus, if an actual transfer is to be made this is where we
+ * take off for real.
+ */
+static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct SessionHandle *data = conn->data;
+
+ if(ftp->transfer != FTPTRANSFER_BODY) {
+ /* doesn't transfer any data */
+
+ /* still possibly do PRE QUOTE jobs */
+ state(conn, FTP_RETR_PREQUOTE);
+ result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
+ }
+ else if(data->set.ftp_use_port) {
+ /* We have chosen to use the PORT (or similar) command */
+ result = ftp_state_use_port(conn, EPRT);
+ }
+ else {
+ /* We have chosen (this is default) to use the PASV (or similar) command */
+ if(data->set.ftp_use_pret) {
+ /* The user has requested that we send a PRET command
+ to prepare the server for the upcoming PASV */
+ if(!conn->proto.ftpc.file) {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET %s",
+ data->set.str[STRING_CUSTOMREQUEST]?
+ data->set.str[STRING_CUSTOMREQUEST]:
+ (data->set.ftp_list_only?"NLST":"LIST"));
+ }
+ else if(data->set.upload) {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file);
+ }
+ else {
+ PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file);
+ }
+ state(conn, FTP_PRET);
+ }
+ else {
+ result = ftp_state_use_pasv(conn);
+ }
+ }
+ return result;
+}
+
+static CURLcode ftp_state_rest(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
+ /* if a "head"-like request is being made (on a file) */
+
+ /* Determine if server can respond to REST command and therefore
+ whether it supports range */
+ PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0);
+
+ state(conn, FTP_REST);
+ }
+ else
+ result = ftp_state_prepare_transfer(conn);
+
+ return result;
+}
+
+static CURLcode ftp_state_size(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
+ /* if a "head"-like request is being made (on a file) */
+
+ /* we know ftpc->file is a valid pointer to a file name */
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
+
+ state(conn, FTP_SIZE);
+ }
+ else
+ result = ftp_state_rest(conn);
+
+ return result;
+}
+
+static CURLcode ftp_state_list(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ /* If this output is to be machine-parsed, the NLST command might be better
+ to use, since the LIST command output is not specified or standard in any
+ way. It has turned out that the NLST list output is not the same on all
+ servers either... */
+
+ /*
+ if FTPFILE_NOCWD was specified, we are currently in
+ the user's home directory, so we should add the path
+ as argument for the LIST / NLST / or custom command.
+ Whether the server will support this, is uncertain.
+
+ The other ftp_filemethods will CWD into dir/dir/ first and
+ then just do LIST (in that case: nothing to do here)
+ */
+ char *cmd,*lstArg,*slashPos;
+
+ lstArg = NULL;
+ if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
+ data->state.path &&
+ data->state.path[0] &&
+ strchr(data->state.path,'/')) {
+
+ lstArg = strdup(data->state.path);
+ if(!lstArg)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Check if path does not end with /, as then we cut off the file part */
+ if(lstArg[strlen(lstArg) - 1] != '/') {
+
+ /* chop off the file part if format is dir/dir/file */
+ slashPos = strrchr(lstArg,'/');
+ if(slashPos)
+ *(slashPos+1) = '\0';
+ }
+ }
+
+ cmd = aprintf( "%s%s%s",
+ data->set.str[STRING_CUSTOMREQUEST]?
+ data->set.str[STRING_CUSTOMREQUEST]:
+ (data->set.ftp_list_only?"NLST":"LIST"),
+ lstArg? " ": "",
+ lstArg? lstArg: "" );
+
+ if(!cmd) {
+ if(lstArg)
+ free(lstArg);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
+
+ if(lstArg)
+ free(lstArg);
+
+ free(cmd);
+
+ if(result != CURLE_OK)
+ return result;
+
+ state(conn, FTP_LIST);
+
+ return result;
+}
+
+static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* We've sent the TYPE, now we must send the list of prequote strings */
+
+ result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
+
+ return result;
+}
+
+static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* We've sent the TYPE, now we must send the list of prequote strings */
+
+ result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
+
+ return result;
+}
+
+static CURLcode ftp_state_type(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ /* If we have selected NOBODY and HEADER, it means that we only want file
+ information. Which in FTP can't be much more than the file size and
+ date. */
+ if(data->set.opt_no_body && ftpc->file &&
+ ftp_need_type(conn, data->set.prefer_ascii)) {
+ /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
+ may not support it! It is however the only way we have to get a file's
+ size! */
+
+ ftp->transfer = FTPTRANSFER_INFO;
+ /* this means no actual transfer will be made */
+
+ /* Some servers return different sizes for different modes, and thus we
+ must set the proper type before we check the size */
+ result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE);
+ if(result)
+ return result;
+ }
+ else
+ result = ftp_state_size(conn);
+
+ return result;
+}
+
+/* This is called after the CWD commands have been done in the beginning of
+ the DO phase */
+static CURLcode ftp_state_mdtm(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ /* Requested time of file or time-depended transfer? */
+ if((data->set.get_filetime || data->set.timecondition) && ftpc->file) {
+
+ /* we have requested to get the modified-time of the file, this is a white
+ spot as the MDTM is not mentioned in RFC959 */
+ PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file);
+
+ state(conn, FTP_MDTM);
+ }
+ else
+ result = ftp_state_type(conn);
+
+ return result;
+}
+
+
+/* This is called after the TYPE and possible quote commands have been sent */
+static CURLcode ftp_state_ul_setup(struct connectdata *conn,
+ bool sizechecked)
+{
+ CURLcode result = CURLE_OK;
+ struct FTP *ftp = conn->data->req.protop;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ int seekerr = CURL_SEEKFUNC_OK;
+
+ if((data->state.resume_from && !sizechecked) ||
+ ((data->state.resume_from > 0) && sizechecked)) {
+ /* we're about to continue the uploading of a file */
+ /* 1. get already existing file's size. We use the SIZE command for this
+ which may not exist in the server! The SIZE command is not in
+ RFC959. */
+
+ /* 2. This used to set REST. But since we can do append, we
+ don't another ftp command. We just skip the source file
+ offset and then we APPEND the rest on the file instead */
+
+ /* 3. pass file-size number of bytes in the source file */
+ /* 4. lower the infilesize counter */
+ /* => transfer as usual */
+
+ if(data->state.resume_from < 0 ) {
+ /* Got no given size to start from, figure it out */
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
+ state(conn, FTP_STOR_SIZE);
+ return result;
+ }
+
+ /* enable append */
+ data->set.ftp_append = TRUE;
+
+ /* Let's read off the proper amount of bytes from the input. */
+ if(conn->seek_func) {
+ seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+ SEEK_SET);
+ }
+
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+ do {
+ size_t readthisamountnow =
+ (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
+ BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ conn->fread_func(data->state.buffer, 1, readthisamountnow,
+ conn->fread_in);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Failed to read data");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ } while(passed < data->state.resume_from);
+ }
+ }
+ /* now, decrease the size of the read */
+ if(data->state.infilesize>0) {
+ data->state.infilesize -= data->state.resume_from;
+
+ if(data->state.infilesize <= 0) {
+ infof(data, "File already completely uploaded\n");
+
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ /* Set ->transfer so that we won't get any error in
+ * ftp_done() because we didn't transfer anything! */
+ ftp->transfer = FTPTRANSFER_NONE;
+
+ state(conn, FTP_STOP);
+ return CURLE_OK;
+ }
+ }
+ /* we've passed, proceed as normal */
+ } /* resume_from */
+
+ PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
+ ftpc->file);
+
+ state(conn, FTP_STOR);
+
+ return result;
+}
+
+static CURLcode ftp_state_quote(struct connectdata *conn,
+ bool init,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ bool quote=FALSE;
+ struct curl_slist *item;
+
+ switch(instate) {
+ case FTP_QUOTE:
+ default:
+ item = data->set.quote;
+ break;
+ case FTP_RETR_PREQUOTE:
+ case FTP_STOR_PREQUOTE:
+ item = data->set.prequote;
+ break;
+ case FTP_POSTQUOTE:
+ item = data->set.postquote;
+ break;
+ }
+
+ /*
+ * This state uses:
+ * 'count1' to iterate over the commands to send
+ * 'count2' to store wether to allow commands to fail
+ */
+
+ if(init)
+ ftpc->count1 = 0;
+ else
+ ftpc->count1++;
+
+ if(item) {
+ int i = 0;
+
+ /* Skip count1 items in the linked list */
+ while((i< ftpc->count1) && item) {
+ item = item->next;
+ i++;
+ }
+ if(item) {
+ char *cmd = item->data;
+ if(cmd[0] == '*') {
+ cmd++;
+ ftpc->count2 = 1; /* the sent command is allowed to fail */
+ }
+ else
+ ftpc->count2 = 0; /* failure means cancel operation */
+
+ PPSENDF(&ftpc->pp, "%s", cmd);
+ state(conn, instate);
+ quote = TRUE;
+ }
+ }
+
+ if(!quote) {
+ /* No more quote to send, continue to ... */
+ switch(instate) {
+ case FTP_QUOTE:
+ default:
+ result = ftp_state_cwd(conn);
+ break;
+ case FTP_RETR_PREQUOTE:
+ if(ftp->transfer != FTPTRANSFER_BODY)
+ state(conn, FTP_STOP);
+ else {
+ if(ftpc->known_filesize != -1) {
+ Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
+ result = ftp_state_retr(conn, ftpc->known_filesize);
+ }
+ else {
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
+ state(conn, FTP_RETR_SIZE);
+ }
+ }
+ break;
+ case FTP_STOR_PREQUOTE:
+ result = ftp_state_ul_setup(conn, FALSE);
+ break;
+ case FTP_POSTQUOTE:
+ break;
+ }
+ }
+
+ return result;
+}
+
+/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
+ problems */
+static CURLcode ftp_epsv_disable(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
+ /* disable it for next transfer */
+ conn->bits.ftp_use_epsv = FALSE;
+ conn->data->state.errorbuf = FALSE; /* allow error message to get
+ rewritten */
+ PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV");
+ conn->proto.ftpc.count1++;
+ /* remain in/go to the FTP_PASV state */
+ state(conn, FTP_PASV);
+ return result;
+}
+
+/*
+ * Perform the necessary magic that needs to be done once the TCP connection
+ * to the proxy has completed.
+ */
+static CURLcode proxy_magic(struct connectdata *conn,
+ char *newhost, unsigned short newport,
+ bool *magicdone)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+
+ *magicdone = FALSE;
+ switch(conn->proxytype) {
+ case CURLPROXY_SOCKS5:
+ case CURLPROXY_SOCKS5_HOSTNAME:
+ result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
+ newport, SECONDARYSOCKET, conn);
+ *magicdone = TRUE;
+ break;
+ case CURLPROXY_SOCKS4:
+ result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
+ SECONDARYSOCKET, conn, FALSE);
+ *magicdone = TRUE;
+ break;
+ case CURLPROXY_SOCKS4A:
+ result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
+ SECONDARYSOCKET, conn, TRUE);
+ *magicdone = TRUE;
+ break;
+ case CURLPROXY_HTTP:
+ case CURLPROXY_HTTP_1_0:
+ /* do nothing here. handled later. */
+ break;
+ default:
+ failf(data, "unknown proxytype option given");
+ result = CURLE_COULDNT_CONNECT;
+ break;
+ }
+
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
+ /* BLOCKING */
+ /* We want "seamless" FTP operations through HTTP proxy tunnel */
+
+ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
+ * member conn->proto.http; we want FTP through HTTP and we have to
+ * change the member temporarily for connecting to the HTTP proxy. After
+ * Curl_proxyCONNECT we have to set back the member to the original
+ * struct FTP pointer
+ */
+ struct HTTP http_proxy;
+ struct FTP *ftp_save = data->req.protop;
+ memset(&http_proxy, 0, sizeof(http_proxy));
+ data->req.protop = &http_proxy;
+
+ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
+
+ data->req.protop = ftp_save;
+
+ if(result)
+ return result;
+
+ if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
+ /* the CONNECT procedure is not complete, the tunnel is not yet up */
+ state(conn, FTP_STOP); /* this phase is completed */
+ return result;
+ }
+ else
+ *magicdone = TRUE;
+ }
+ return result;
+}
+
+static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
+ int ftpcode)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result;
+ struct SessionHandle *data=conn->data;
+ struct Curl_dns_entry *addr=NULL;
+ int rc;
+ unsigned short connectport; /* the local port connect() should use! */
+ char *str=&data->state.buffer[4]; /* start on the first letter */
+
+ if((ftpc->count1 == 0) &&
+ (ftpcode == 229)) {
+ /* positive EPSV response */
+ char *ptr = strchr(str, '(');
+ if(ptr) {
+ unsigned int num;
+ char separator[4];
+ ptr++;
+ if(5 == sscanf(ptr, "%c%c%c%u%c",
+ &separator[0],
+ &separator[1],
+ &separator[2],
+ &num,
+ &separator[3])) {
+ const char sep1 = separator[0];
+ int i;
+
+ /* The four separators should be identical, or else this is an oddly
+ formatted reply and we bail out immediately. */
+ for(i=1; i<4; i++) {
+ if(separator[i] != sep1) {
+ ptr=NULL; /* set to NULL to signal error */
+ break;
+ }
+ }
+ if(num > 0xffff) {
+ failf(data, "Illegal port number in EPSV reply");
+ return CURLE_FTP_WEIRD_PASV_REPLY;
+ }
+ if(ptr) {
+ ftpc->newport = (unsigned short)(num & 0xffff);
+
+ if(conn->bits.tunnel_proxy ||
+ conn->proxytype == CURLPROXY_SOCKS5 ||
+ conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+ conn->proxytype == CURLPROXY_SOCKS4 ||
+ conn->proxytype == CURLPROXY_SOCKS4A)
+ /* proxy tunnel -> use other host info because ip_addr_str is the
+ proxy address not the ftp host */
+ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
+ conn->host.name);
+ else
+ /* use the same IP we are already connected to */
+ snprintf(ftpc->newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str);
+ }
+ }
+ else
+ ptr=NULL;
+ }
+ if(!ptr) {
+ failf(data, "Weirdly formatted EPSV reply");
+ return CURLE_FTP_WEIRD_PASV_REPLY;
+ }
+ }
+ else if((ftpc->count1 == 1) &&
+ (ftpcode == 227)) {
+ /* positive PASV response */
+ int ip[4];
+ int port[2];
+
+ /*
+ * Scan for a sequence of six comma-separated numbers and use them as
+ * IP+port indicators.
+ *
+ * Found reply-strings include:
+ * "227 Entering Passive Mode (127,0,0,1,4,51)"
+ * "227 Data transfer will passively listen to 127,0,0,1,4,51"
+ * "227 Entering passive mode. 127,0,0,1,4,51"
+ */
+ while(*str) {
+ if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d",
+ &ip[0], &ip[1], &ip[2], &ip[3],
+ &port[0], &port[1]))
+ break;
+ str++;
+ }
+
+ if(!*str) {
+ failf(data, "Couldn't interpret the 227-response");
+ return CURLE_FTP_WEIRD_227_FORMAT;
+ }
+
+ /* we got OK from server */
+ if(data->set.ftp_skip_ip) {
+ /* told to ignore the remotely given IP but instead use the one we used
+ for the control connection */
+ infof(data, "Skips %d.%d.%d.%d for data connection, uses %s instead\n",
+ ip[0], ip[1], ip[2], ip[3],
+ conn->ip_addr_str);
+ if(conn->bits.tunnel_proxy ||
+ conn->proxytype == CURLPROXY_SOCKS5 ||
+ conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+ conn->proxytype == CURLPROXY_SOCKS4 ||
+ conn->proxytype == CURLPROXY_SOCKS4A)
+ /* proxy tunnel -> use other host info because ip_addr_str is the
+ proxy address not the ftp host */
+ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", conn->host.name);
+ else
+ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
+ conn->ip_addr_str);
+ }
+ else
+ snprintf(ftpc->newhost, sizeof(ftpc->newhost),
+ "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+ ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
+ }
+ else if(ftpc->count1 == 0) {
+ /* EPSV failed, move on to PASV */
+ return ftp_epsv_disable(conn);
+ }
+ else {
+ failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
+ return CURLE_FTP_WEIRD_PASV_REPLY;
+ }
+
+ if(conn->bits.proxy) {
+ /*
+ * This connection uses a proxy and we need to connect to the proxy again
+ * here. We don't want to rely on a former host lookup that might've
+ * expired now, instead we remake the lookup here and now!
+ */
+ rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
+ if(rc == CURLRESOLV_PENDING)
+ /* BLOCKING, ignores the return code but 'addr' will be NULL in
+ case of failure */
+ (void)Curl_resolver_wait_resolv(conn, &addr);
+
+ connectport =
+ (unsigned short)conn->port; /* we connect to the proxy's port */
+
+ if(!addr) {
+ failf(data, "Can't resolve proxy host %s:%hu",
+ conn->proxy.name, connectport);
+ return CURLE_FTP_CANT_GET_HOST;
+ }
+ }
+ else {
+ /* normal, direct, ftp connection */
+ rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
+ if(rc == CURLRESOLV_PENDING)
+ /* BLOCKING */
+ (void)Curl_resolver_wait_resolv(conn, &addr);
+
+ connectport = ftpc->newport; /* we connect to the remote port */
+
+ if(!addr) {
+ failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport);
+ return CURLE_FTP_CANT_GET_HOST;
+ }
+ }
+
+ conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
+ result = Curl_connecthost(conn, addr);
+
+ Curl_resolv_unlock(data, addr); /* we're done using this address */
+
+ if(result) {
+ if(ftpc->count1 == 0 && ftpcode == 229)
+ return ftp_epsv_disable(conn);
+
+ return result;
+ }
+
+
+ /*
+ * When this is used from the multi interface, this might've returned with
+ * the 'connected' set to FALSE and thus we are now awaiting a non-blocking
+ * connect to connect.
+ */
+
+ if(data->set.verbose)
+ /* this just dumps information about this second connection */
+ ftp_pasv_verbose(conn, conn->ip_addr, ftpc->newhost, connectport);
+
+ conn->bits.do_more = TRUE;
+ state(conn, FTP_STOP); /* this phase is completed */
+
+ return result;
+}
+
+static CURLcode ftp_state_port_resp(struct connectdata *conn,
+ int ftpcode)
+{
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ ftpport fcmd = (ftpport)ftpc->count1;
+ CURLcode result = CURLE_OK;
+
+ if(ftpcode != 200) {
+ /* the command failed */
+
+ if(EPRT == fcmd) {
+ infof(data, "disabling EPRT usage\n");
+ conn->bits.ftp_use_eprt = FALSE;
+ }
+ fcmd++;
+
+ if(fcmd == DONE) {
+ failf(data, "Failed to do PORT");
+ result = CURLE_FTP_PORT_FAILED;
+ }
+ else
+ /* try next */
+ result = ftp_state_use_port(conn, fcmd);
+ }
+ else {
+ infof(data, "Connect data stream actively\n");
+ state(conn, FTP_STOP); /* end of DO phase */
+ result = ftp_dophase_done(conn, FALSE);
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
+ int ftpcode)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ switch(ftpcode) {
+ case 213:
+ {
+ /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
+ last .sss part is optional and means fractions of a second */
+ int year, month, day, hour, minute, second;
+ char *buf = data->state.buffer;
+ if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d",
+ &year, &month, &day, &hour, &minute, &second)) {
+ /* we have a time, reformat it */
+ time_t secs=time(NULL);
+ /* using the good old yacc/bison yuck */
+ snprintf(buf, sizeof(conn->data->state.buffer),
+ "%04d%02d%02d %02d:%02d:%02d GMT",
+ year, month, day, hour, minute, second);
+ /* now, convert this into a time() value: */
+ data->info.filetime = (long)curl_getdate(buf, &secs);
+ }
+
+#ifdef CURL_FTP_HTTPSTYLE_HEAD
+ /* If we asked for a time of the file and we actually got one as well,
+ we "emulate" a HTTP-style header in our output. */
+
+ if(data->set.opt_no_body &&
+ ftpc->file &&
+ data->set.get_filetime &&
+ (data->info.filetime>=0) ) {
+ time_t filetime = (time_t)data->info.filetime;
+ struct tm buffer;
+ const struct tm *tm = &buffer;
+
+ result = Curl_gmtime(filetime, &buffer);
+ if(result)
+ return result;
+
+ /* format: "Tue, 15 Nov 1994 12:45:26" */
+ snprintf(buf, BUFSIZE-1,
+ "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ if(result)
+ return result;
+ } /* end of a ridiculous amount of conditionals */
+#endif
+ }
+ break;
+ default:
+ infof(data, "unsupported MDTM reply format\n");
+ break;
+ case 550: /* "No such file or directory" */
+ failf(data, "Given file does not exist");
+ result = CURLE_FTP_COULDNT_RETR_FILE;
+ break;
+ }
+
+ if(data->set.timecondition) {
+ if((data->info.filetime > 0) && (data->set.timevalue > 0)) {
+ switch(data->set.timecondition) {
+ case CURL_TIMECOND_IFMODSINCE:
+ default:
+ if(data->info.filetime <= data->set.timevalue) {
+ infof(data, "The requested document is not new enough\n");
+ ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
+ data->info.timecond = TRUE;
+ state(conn, FTP_STOP);
+ return CURLE_OK;
+ }
+ break;
+ case CURL_TIMECOND_IFUNMODSINCE:
+ if(data->info.filetime > data->set.timevalue) {
+ infof(data, "The requested document is not old enough\n");
+ ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
+ data->info.timecond = TRUE;
+ state(conn, FTP_STOP);
+ return CURLE_OK;
+ }
+ break;
+ } /* switch */
+ }
+ else {
+ infof(data, "Skipping time comparison\n");
+ }
+ }
+
+ if(!result)
+ result = ftp_state_type(conn);
+
+ return result;
+}
+
+static CURLcode ftp_state_type_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+
+ if(ftpcode/100 != 2) {
+ /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
+ successful 'TYPE I'. While that is not as RFC959 says, it is still a
+ positive response code and we allow that. */
+ failf(data, "Couldn't set desired mode");
+ return CURLE_FTP_COULDNT_SET_TYPE;
+ }
+ if(ftpcode != 200)
+ infof(data, "Got a %03d response code instead of the assumed 200\n",
+ ftpcode);
+
+ if(instate == FTP_TYPE)
+ result = ftp_state_size(conn);
+ else if(instate == FTP_LIST_TYPE)
+ result = ftp_state_list(conn);
+ else if(instate == FTP_RETR_TYPE)
+ result = ftp_state_retr_prequote(conn);
+ else if(instate == FTP_STOR_TYPE)
+ result = ftp_state_stor_prequote(conn);
+
+ return result;
+}
+
+static CURLcode ftp_state_retr(struct connectdata *conn,
+ curl_off_t filesize)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+ ftp->downloadsize = filesize;
+
+ if(data->state.resume_from) {
+ /* We always (attempt to) get the size of downloads, so it is done before
+ this even when not doing resumes. */
+ if(filesize == -1) {
+ infof(data, "ftp server doesn't support SIZE\n");
+ /* We couldn't get the size and therefore we can't know if there really
+ is a part of the file left to get, although the server will just
+ close the connection when we start the connection so it won't cause
+ us any harm, just not make us exit as nicely. */
+ }
+ else {
+ /* We got a file size report, so we check that there actually is a
+ part of the file left to get, or else we go home. */
+ if(data->state.resume_from< 0) {
+ /* We're supposed to download the last abs(from) bytes */
+ if(filesize < -data->state.resume_from) {
+ failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
+ ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
+ data->state.resume_from, filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ /* convert to size to download */
+ ftp->downloadsize = -data->state.resume_from;
+ /* download from where? */
+ data->state.resume_from = filesize - ftp->downloadsize;
+ }
+ else {
+ if(filesize < data->state.resume_from) {
+ failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
+ ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
+ data->state.resume_from, filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ /* Now store the number of bytes we are expected to download */
+ ftp->downloadsize = filesize-data->state.resume_from;
+ }
+ }
+
+ if(ftp->downloadsize == 0) {
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ infof(data, "File already completely downloaded\n");
+
+ /* Set ->transfer so that we won't get any error in ftp_done()
+ * because we didn't transfer the any file */
+ ftp->transfer = FTPTRANSFER_NONE;
+ state(conn, FTP_STOP);
+ return CURLE_OK;
+ }
+
+ /* Set resume file transfer offset */
+ infof(data, "Instructs server to resume from offset %"
+ CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
+
+ PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
+ data->state.resume_from);
+
+ state(conn, FTP_RETR_REST);
+ }
+ else {
+ /* no resume */
+ PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
+ state(conn, FTP_RETR);
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_size_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ curl_off_t filesize;
+ char *buf = data->state.buffer;
+
+ /* get the size from the ascii string: */
+ filesize = (ftpcode == 213)?curlx_strtoofft(buf+4, NULL, 0):-1;
+
+ if(instate == FTP_SIZE) {
+#ifdef CURL_FTP_HTTPSTYLE_HEAD
+ if(-1 != filesize) {
+ snprintf(buf, sizeof(data->state.buffer),
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ if(result)
+ return result;
+ }
+#endif
+ Curl_pgrsSetDownloadSize(data, filesize);
+ result = ftp_state_rest(conn);
+ }
+ else if(instate == FTP_RETR_SIZE) {
+ Curl_pgrsSetDownloadSize(data, filesize);
+ result = ftp_state_retr(conn, filesize);
+ }
+ else if(instate == FTP_STOR_SIZE) {
+ data->state.resume_from = filesize;
+ result = ftp_state_ul_setup(conn, TRUE);
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_rest_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ switch(instate) {
+ case FTP_REST:
+ default:
+#ifdef CURL_FTP_HTTPSTYLE_HEAD
+ if(ftpcode == 350) {
+ char buffer[24]= { "Accept-ranges: bytes\r\n" };
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0);
+ if(result)
+ return result;
+ }
+#endif
+ result = ftp_state_prepare_transfer(conn);
+ break;
+
+ case FTP_RETR_REST:
+ if(ftpcode != 350) {
+ failf(conn->data, "Couldn't use REST");
+ result = CURLE_FTP_COULDNT_USE_REST;
+ }
+ else {
+ PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
+ state(conn, FTP_RETR);
+ }
+ break;
+ }
+
+ return result;
+}
+
+static CURLcode ftp_state_stor_resp(struct connectdata *conn,
+ int ftpcode, ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ if(ftpcode>=400) {
+ failf(data, "Failed FTP upload: %0d", ftpcode);
+ state(conn, FTP_STOP);
+ /* oops, we never close the sockets! */
+ return CURLE_UPLOAD_FAILED;
+ }
+
+ conn->proto.ftpc.state_saved = instate;
+
+ /* PORT means we are now awaiting the server to connect to us. */
+ if(data->set.ftp_use_port) {
+ bool connected;
+
+ state(conn, FTP_STOP); /* no longer in STOR state */
+
+ result = AllowServerConnect(conn, &connected);
+ if(result)
+ return result;
+
+ if(!connected) {
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ infof(data, "Data conn was not available immediately\n");
+ ftpc->wait_data_conn = TRUE;
+ }
+
+ return CURLE_OK;
+ }
+ else
+ return InitiateTransfer(conn);
+}
+
+/* for LIST and RETR responses */
+static CURLcode ftp_state_get_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ char *buf = data->state.buffer;
+
+ if((ftpcode == 150) || (ftpcode == 125)) {
+
+ /*
+ A;
+ 150 Opening BINARY mode data connection for /etc/passwd (2241
+ bytes). (ok, the file is being transferred)
+
+ B:
+ 150 Opening ASCII mode data connection for /bin/ls
+
+ C:
+ 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes).
+
+ D:
+ 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes)
+
+ E:
+ 125 Data connection already open; Transfer starting. */
+
+ curl_off_t size=-1; /* default unknown size */
+
+
+ /*
+ * It appears that there are FTP-servers that return size 0 for files when
+ * SIZE is used on the file while being in BINARY mode. To work around
+ * that (stupid) behavior, we attempt to parse the RETR response even if
+ * the SIZE returned size zero.
+ *
+ * Debugging help from Salvatore Sorrentino on February 26, 2003.
+ */
+
+ if((instate != FTP_LIST) &&
+ !data->set.prefer_ascii &&
+ (ftp->downloadsize < 1)) {
+ /*
+ * It seems directory listings either don't show the size or very
+ * often uses size 0 anyway. ASCII transfers may very well turn out
+ * that the transferred amount of data is not the same as this line
+ * tells, why using this number in those cases only confuses us.
+ *
+ * Example D above makes this parsing a little tricky */
+ char *bytes;
+ bytes=strstr(buf, " bytes");
+ if(bytes--) {
+ long in=(long)(bytes-buf);
+ /* this is a hint there is size information in there! ;-) */
+ while(--in) {
+ /* scan for the left parenthesis and break there */
+ if('(' == *bytes)
+ break;
+ /* skip only digits */
+ if(!ISDIGIT(*bytes)) {
+ bytes=NULL;
+ break;
+ }
+ /* one more estep backwards */
+ bytes--;
+ }
+ /* if we have nothing but digits: */
+ if(bytes++) {
+ /* get the number! */
+ size = curlx_strtoofft(bytes, NULL, 0);
+ }
+ }
+ }
+ else if(ftp->downloadsize > -1)
+ size = ftp->downloadsize;
+
+ if(size > data->req.maxdownload && data->req.maxdownload > 0)
+ size = data->req.size = data->req.maxdownload;
+ else if((instate != FTP_LIST) && (data->set.prefer_ascii))
+ size = -1; /* kludge for servers that understate ASCII mode file size */
+
+ infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n",
+ data->req.maxdownload);
+
+ if(instate != FTP_LIST)
+ infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n",
+ size);
+
+ /* FTP download: */
+ conn->proto.ftpc.state_saved = instate;
+ conn->proto.ftpc.retr_size_saved = size;
+
+ if(data->set.ftp_use_port) {
+ bool connected;
+
+ result = AllowServerConnect(conn, &connected);
+ if(result)
+ return result;
+
+ if(!connected) {
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ infof(data, "Data conn was not available immediately\n");
+ state(conn, FTP_STOP);
+ ftpc->wait_data_conn = TRUE;
+ }
+ }
+ else
+ return InitiateTransfer(conn);
+ }
+ else {
+ if((instate == FTP_LIST) && (ftpcode == 450)) {
+ /* simply no matching files in the dir listing */
+ ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
+ state(conn, FTP_STOP); /* this phase is over */
+ }
+ else {
+ failf(data, "RETR response: %03d", ftpcode);
+ return instate == FTP_RETR && ftpcode == 550?
+ CURLE_REMOTE_FILE_NOT_FOUND:
+ CURLE_FTP_COULDNT_RETR_FILE;
+ }
+ }
+
+ return result;
+}
+
+/* after USER, PASS and ACCT */
+static CURLcode ftp_state_loggedin(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ if(conn->ssl[FIRSTSOCKET].use) {
+ /* PBSZ = PROTECTION BUFFER SIZE.
+
+ The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
+
+ Specifically, the PROT command MUST be preceded by a PBSZ
+ command and a PBSZ command MUST be preceded by a successful
+ security data exchange (the TLS negotiation in this case)
+
+ ... (and on page 8):
+
+ Thus the PBSZ command must still be issued, but must have a
+ parameter of '0' to indicate that no buffering is taking place
+ and the data connection should not be encapsulated.
+ */
+ PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0);
+ state(conn, FTP_PBSZ);
+ }
+ else {
+ result = ftp_state_pwd(conn);
+ }
+ return result;
+}
+
+/* for USER and PASS responses */
+static CURLcode ftp_state_user_resp(struct connectdata *conn,
+ int ftpcode,
+ ftpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ (void)instate; /* no use for this yet */
+
+ /* some need password anyway, and others just return 2xx ignored */
+ if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
+ /* 331 Password required for ...
+ (the server requires to send the user's password too) */
+ PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:"");
+ state(conn, FTP_PASS);
+ }
+ else if(ftpcode/100 == 2) {
+ /* 230 User ... logged in.
+ (the user logged in with or without password) */
+ result = ftp_state_loggedin(conn);
+ }
+ else if(ftpcode == 332) {
+ if(data->set.str[STRING_FTP_ACCOUNT]) {
+ PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
+ state(conn, FTP_ACCT);
+ }
+ else {
+ failf(data, "ACCT requested but none available");
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+ else {
+ /* All other response codes, like:
+
+ 530 User ... access denied
+ (the server denies to log the specified user) */
+
+ if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
+ !conn->data->state.ftp_trying_alternative) {
+ /* Ok, USER failed. Let's try the supplied command. */
+ PPSENDF(&conn->proto.ftpc.pp, "%s",
+ conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
+ conn->data->state.ftp_trying_alternative = TRUE;
+ state(conn, FTP_USER);
+ result = CURLE_OK;
+ }
+ else {
+ failf(data, "Access denied: %03d", ftpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+ return result;
+}
+
+/* for ACCT response */
+static CURLcode ftp_state_acct_resp(struct connectdata *conn,
+ int ftpcode)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ if(ftpcode != 230) {
+ failf(data, "ACCT rejected by server: %03d", ftpcode);
+ result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
+ }
+ else
+ result = ftp_state_loggedin(conn);
+
+ return result;
+}
+
+
+static CURLcode ftp_statemach_act(struct connectdata *conn)
+{
+ CURLcode result;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ struct SessionHandle *data=conn->data;
+ int ftpcode;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ static const char ftpauth[][4] = { "SSL", "TLS" };
+ size_t nread = 0;
+
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
+
+ result = ftp_readresp(sock, pp, &ftpcode, &nread);
+ if(result)
+ return result;
+
+ if(ftpcode) {
+ /* we have now received a full FTP server response */
+ switch(ftpc->state) {
+ case FTP_WAIT220:
+ if(ftpcode == 230)
+ /* 230 User logged in - already! */
+ return ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ else if(ftpcode != 220) {
+ failf(data, "Got a %03d ftp-server response when 220 was expected",
+ ftpcode);
+ return CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+
+ /* We have received a 220 response fine, now we proceed. */
+#ifdef HAVE_GSSAPI
+ if(data->set.krb) {
+ /* If not anonymous login, try a secure login. Note that this
+ procedure is still BLOCKING. */
+
+ Curl_sec_request_prot(conn, "private");
+ /* We set private first as default, in case the line below fails to
+ set a valid level */
+ Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
+
+ if(Curl_sec_login(conn) != CURLE_OK)
+ infof(data, "Logging in with password in cleartext!\n");
+ else
+ infof(data, "Authentication successful\n");
+ }
+#endif
+
+ if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* We don't have a SSL/TLS connection yet, but FTPS is
+ requested. Try a FTPS connection now */
+
+ ftpc->count3=0;
+ switch(data->set.ftpsslauth) {
+ case CURLFTPAUTH_DEFAULT:
+ case CURLFTPAUTH_SSL:
+ ftpc->count2 = 1; /* add one to get next */
+ ftpc->count1 = 0;
+ break;
+ case CURLFTPAUTH_TLS:
+ ftpc->count2 = -1; /* subtract one to get next */
+ ftpc->count1 = 1;
+ break;
+ default:
+ failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d",
+ (int)data->set.ftpsslauth);
+ return CURLE_UNKNOWN_OPTION; /* we don't know what to do */
+ }
+ PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
+ state(conn, FTP_AUTH);
+ }
+ else {
+ result = ftp_state_user(conn);
+ if(result)
+ return result;
+ }
+
+ break;
+
+ case FTP_AUTH:
+ /* we have gotten the response to a previous AUTH command */
+
+ /* RFC2228 (page 5) says:
+ *
+ * If the server is willing to accept the named security mechanism,
+ * and does not require any security data, it must respond with
+ * reply code 234/334.
+ */
+
+ if((ftpcode == 234) || (ftpcode == 334)) {
+ /* Curl_ssl_connect is BLOCKING */
+ result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ if(CURLE_OK == result) {
+ conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
+ result = ftp_state_user(conn);
+ }
+ }
+ else if(ftpc->count3 < 1) {
+ ftpc->count3++;
+ ftpc->count1 += ftpc->count2; /* get next attempt */
+ result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
+ /* remain in this same state */
+ }
+ else {
+ if(data->set.use_ssl > CURLUSESSL_TRY)
+ /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */
+ result = CURLE_USE_SSL_FAILED;
+ else
+ /* ignore the failure and continue */
+ result = ftp_state_user(conn);
+ }
+
+ if(result)
+ return result;
+ break;
+
+ case FTP_USER:
+ case FTP_PASS:
+ result = ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_ACCT:
+ result = ftp_state_acct_resp(conn, ftpcode);
+ break;
+
+ case FTP_PBSZ:
+ PPSENDF(&ftpc->pp, "PROT %c",
+ data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
+ state(conn, FTP_PROT);
+
+ break;
+
+ case FTP_PROT:
+ if(ftpcode/100 == 2)
+ /* We have enabled SSL for the data connection! */
+ conn->ssl[SECONDARYSOCKET].use =
+ (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
+ /* FTP servers typically responds with 500 if they decide to reject
+ our 'P' request */
+ else if(data->set.use_ssl > CURLUSESSL_CONTROL)
+ /* we failed and bails out */
+ return CURLE_USE_SSL_FAILED;
+
+ if(data->set.ftp_ccc) {
+ /* CCC - Clear Command Channel
+ */
+ PPSENDF(&ftpc->pp, "%s", "CCC");
+ state(conn, FTP_CCC);
+ }
+ else {
+ result = ftp_state_pwd(conn);
+ if(result)
+ return result;
+ }
+ break;
+
+ case FTP_CCC:
+ if(ftpcode < 500) {
+ /* First shut down the SSL layer (note: this call will block) */
+ result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
+
+ if(result) {
+ failf(conn->data, "Failed to clear the command channel (CCC)");
+ return result;
+ }
+ }
+
+ /* Then continue as normal */
+ result = ftp_state_pwd(conn);
+ if(result)
+ return result;
+ break;
+
+ case FTP_PWD:
+ if(ftpcode == 257) {
+ char *ptr=&data->state.buffer[4]; /* start on the first letter */
+ char *dir;
+ char *store;
+
+ dir = malloc(nread + 1);
+ if(!dir)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Reply format is like
+ 257<space>[rubbish]"<directory-name>"<space><commentary> and the
+ RFC959 says
+
+ The directory name can contain any character; embedded
+ double-quotes should be escaped by double-quotes (the
+ "quote-doubling" convention).
+ */
+
+ /* scan for the first double-quote for non-standard responses */
+ while(ptr < &data->state.buffer[sizeof(data->state.buffer)]
+ && *ptr != '\n' && *ptr != '\0' && *ptr != '"')
+ ptr++;
+
+ if('\"' == *ptr) {
+ /* it started good */
+ ptr++;
+ for(store = dir; *ptr;) {
+ if('\"' == *ptr) {
+ if('\"' == ptr[1]) {
+ /* "quote-doubling" */
+ *store = ptr[1];
+ ptr++;
+ }
+ else {
+ /* end of path */
+ *store = '\0'; /* zero terminate */
+ break; /* get out of this loop */
+ }
+ }
+ else
+ *store = *ptr;
+ store++;
+ ptr++;
+ }
+
+ /* If the path name does not look like an absolute path (i.e.: it
+ does not start with a '/'), we probably need some server-dependent
+ adjustments. For example, this is the case when connecting to
+ an OS400 FTP server: this server supports two name syntaxes,
+ the default one being incompatible with standard pathes. In
+ addition, this server switches automatically to the regular path
+ syntax when one is encountered in a command: this results in
+ having an entrypath in the wrong syntax when later used in CWD.
+ The method used here is to check the server OS: we do it only
+ if the path name looks strange to minimize overhead on other
+ systems. */
+
+ if(!ftpc->server_os && dir[0] != '/') {
+
+ result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST");
+ if(result != CURLE_OK) {
+ free(dir);
+ return result;
+ }
+ Curl_safefree(ftpc->entrypath);
+ ftpc->entrypath = dir; /* remember this */
+ infof(data, "Entry path is '%s'\n", ftpc->entrypath);
+ /* also save it where getinfo can access it: */
+ data->state.most_recent_ftp_entrypath = ftpc->entrypath;
+ state(conn, FTP_SYST);
+ break;
+ }
+
+ Curl_safefree(ftpc->entrypath);
+ ftpc->entrypath = dir; /* remember this */
+ infof(data, "Entry path is '%s'\n", ftpc->entrypath);
+ /* also save it where getinfo can access it: */
+ data->state.most_recent_ftp_entrypath = ftpc->entrypath;
+ }
+ else {
+ /* couldn't get the path */
+ free(dir);
+ infof(data, "Failed to figure out path\n");
+ }
+ }
+ state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ break;
+
+ case FTP_SYST:
+ if(ftpcode == 215) {
+ char *ptr=&data->state.buffer[4]; /* start on the first letter */
+ char *os;
+ char *store;
+
+ os = malloc(nread + 1);
+ if(!os)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Reply format is like
+ 215<space><OS-name><space><commentary>
+ */
+ while(*ptr == ' ')
+ ptr++;
+ for(store = os; *ptr && *ptr != ' ';)
+ *store++ = *ptr++;
+ *store = '\0'; /* zero terminate */
+
+ /* Check for special servers here. */
+
+ if(strequal(os, "OS/400")) {
+ /* Force OS400 name format 1. */
+ result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
+ if(result != CURLE_OK) {
+ free(os);
+ return result;
+ }
+ /* remember target server OS */
+ Curl_safefree(ftpc->server_os);
+ ftpc->server_os = os;
+ state(conn, FTP_NAMEFMT);
+ break;
+ }
+ else {
+ /* Nothing special for the target server. */
+ /* remember target server OS */
+ Curl_safefree(ftpc->server_os);
+ ftpc->server_os = os;
+ }
+ }
+ else {
+ /* Cannot identify server OS. Continue anyway and cross fingers. */
+ }
+
+ state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ break;
+
+ case FTP_NAMEFMT:
+ if(ftpcode == 250) {
+ /* Name format change successful: reload initial path. */
+ ftp_state_pwd(conn);
+ break;
+ }
+
+ state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ break;
+
+ case FTP_QUOTE:
+ case FTP_POSTQUOTE:
+ case FTP_RETR_PREQUOTE:
+ case FTP_STOR_PREQUOTE:
+ if((ftpcode >= 400) && !ftpc->count2) {
+ /* failure response code, and not allowed to fail */
+ failf(conn->data, "QUOT command failed with %03d", ftpcode);
+ return CURLE_QUOTE_ERROR;
+ }
+ result = ftp_state_quote(conn, FALSE, ftpc->state);
+ if(result)
+ return result;
+
+ break;
+
+ case FTP_CWD:
+ if(ftpcode/100 != 2) {
+ /* failure to CWD there */
+ if(conn->data->set.ftp_create_missing_dirs &&
+ ftpc->count1 && !ftpc->count2) {
+ /* try making it */
+ ftpc->count2++; /* counter to prevent CWD-MKD loops */
+ PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->count1 - 1]);
+ state(conn, FTP_MKD);
+ }
+ else {
+ /* return failure */
+ failf(data, "Server denied you to change to the given directory");
+ ftpc->cwdfail = TRUE; /* don't remember this path as we failed
+ to enter it */
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+ }
+ else {
+ /* success */
+ ftpc->count2=0;
+ if(++ftpc->count1 <= ftpc->dirdepth) {
+ /* send next CWD */
+ PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
+ }
+ else {
+ result = ftp_state_mdtm(conn);
+ if(result)
+ return result;
+ }
+ }
+ break;
+
+ case FTP_MKD:
+ if((ftpcode/100 != 2) && !ftpc->count3--) {
+ /* failure to MKD the dir */
+ failf(data, "Failed to MKD dir: %03d", ftpcode);
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+ state(conn, FTP_CWD);
+ /* send CWD */
+ PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
+ break;
+
+ case FTP_MDTM:
+ result = ftp_state_mdtm_resp(conn, ftpcode);
+ break;
+
+ case FTP_TYPE:
+ case FTP_LIST_TYPE:
+ case FTP_RETR_TYPE:
+ case FTP_STOR_TYPE:
+ result = ftp_state_type_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_SIZE:
+ case FTP_RETR_SIZE:
+ case FTP_STOR_SIZE:
+ result = ftp_state_size_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_REST:
+ case FTP_RETR_REST:
+ result = ftp_state_rest_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_PRET:
+ if(ftpcode != 200) {
+ /* there only is this one standard OK return code. */
+ failf(data, "PRET command not accepted: %03d", ftpcode);
+ return CURLE_FTP_PRET_FAILED;
+ }
+ result = ftp_state_use_pasv(conn);
+ break;
+
+ case FTP_PASV:
+ result = ftp_state_pasv_resp(conn, ftpcode);
+ break;
+
+ case FTP_PORT:
+ result = ftp_state_port_resp(conn, ftpcode);
+ break;
+
+ case FTP_LIST:
+ case FTP_RETR:
+ result = ftp_state_get_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_STOR:
+ result = ftp_state_stor_resp(conn, ftpcode, ftpc->state);
+ break;
+
+ case FTP_QUIT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ state(conn, FTP_STOP);
+ break;
+ }
+ } /* if(ftpcode) */
+
+ return result;
+}
+
+
+/* called repeatedly until done from multi.c */
+static CURLcode ftp_multi_statemach(struct connectdata *conn,
+ bool *done)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
+
+ /* Check for the state outside of the Curl_socket_ready() return code checks
+ since at times we are in fact already in this state when this function
+ gets called. */
+ *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
+
+ return result;
+}
+
+static CURLcode ftp_block_statemach(struct connectdata *conn)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ CURLcode result = CURLE_OK;
+
+ while(ftpc->state != FTP_STOP) {
+ result = Curl_pp_statemach(pp, TRUE);
+ if(result)
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * ftp_connect() should do everything that is to be considered a part of
+ * the connection phase.
+ *
+ * The variable 'done' points to will be TRUE if the protocol-layer connect
+ * phase is done when this function returns, or FALSE if not.
+ *
+ */
+static CURLcode ftp_connect(struct connectdata *conn,
+ bool *done) /* see description above */
+{
+ CURLcode result;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+
+ *done = FALSE; /* default to not done yet */
+
+ /* We always support persistent connections on ftp */
+ connkeep(conn, "FTP default");
+
+ pp->response_time = RESP_TIMEOUT; /* set default response time-out */
+ pp->statemach_act = ftp_statemach_act;
+ pp->endofresp = ftp_endofresp;
+ pp->conn = conn;
+
+ if(conn->handler->flags & PROTOPT_SSL) {
+ /* BLOCKING */
+ result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ if(result)
+ return result;
+ }
+
+ Curl_pp_init(pp); /* init the generic pingpong data */
+
+ /* When we connect, we start in the state where we await the 220
+ response */
+ state(conn, FTP_WAIT220);
+
+ result = ftp_multi_statemach(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_done()
+ *
+ * The DONE function. This does what needs to be done after a single DO has
+ * performed.
+ *
+ * Input argument is already checked for validity.
+ */
+static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ struct SessionHandle *data = conn->data;
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+ ssize_t nread;
+ int ftpcode;
+ CURLcode result = CURLE_OK;
+ bool was_ctl_valid = ftpc->ctl_valid;
+ char *path;
+ const char *path_to_use = data->state.path;
+
+ if(!ftp)
+ /* When the easy handle is removed from the multi while libcurl is still
+ * trying to resolve the host name, it seems that the ftp struct is not
+ * yet initialized, but the removal action calls Curl_done() which calls
+ * this function. So we simply return success if no ftp pointer is set.
+ */
+ return CURLE_OK;
+
+ switch(status) {
+ case CURLE_BAD_DOWNLOAD_RESUME:
+ case CURLE_FTP_WEIRD_PASV_REPLY:
+ case CURLE_FTP_PORT_FAILED:
+ case CURLE_FTP_ACCEPT_FAILED:
+ case CURLE_FTP_ACCEPT_TIMEOUT:
+ case CURLE_FTP_COULDNT_SET_TYPE:
+ case CURLE_FTP_COULDNT_RETR_FILE:
+ case CURLE_PARTIAL_FILE:
+ case CURLE_UPLOAD_FAILED:
+ case CURLE_REMOTE_ACCESS_DENIED:
+ case CURLE_FILESIZE_EXCEEDED:
+ case CURLE_REMOTE_FILE_NOT_FOUND:
+ case CURLE_WRITE_ERROR:
+ /* the connection stays alive fine even though this happened */
+ /* fall-through */
+ case CURLE_OK: /* doesn't affect the control connection's status */
+ if(!premature) {
+ ftpc->ctl_valid = was_ctl_valid;
+ break;
+ }
+ /* until we cope better with prematurely ended requests, let them
+ * fallback as if in complete failure */
+ default: /* by default, an error means the control connection is
+ wedged and should not be used anymore */
+ ftpc->ctl_valid = FALSE;
+ ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the
+ current path, as this connection is going */
+ connclose(conn, "FTP ended with bad error code");
+ result = status; /* use the already set error code */
+ break;
+ }
+
+ /* now store a copy of the directory we are in */
+ if(ftpc->prevpath)
+ free(ftpc->prevpath);
+
+ if(data->set.wildcardmatch) {
+ if(data->set.chunk_end && ftpc->file) {
+ data->set.chunk_end(data->wildcard.customptr);
+ }
+ ftpc->known_filesize = -1;
+ }
+
+ /* get the "raw" path */
+ path = curl_easy_unescape(data, path_to_use, 0, NULL);
+ if(!path) {
+ /* out of memory, but we can limp along anyway (and should try to
+ * since we may already be in the out of memory cleanup path) */
+ if(!result)
+ result = CURLE_OUT_OF_MEMORY;
+ ftpc->ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
+ ftpc->prevpath = NULL; /* no path remembering */
+ }
+ else {
+ size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */
+ size_t dlen = strlen(path)-flen;
+ if(!ftpc->cwdfail) {
+ if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) {
+ ftpc->prevpath = path;
+ if(flen)
+ /* if 'path' is not the whole string */
+ ftpc->prevpath[dlen]=0; /* terminate */
+ }
+ else {
+ /* we never changed dir */
+ ftpc->prevpath=strdup("");
+ free(path);
+ }
+ if(ftpc->prevpath)
+ infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
+ }
+ else {
+ ftpc->prevpath = NULL; /* no path */
+ free(path);
+ }
+ }
+ /* free the dir tree and file parts */
+ freedirs(ftpc);
+
+ /* shut down the socket to inform the server we're done */
+
+#ifdef _WIN32_WCE
+ shutdown(conn->sock[SECONDARYSOCKET],2); /* SD_BOTH */
+#endif
+
+ if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
+ if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
+ /* partial download completed */
+ result = Curl_pp_sendf(pp, "%s", "ABOR");
+ if(result) {
+ failf(data, "Failure sending ABOR command: %s",
+ curl_easy_strerror(result));
+ ftpc->ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(conn, "ABOR command failed"); /* connection closure */
+ }
+ }
+
+ if(conn->ssl[SECONDARYSOCKET].use) {
+ /* The secondary socket is using SSL so we must close down that part
+ first before we close the socket for real */
+ Curl_ssl_close(conn, SECONDARYSOCKET);
+
+ /* Note that we keep "use" set to TRUE since that (next) connection is
+ still requested to use SSL */
+ }
+ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
+ Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
+ conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
+ }
+ }
+
+ if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
+ pp->pending_resp && !premature) {
+ /*
+ * Let's see what the server says about the transfer we just performed,
+ * but lower the timeout as sometimes this connection has died while the
+ * data has been transferred. This happens when doing through NATs etc that
+ * abandon old silent connections.
+ */
+ long old_time = pp->response_time;
+
+ pp->response_time = 60*1000; /* give it only a minute for now */
+ pp->response = Curl_tvnow(); /* timeout relative now */
+
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+
+ pp->response_time = old_time; /* set this back to previous value */
+
+ if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
+ failf(data, "control connection looks dead");
+ ftpc->ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
+ }
+
+ if(result)
+ return result;
+
+ if(ftpc->dont_check && data->req.maxdownload > 0) {
+ /* we have just sent ABOR and there is no reliable way to check if it was
+ * successful or not; we have to close the connection now */
+ infof(data, "partial download completed, closing connection\n");
+ connclose(conn, "Partial download with no ability to check");
+ return result;
+ }
+
+ if(!ftpc->dont_check) {
+ /* 226 Transfer complete, 250 Requested file action okay, completed. */
+ if((ftpcode != 226) && (ftpcode != 250)) {
+ failf(data, "server did not report OK, got %d", ftpcode);
+ result = CURLE_PARTIAL_FILE;
+ }
+ }
+ }
+
+ if(result || premature)
+ /* the response code from the transfer showed an error already so no
+ use checking further */
+ ;
+ else if(data->set.upload) {
+ if((-1 != data->state.infilesize) &&
+ (data->state.infilesize != *ftp->bytecountp) &&
+ !data->set.crlf &&
+ (ftp->transfer == FTPTRANSFER_BODY)) {
+ failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
+ " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
+ *ftp->bytecountp, data->state.infilesize);
+ result = CURLE_PARTIAL_FILE;
+ }
+ }
+ else {
+ if((-1 != data->req.size) &&
+ (data->req.size != *ftp->bytecountp) &&
+#ifdef CURL_DO_LINEEND_CONV
+ /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
+ * we'll check to see if the discrepancy can be explained by the number
+ * of CRLFs we've changed to LFs.
+ */
+ ((data->req.size + data->state.crlf_conversions) !=
+ *ftp->bytecountp) &&
+#endif /* CURL_DO_LINEEND_CONV */
+ (data->req.maxdownload != *ftp->bytecountp)) {
+ failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
+ " bytes", *ftp->bytecountp);
+ result = CURLE_PARTIAL_FILE;
+ }
+ else if(!ftpc->dont_check &&
+ !*ftp->bytecountp &&
+ (data->req.size>0)) {
+ failf(data, "No data was received!");
+ result = CURLE_FTP_COULDNT_RETR_FILE;
+ }
+ }
+
+ /* clear these for next connection */
+ ftp->transfer = FTPTRANSFER_BODY;
+ ftpc->dont_check = FALSE;
+
+ /* Send any post-transfer QUOTE strings? */
+ if(!status && !result && !premature && data->set.postquote)
+ result = ftp_sendquote(conn, data->set.postquote);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_sendquote()
+ *
+ * Where a 'quote' means a list of custom commands to send to the server.
+ * The quote list is passed as an argument.
+ *
+ * BLOCKING
+ */
+
+static
+CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
+{
+ struct curl_slist *item;
+ ssize_t nread;
+ int ftpcode;
+ CURLcode result;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+
+ item = quote;
+ while(item) {
+ if(item->data) {
+ char *cmd = item->data;
+ bool acceptfail = FALSE;
+
+ /* if a command starts with an asterisk, which a legal FTP command never
+ can, the command will be allowed to fail without it causing any
+ aborts or cancels etc. It will cause libcurl to act as if the command
+ is successful, whatever the server reponds. */
+
+ if(cmd[0] == '*') {
+ cmd++;
+ acceptfail = TRUE;
+ }
+
+ PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
+
+ pp->response = Curl_tvnow(); /* timeout relative now */
+
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
+
+ if(!acceptfail && (ftpcode >= 400)) {
+ failf(conn->data, "QUOT string not accepted: %s", cmd);
+ return CURLE_QUOTE_ERROR;
+ }
+ }
+
+ item = item->next;
+ }
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * ftp_need_type()
+ *
+ * Returns TRUE if we in the current situation should send TYPE
+ */
+static int ftp_need_type(struct connectdata *conn,
+ bool ascii_wanted)
+{
+ return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I');
+}
+
+/***********************************************************************
+ *
+ * ftp_nb_type()
+ *
+ * Set TYPE. We only deal with ASCII or BINARY so this function
+ * sets one of them.
+ * If the transfer type is not sent, simulate on OK response in newstate
+ */
+static CURLcode ftp_nb_type(struct connectdata *conn,
+ bool ascii, ftpstate newstate)
+{
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result;
+ char want = (char)(ascii?'A':'I');
+
+ if(ftpc->transfertype == want) {
+ state(conn, newstate);
+ return ftp_state_type_resp(conn, 200, newstate);
+ }
+
+ PPSENDF(&ftpc->pp, "TYPE %c", want);
+ state(conn, newstate);
+
+ /* keep track of our current transfer type */
+ ftpc->transfertype = want;
+ return CURLE_OK;
+}
+
+/***************************************************************************
+ *
+ * ftp_pasv_verbose()
+ *
+ * This function only outputs some informationals about this second connection
+ * when we've issued a PASV command before and thus we have connected to a
+ * possibly new IP address.
+ *
+ */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void
+ftp_pasv_verbose(struct connectdata *conn,
+ Curl_addrinfo *ai,
+ char *newhost, /* ascii version */
+ int port)
+{
+ char buf[256];
+ Curl_printable_address(ai, buf, sizeof(buf));
+ infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
+}
+#endif
+
+/*
+ Check if this is a range download, and if so, set the internal variables
+ properly.
+ */
+
+static CURLcode ftp_range(struct connectdata *conn)
+{
+ curl_off_t from, to;
+ char *ptr;
+ char *ptr2;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(data->state.use_range && data->state.range) {
+ from=curlx_strtoofft(data->state.range, &ptr, 0);
+ while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+ ptr++;
+ to=curlx_strtoofft(ptr, &ptr2, 0);
+ if(ptr == ptr2) {
+ /* we didn't get any digit */
+ to=-1;
+ }
+ if((-1 == to) && (from>=0)) {
+ /* X - */
+ data->state.resume_from = from;
+ DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T
+ " to end of file\n", from));
+ }
+ else if(from < 0) {
+ /* -Y */
+ data->req.maxdownload = -from;
+ data->state.resume_from = from;
+ DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
+ " bytes\n", -from));
+ }
+ else {
+ /* X-Y */
+ data->req.maxdownload = (to-from)+1; /* include last byte */
+ data->state.resume_from = from;
+ DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, data->req.maxdownload));
+ }
+ DEBUGF(infof(conn->data, "range-download from %" CURL_FORMAT_CURL_OFF_T
+ " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, to, data->req.maxdownload));
+ ftpc->dont_check = TRUE; /* dont check for successful transfer */
+ }
+ else
+ data->req.maxdownload = -1;
+ return CURLE_OK;
+}
+
+
+/*
+ * ftp_do_more()
+ *
+ * This function shall be called when the second FTP (data) connection is
+ * connected.
+ *
+ * 'complete' can return 0 for incomplete, 1 for done and -1 for go back
+ * (which basically is only for when PASV is being sent to retry a failed
+ * EPSV).
+ */
+
+static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
+{
+ struct SessionHandle *data=conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
+ bool complete = FALSE;
+
+ /* the ftp struct is inited in ftp_connect() */
+ struct FTP *ftp = data->req.protop;
+
+ /* if the second connection isn't done yet, wait for it */
+ if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
+ if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
+ /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
+ aren't used so we blank their arguments. TODO: make this nicer */
+ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
+
+ return result;
+ }
+
+ result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
+
+ /* Ready to do more? */
+ if(connected) {
+ DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
+ if(conn->bits.proxy) {
+ infof(data, "Connection to proxy confirmed\n");
+ result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
+ }
+ }
+ else {
+ if(result && (ftpc->count1 == 0)) {
+ *completep = -1; /* go back to DOING please */
+ /* this is a EPSV connect failing, try PASV instead */
+ return ftp_epsv_disable(conn);
+ }
+ return result;
+ }
+ }
+
+ if(ftpc->state) {
+ /* already in a state so skip the intial commands.
+ They are only done to kickstart the do_more state */
+ result = ftp_multi_statemach(conn, &complete);
+
+ *completep = (int)complete;
+
+ /* if we got an error or if we don't wait for a data connection return
+ immediately */
+ if(result || (ftpc->wait_data_conn != TRUE))
+ return result;
+
+ if(ftpc->wait_data_conn)
+ /* if we reach the end of the FTP state machine here, *complete will be
+ TRUE but so is ftpc->wait_data_conn, which says we need to wait for
+ the data connection and therefore we're not actually complete */
+ *completep = 0;
+ }
+
+ if(ftp->transfer <= FTPTRANSFER_INFO) {
+ /* a transfer is about to take place, or if not a file name was given
+ so we'll do a SIZE on it later and then we need the right TYPE first */
+
+ if(ftpc->wait_data_conn == TRUE) {
+ bool serv_conned;
+
+ result = ReceivedServerConnect(conn, &serv_conned);
+ if(result)
+ return result; /* Failed to accept data connection */
+
+ if(serv_conned) {
+ /* It looks data connection is established */
+ result = AcceptServerConnect(conn);
+ ftpc->wait_data_conn = FALSE;
+ if(!result)
+ result = InitiateTransfer(conn);
+
+ if(result)
+ return result;
+
+ *completep = 1; /* this state is now complete when the server has
+ connected back to us */
+ }
+ }
+ else if(data->set.upload) {
+ result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
+ if(result)
+ return result;
+
+ result = ftp_multi_statemach(conn, &complete);
+ *completep = (int)complete;
+ }
+ else {
+ /* download */
+ ftp->downloadsize = -1; /* unknown as of yet */
+
+ result = ftp_range(conn);
+ if(result)
+ ;
+ else if(data->set.ftp_list_only || !ftpc->file) {
+ /* The specified path ends with a slash, and therefore we think this
+ is a directory that is requested, use LIST. But before that we
+ need to set ASCII transfer mode. */
+
+ /* But only if a body transfer was requested. */
+ if(ftp->transfer == FTPTRANSFER_BODY) {
+ result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE);
+ if(result)
+ return result;
+ }
+ /* otherwise just fall through */
+ }
+ else {
+ result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE);
+ if(result)
+ return result;
+ }
+
+ result = ftp_multi_statemach(conn, &complete);
+ *completep = (int)complete;
+ }
+ return result;
+ }
+
+ if((result == CURLE_OK) && (ftp->transfer != FTPTRANSFER_BODY))
+ /* no data to transfer. FIX: it feels like a kludge to have this here
+ too! */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ if(!ftpc->wait_data_conn) {
+ /* no waiting for the data connection so this is now complete */
+ *completep = 1;
+ DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result));
+ }
+
+ return result;
+}
+
+
+
+/***********************************************************************
+ *
+ * ftp_perform()
+ *
+ * This is the actual DO function for FTP. Get a file/directory according to
+ * the options previously setup.
+ */
+
+static
+CURLcode ftp_perform(struct connectdata *conn,
+ bool *connected, /* connect status after PASV / PORT */
+ bool *dophase_done)
+{
+ /* this is FTP and no proxy */
+ CURLcode result=CURLE_OK;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ if(conn->data->set.opt_no_body) {
+ /* requested no body means no transfer... */
+ struct FTP *ftp = conn->data->req.protop;
+ ftp->transfer = FTPTRANSFER_INFO;
+ }
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* start the first command in the DO phase */
+ result = ftp_state_quote(conn, TRUE, FTP_QUOTE);
+ if(result)
+ return result;
+
+ /* run the state-machine */
+ result = ftp_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[SECONDARYSOCKET];
+
+ infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected);
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete1\n"));
+
+ return result;
+}
+
+static void wc_data_dtor(void *ptr)
+{
+ struct ftp_wc_tmpdata *tmp = ptr;
+ if(tmp)
+ Curl_ftp_parselist_data_free(&tmp->parser);
+ Curl_safefree(tmp);
+}
+
+static CURLcode init_wc_data(struct connectdata *conn)
+{
+ char *last_slash;
+ char *path = conn->data->state.path;
+ struct WildcardData *wildcard = &(conn->data->wildcard);
+ CURLcode ret = CURLE_OK;
+ struct ftp_wc_tmpdata *ftp_tmp;
+
+ last_slash = strrchr(conn->data->state.path, '/');
+ if(last_slash) {
+ last_slash++;
+ if(last_slash[0] == '\0') {
+ wildcard->state = CURLWC_CLEAN;
+ ret = ftp_parse_url_path(conn);
+ return ret;
+ }
+ else {
+ wildcard->pattern = strdup(last_slash);
+ if(!wildcard->pattern)
+ return CURLE_OUT_OF_MEMORY;
+ last_slash[0] = '\0'; /* cut file from path */
+ }
+ }
+ else { /* there is only 'wildcard pattern' or nothing */
+ if(path[0]) {
+ wildcard->pattern = strdup(path);
+ if(!wildcard->pattern)
+ return CURLE_OUT_OF_MEMORY;
+ path[0] = '\0';
+ }
+ else { /* only list */
+ wildcard->state = CURLWC_CLEAN;
+ ret = ftp_parse_url_path(conn);
+ return ret;
+ }
+ }
+
+ /* program continues only if URL is not ending with slash, allocate needed
+ resources for wildcard transfer */
+
+ /* allocate ftp protocol specific temporary wildcard data */
+ ftp_tmp = calloc(1, sizeof(struct ftp_wc_tmpdata));
+ if(!ftp_tmp) {
+ Curl_safefree(wildcard->pattern);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* INITIALIZE parselist structure */
+ ftp_tmp->parser = Curl_ftp_parselist_data_alloc();
+ if(!ftp_tmp->parser) {
+ Curl_safefree(wildcard->pattern);
+ Curl_safefree(ftp_tmp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */
+ wildcard->tmp_dtor = wc_data_dtor;
+
+ /* wildcard does not support NOCWD option (assert it?) */
+ if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
+ conn->data->set.ftp_filemethod = FTPFILE_MULTICWD;
+
+ /* try to parse ftp url */
+ ret = ftp_parse_url_path(conn);
+ if(ret) {
+ Curl_safefree(wildcard->pattern);
+ wildcard->tmp_dtor(wildcard->tmp);
+ wildcard->tmp_dtor = ZERO_NULL;
+ wildcard->tmp = NULL;
+ return ret;
+ }
+
+ wildcard->path = strdup(conn->data->state.path);
+ if(!wildcard->path) {
+ Curl_safefree(wildcard->pattern);
+ wildcard->tmp_dtor(wildcard->tmp);
+ wildcard->tmp_dtor = ZERO_NULL;
+ wildcard->tmp = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* backup old write_function */
+ ftp_tmp->backup.write_function = conn->data->set.fwrite_func;
+ /* parsing write function */
+ conn->data->set.fwrite_func = Curl_ftp_parselist;
+ /* backup old file descriptor */
+ ftp_tmp->backup.file_descriptor = conn->data->set.out;
+ /* let the writefunc callback know what curl pointer is working with */
+ conn->data->set.out = conn;
+
+ infof(conn->data, "Wildcard - Parsing started\n");
+ return CURLE_OK;
+}
+
+/* This is called recursively */
+static CURLcode wc_statemach(struct connectdata *conn)
+{
+ struct WildcardData * const wildcard = &(conn->data->wildcard);
+ CURLcode ret = CURLE_OK;
+
+ switch (wildcard->state) {
+ case CURLWC_INIT:
+ ret = init_wc_data(conn);
+ if(wildcard->state == CURLWC_CLEAN)
+ /* only listing! */
+ break;
+ else
+ wildcard->state = ret ? CURLWC_ERROR : CURLWC_MATCHING;
+ break;
+
+ case CURLWC_MATCHING: {
+ /* In this state is LIST response successfully parsed, so lets restore
+ previous WRITEFUNCTION callback and WRITEDATA pointer */
+ struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
+ conn->data->set.fwrite_func = ftp_tmp->backup.write_function;
+ conn->data->set.out = ftp_tmp->backup.file_descriptor;
+ ftp_tmp->backup.write_function = ZERO_NULL;
+ ftp_tmp->backup.file_descriptor = NULL;
+ wildcard->state = CURLWC_DOWNLOADING;
+
+ if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) {
+ /* error found in LIST parsing */
+ wildcard->state = CURLWC_CLEAN;
+ return wc_statemach(conn);
+ }
+ else if(wildcard->filelist->size == 0) {
+ /* no corresponding file */
+ wildcard->state = CURLWC_CLEAN;
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
+ return wc_statemach(conn);
+ }
+
+ case CURLWC_DOWNLOADING: {
+ /* filelist has at least one file, lets get first one */
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct curl_fileinfo *finfo = wildcard->filelist->head->ptr;
+
+ char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
+ if(!tmp_path)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* switch default "state.pathbuffer" and tmp_path, good to see
+ ftp_parse_url_path function to understand this trick */
+ Curl_safefree(conn->data->state.pathbuffer);
+ conn->data->state.pathbuffer = tmp_path;
+ conn->data->state.path = tmp_path;
+
+ infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
+ if(conn->data->set.chunk_bgn) {
+ long userresponse = conn->data->set.chunk_bgn(
+ finfo, wildcard->customptr, (int)wildcard->filelist->size);
+ switch(userresponse) {
+ case CURL_CHUNK_BGN_FUNC_SKIP:
+ infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
+ finfo->filename);
+ wildcard->state = CURLWC_SKIP;
+ return wc_statemach(conn);
+ case CURL_CHUNK_BGN_FUNC_FAIL:
+ return CURLE_CHUNK_FAILED;
+ }
+ }
+
+ if(finfo->filetype != CURLFILETYPE_FILE) {
+ wildcard->state = CURLWC_SKIP;
+ return wc_statemach(conn);
+ }
+
+ if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
+ ftpc->known_filesize = finfo->size;
+
+ ret = ftp_parse_url_path(conn);
+ if(ret) {
+ return ret;
+ }
+
+ /* we don't need the Curl_fileinfo of first file anymore */
+ Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
+
+ if(wildcard->filelist->size == 0) { /* remains only one file to down. */
+ wildcard->state = CURLWC_CLEAN;
+ /* after that will be ftp_do called once again and no transfer
+ will be done because of CURLWC_CLEAN state */
+ return CURLE_OK;
+ }
+ } break;
+
+ case CURLWC_SKIP: {
+ if(conn->data->set.chunk_end)
+ conn->data->set.chunk_end(conn->data->wildcard.customptr);
+ Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
+ wildcard->state = (wildcard->filelist->size == 0) ?
+ CURLWC_CLEAN : CURLWC_DOWNLOADING;
+ return wc_statemach(conn);
+ }
+
+ case CURLWC_CLEAN: {
+ struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
+ ret = CURLE_OK;
+ if(ftp_tmp) {
+ ret = Curl_ftp_parselist_geterror(ftp_tmp->parser);
+ }
+ wildcard->state = ret ? CURLWC_ERROR : CURLWC_DONE;
+ } break;
+
+ case CURLWC_DONE:
+ case CURLWC_ERROR:
+ break;
+ }
+
+ return ret;
+}
+
+/***********************************************************************
+ *
+ * ftp_do()
+ *
+ * This function is registered as 'curl_do' function. It decodes the path
+ * parts etc as a wrapper to the actual DO function (ftp_perform).
+ *
+ * The input argument is already checked for validity.
+ */
+static CURLcode ftp_do(struct connectdata *conn, bool *done)
+{
+ CURLcode retcode = CURLE_OK;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ *done = FALSE; /* default to false */
+ ftpc->wait_data_conn = FALSE; /* default to no such wait */
+
+ if(conn->data->set.wildcardmatch) {
+ retcode = wc_statemach(conn);
+ if(conn->data->wildcard.state == CURLWC_SKIP ||
+ conn->data->wildcard.state == CURLWC_DONE) {
+ /* do not call ftp_regular_transfer */
+ return CURLE_OK;
+ }
+ if(retcode) /* error, loop or skipping the file */
+ return retcode;
+ }
+ else { /* no wildcard FSM needed */
+ retcode = ftp_parse_url_path(conn);
+ if(retcode)
+ return retcode;
+ }
+
+ retcode = ftp_regular_transfer(conn, done);
+
+ return retcode;
+}
+
+
+CURLcode Curl_ftpsendf(struct connectdata *conn,
+ const char *fmt, ...)
+{
+ ssize_t bytes_written;
+#define SBUF_SIZE 1024
+ char s[SBUF_SIZE];
+ size_t write_len;
+ char *sptr=s;
+ CURLcode res = CURLE_OK;
+#ifdef HAVE_GSSAPI
+ enum protection_level data_sec = conn->data_prot;
+#endif
+
+ va_list ap;
+ va_start(ap, fmt);
+ write_len = vsnprintf(s, SBUF_SIZE-3, fmt, ap);
+ va_end(ap);
+
+ strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
+ write_len +=2;
+
+ bytes_written=0;
+
+ res = Curl_convert_to_network(conn->data, s, write_len);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(res)
+ return(res);
+
+ for(;;) {
+#ifdef HAVE_GSSAPI
+ conn->data_prot = PROT_CMD;
+#endif
+ res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
+ &bytes_written);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
+ conn->data_prot = data_sec;
+#endif
+
+ if(CURLE_OK != res)
+ break;
+
+ if(conn->data->set.verbose)
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT,
+ sptr, (size_t)bytes_written, conn);
+
+ if(bytes_written != (ssize_t)write_len) {
+ write_len -= bytes_written;
+ sptr += bytes_written;
+ }
+ else
+ break;
+ }
+
+ return res;
+}
+
+/***********************************************************************
+ *
+ * ftp_quit()
+ *
+ * This should be called before calling sclose() on an ftp control connection
+ * (not data connections). We should then wait for the response from the
+ * server before returning. The calling code should then try to close the
+ * connection.
+ *
+ */
+static CURLcode ftp_quit(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ if(conn->proto.ftpc.ctl_valid) {
+ result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT");
+ if(result) {
+ failf(conn->data, "Failure sending QUIT command: %s",
+ curl_easy_strerror(result));
+ conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(conn, "QUIT command failed"); /* mark for connection closure */
+ state(conn, FTP_STOP);
+ return result;
+ }
+
+ state(conn, FTP_QUIT);
+
+ result = ftp_block_statemach(conn);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_disconnect()
+ *
+ * Disconnect from an FTP server. Cleanup protocol-specific per-connection
+ * resources. BLOCKING.
+ */
+static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct ftp_conn *ftpc= &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
+
+ /* We cannot send quit unconditionally. If this connection is stale or
+ bad in any way, sending quit and waiting around here will make the
+ disconnect wait in vain and cause more problems than we need to.
+
+ ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
+ will try to send the QUIT command, otherwise it will just return.
+ */
+ if(dead_connection)
+ ftpc->ctl_valid = FALSE;
+
+ /* The FTP session may or may not have been allocated/setup at this point! */
+ (void)ftp_quit(conn); /* ignore errors on the QUIT */
+
+ if(ftpc->entrypath) {
+ struct SessionHandle *data = conn->data;
+ if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
+ data->state.most_recent_ftp_entrypath = NULL;
+ }
+ free(ftpc->entrypath);
+ ftpc->entrypath = NULL;
+ }
+
+ freedirs(ftpc);
+ if(ftpc->prevpath) {
+ free(ftpc->prevpath);
+ ftpc->prevpath = NULL;
+ }
+ if(ftpc->server_os) {
+ free(ftpc->server_os);
+ ftpc->server_os = NULL;
+ }
+
+ Curl_pp_disconnect(pp);
+
+#ifdef HAVE_GSSAPI
+ Curl_sec_end(conn);
+#endif
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * ftp_parse_url_path()
+ *
+ * Parse the URL path into separate path components.
+ *
+ */
+static
+CURLcode ftp_parse_url_path(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ /* the ftp struct is already inited in ftp_connect() */
+ struct FTP *ftp = data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ const char *slash_pos; /* position of the first '/' char in curpos */
+ const char *path_to_use = data->state.path;
+ const char *cur_pos;
+ const char *filename = NULL;
+
+ cur_pos = path_to_use; /* current position in path. point at the begin
+ of next path component */
+
+ ftpc->ctl_valid = FALSE;
+ ftpc->cwdfail = FALSE;
+
+ switch(data->set.ftp_filemethod) {
+ case FTPFILE_NOCWD:
+ /* fastest, but less standard-compliant */
+
+ /*
+ The best time to check whether the path is a file or directory is right
+ here. so:
+
+ the first condition in the if() right here, is there just in case
+ someone decides to set path to NULL one day
+ */
+ if(data->state.path &&
+ data->state.path[0] &&
+ (data->state.path[strlen(data->state.path) - 1] != '/') )
+ filename = data->state.path; /* this is a full file path */
+ /*
+ ftpc->file is not used anywhere other than for operations on a file.
+ In other words, never for directory operations.
+ So we can safely leave filename as NULL here and use it as a
+ argument in dir/file decisions.
+ */
+ break;
+
+ case FTPFILE_SINGLECWD:
+ /* get the last slash */
+ if(!path_to_use[0]) {
+ /* no dir, no file */
+ ftpc->dirdepth = 0;
+ break;
+ }
+ slash_pos=strrchr(cur_pos, '/');
+ if(slash_pos || !*cur_pos) {
+ size_t dirlen = slash_pos-cur_pos;
+
+ ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
+ if(!ftpc->dirs)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(!dirlen)
+ dirlen++;
+
+ ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
+ slash_pos ? curlx_uztosi(dirlen) : 1,
+ NULL);
+ if(!ftpc->dirs[0]) {
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ftpc->dirdepth = 1; /* we consider it to be a single dir */
+ filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
+ }
+ else
+ filename = cur_pos; /* this is a file name only */
+ break;
+
+ default: /* allow pretty much anything */
+ case FTPFILE_MULTICWD:
+ ftpc->dirdepth = 0;
+ ftpc->diralloc = 5; /* default dir depth to allocate */
+ ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0]));
+ if(!ftpc->dirs)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* we have a special case for listing the root dir only */
+ if(strequal(path_to_use, "/")) {
+ cur_pos++; /* make it point to the zero byte */
+ ftpc->dirs[0] = strdup("/");
+ ftpc->dirdepth++;
+ }
+ else {
+ /* parse the URL path into separate path components */
+ while((slash_pos = strchr(cur_pos, '/')) != NULL) {
+ /* 1 or 0 pointer offset to indicate absolute directory */
+ ssize_t absolute_dir = ((cur_pos - data->state.path > 0) &&
+ (ftpc->dirdepth == 0))?1:0;
+
+ /* seek out the next path component */
+ if(slash_pos-cur_pos) {
+ /* we skip empty path components, like "x//y" since the FTP command
+ CWD requires a parameter and a non-existent parameter a) doesn't
+ work on many servers and b) has no effect on the others. */
+ int len = curlx_sztosi(slash_pos - cur_pos + absolute_dir);
+ ftpc->dirs[ftpc->dirdepth] =
+ curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL);
+ if(!ftpc->dirs[ftpc->dirdepth]) { /* run out of memory ... */
+ failf(data, "no memory");
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(isBadFtpString(ftpc->dirs[ftpc->dirdepth])) {
+ free(ftpc->dirs[ftpc->dirdepth]);
+ freedirs(ftpc);
+ return CURLE_URL_MALFORMAT;
+ }
+ }
+ else {
+ cur_pos = slash_pos + 1; /* jump to the rest of the string */
+ if(!ftpc->dirdepth) {
+ /* path starts with a slash, add that as a directory */
+ ftpc->dirs[ftpc->dirdepth] = strdup("/");
+ if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */
+ failf(data, "no memory");
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ continue;
+ }
+
+ cur_pos = slash_pos + 1; /* jump to the rest of the string */
+ if(++ftpc->dirdepth >= ftpc->diralloc) {
+ /* enlarge array */
+ char **bigger;
+ ftpc->diralloc *= 2; /* double the size each time */
+ bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0]));
+ if(!bigger) {
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ftpc->dirs = bigger;
+ }
+ }
+ }
+ filename = cur_pos; /* the rest is the file name */
+ break;
+ } /* switch */
+
+ if(filename && *filename) {
+ ftpc->file = curl_easy_unescape(conn->data, filename, 0, NULL);
+ if(NULL == ftpc->file) {
+ freedirs(ftpc);
+ failf(data, "no memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(isBadFtpString(ftpc->file)) {
+ freedirs(ftpc);
+ return CURLE_URL_MALFORMAT;
+ }
+ }
+ else
+ ftpc->file=NULL; /* instead of point to a zero byte, we make it a NULL
+ pointer */
+
+ if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
+ /* We need a file name when uploading. Return error! */
+ failf(data, "Uploading to a URL without a file name!");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ ftpc->cwddone = FALSE; /* default to not done */
+
+ if(ftpc->prevpath) {
+ /* prevpath is "raw" so we convert the input path before we compare the
+ strings */
+ int dlen;
+ char *path = curl_easy_unescape(conn->data, data->state.path, 0, &dlen);
+ if(!path) {
+ freedirs(ftpc);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ dlen -= ftpc->file?curlx_uztosi(strlen(ftpc->file)):0;
+ if((dlen == curlx_uztosi(strlen(ftpc->prevpath))) &&
+ strnequal(path, ftpc->prevpath, dlen)) {
+ infof(data, "Request has same path as previous transfer\n");
+ ftpc->cwddone = TRUE;
+ }
+ free(path);
+ }
+
+ return CURLE_OK;
+}
+
+/* call this when the DO phase has completed */
+static CURLcode ftp_dophase_done(struct connectdata *conn,
+ bool connected)
+{
+ struct FTP *ftp = conn->data->req.protop;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+
+ if(connected) {
+ int completed;
+ CURLcode result = ftp_do_more(conn, &completed);
+
+ if(result) {
+ if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
+ /* close the second socket if it was created already */
+ Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
+ }
+ return result;
+ }
+ }
+
+ if(ftp->transfer != FTPTRANSFER_BODY)
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ else if(!connected)
+ /* since we didn't connect now, we want do_more to get called */
+ conn->bits.do_more = TRUE;
+
+ ftpc->ctl_valid = TRUE; /* seems good */
+
+ return CURLE_OK;
+}
+
+/* called from multi.c while DOing */
+static CURLcode ftp_doing(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = ftp_multi_statemach(conn, dophase_done);
+
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
+ result = ftp_dophase_done(conn, FALSE /* not connected */);
+
+ DEBUGF(infof(conn->data, "DO phase is complete2\n"));
+ }
+ return result;
+}
+
+/***********************************************************************
+ *
+ * ftp_regular_transfer()
+ *
+ * The input argument is already checked for validity.
+ *
+ * Performs all commands done before a regular transfer between a local and a
+ * remote host.
+ *
+ * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
+ * ftp_done() function without finding any major problem.
+ */
+static
+CURLcode ftp_regular_transfer(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result=CURLE_OK;
+ bool connected=FALSE;
+ struct SessionHandle *data = conn->data;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ data->req.size = -1; /* make sure this is unknown at this point */
+
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ ftpc->ctl_valid = TRUE; /* starts good */
+
+ result = ftp_perform(conn,
+ &connected, /* have we connected after PASV/PORT */
+ dophase_done); /* all commands in the DO-phase done? */
+
+ if(CURLE_OK == result) {
+
+ if(!*dophase_done)
+ /* the DO phase has not completed yet */
+ return CURLE_OK;
+
+ result = ftp_dophase_done(conn, connected);
+
+ if(result)
+ return result;
+ }
+ else
+ freedirs(ftpc);
+
+ return result;
+}
+
+static CURLcode ftp_setup_connection(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ char *type;
+ char command;
+ struct FTP *ftp;
+
+ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+ /* Unless we have asked to tunnel ftp operations through the proxy, we
+ switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+ if(conn->handler == &Curl_handler_ftp)
+ conn->handler = &Curl_handler_ftp_proxy;
+ else {
+#ifdef USE_SSL
+ conn->handler = &Curl_handler_ftps_proxy;
+#else
+ failf(data, "FTPS not supported!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+ /* set it up as a HTTP connection instead */
+ return conn->handler->setup_connection(conn);
+#else
+ failf(data, "FTP over http proxy requires HTTP support built-in!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
+ if(NULL == ftp)
+ return CURLE_OUT_OF_MEMORY;
+
+ data->state.path++; /* don't include the initial slash */
+ data->state.slash_removed = TRUE; /* we've skipped the slash */
+
+ /* FTP URLs support an extension like ";type=<typecode>" that
+ * we'll try to get now! */
+ type = strstr(data->state.path, ";type=");
+
+ if(!type)
+ type = strstr(conn->host.rawalloc, ";type=");
+
+ if(type) {
+ *type = 0; /* it was in the middle of the hostname */
+ command = Curl_raw_toupper(type[6]);
+ conn->bits.type_set = TRUE;
+
+ switch (command) {
+ case 'A': /* ASCII mode */
+ data->set.prefer_ascii = TRUE;
+ break;
+
+ case 'D': /* directory mode */
+ data->set.ftp_list_only = TRUE;
+ break;
+
+ case 'I': /* binary mode */
+ default:
+ /* switch off ASCII */
+ data->set.prefer_ascii = FALSE;
+ break;
+ }
+ }
+
+ /* get some initial data into the ftp struct */
+ ftp->bytecountp = &conn->data->req.bytecount;
+ ftp->transfer = FTPTRANSFER_BODY;
+ ftp->downloadsize = 0;
+
+ /* No need to duplicate user+password, the connectdata struct won't change
+ during a session, but we re-init them here since on subsequent inits
+ since the conn struct may have changed or been replaced.
+ */
+ ftp->user = conn->user;
+ ftp->passwd = conn->passwd;
+ if(isBadFtpString(ftp->user))
+ return CURLE_URL_MALFORMAT;
+ if(isBadFtpString(ftp->passwd))
+ return CURLE_URL_MALFORMAT;
+
+ conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
+
+ return CURLE_OK;
+}
+
+#endif /* CURL_DISABLE_FTP */
diff --git a/external/libcurl_android/jni/libcurl/lib/ftp.h b/external/libcurl_android/jni/libcurl/lib/ftp.h
new file mode 100755
index 00000000..b6bfc028
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/ftp.h
@@ -0,0 +1,160 @@
+#ifndef HEADER_CURL_FTP_H
+#define HEADER_CURL_FTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "pingpong.h"
+
+#ifndef CURL_DISABLE_FTP
+extern const struct Curl_handler Curl_handler_ftp;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_ftps;
+#endif
+
+CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
+CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
+ int *ftpcode);
+#endif /* CURL_DISABLE_FTP */
+
+/****************************************************************************
+ * FTP unique setup
+ ***************************************************************************/
+typedef enum {
+ FTP_STOP, /* do nothing state, stops the state machine */
+ FTP_WAIT220, /* waiting for the initial 220 response immediately after
+ a connect */
+ FTP_AUTH,
+ FTP_USER,
+ FTP_PASS,
+ FTP_ACCT,
+ FTP_PBSZ,
+ FTP_PROT,
+ FTP_CCC,
+ FTP_PWD,
+ FTP_SYST,
+ FTP_NAMEFMT,
+ FTP_QUOTE, /* waiting for a response to a command sent in a quote list */
+ FTP_RETR_PREQUOTE,
+ FTP_STOR_PREQUOTE,
+ FTP_POSTQUOTE,
+ FTP_CWD, /* change dir */
+ FTP_MKD, /* if the dir didn't exist */
+ FTP_MDTM, /* to figure out the datestamp */
+ FTP_TYPE, /* to set type when doing a head-like request */
+ FTP_LIST_TYPE, /* set type when about to do a dir list */
+ FTP_RETR_TYPE, /* set type when about to RETR a file */
+ FTP_STOR_TYPE, /* set type when about to STOR a file */
+ FTP_SIZE, /* get the remote file's size for head-like request */
+ FTP_RETR_SIZE, /* get the remote file's size for RETR */
+ FTP_STOR_SIZE, /* get the size for STOR */
+ FTP_REST, /* when used to check if the server supports it in head-like */
+ FTP_RETR_REST, /* when asking for "resume" in for RETR */
+ FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */
+ FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */
+ FTP_PASV, /* generic state for PASV and EPSV, check count1 */
+ FTP_LIST, /* generic state for LIST, NLST or a custom list command */
+ FTP_RETR,
+ FTP_STOR, /* generic state for STOR and APPE */
+ FTP_QUIT,
+ FTP_LAST /* never used */
+} ftpstate;
+
+struct ftp_parselist_data; /* defined later in ftplistparser.c */
+
+struct ftp_wc_tmpdata {
+ struct ftp_parselist_data *parser;
+
+ struct {
+ curl_write_callback write_function;
+ FILE *file_descriptor;
+ } backup;
+};
+
+typedef enum {
+ FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */
+ FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */
+ FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the
+ file */
+} curl_ftpfile;
+
+/* This FTP struct is used in the SessionHandle. All FTP data that is
+ connection-oriented must be in FTP_conn to properly deal with the fact that
+ perhaps the SessionHandle is changed between the times the connection is
+ used. */
+struct FTP {
+ curl_off_t *bytecountp;
+ char *user; /* user name string */
+ char *passwd; /* password string */
+
+ /* transfer a file/body or not, done as a typedefed enum just to make
+ debuggers display the full symbol and not just the numerical value */
+ curl_pp_transfer transfer;
+ curl_off_t downloadsize;
+};
+
+
+/* ftp_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct ftp_conn {
+ struct pingpong pp;
+ char *entrypath; /* the PWD reply when we logged on */
+ char **dirs; /* realloc()ed array for path components */
+ int dirdepth; /* number of entries used in the 'dirs' array */
+ int diralloc; /* number of entries allocated for the 'dirs' array */
+ char *file; /* decoded file */
+ bool dont_check; /* Set to TRUE to prevent the final (post-transfer)
+ file size and 226/250 status check. It should still
+ read the line, just ignore the result. */
+ bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If
+ the connection has timed out or been closed, this
+ should be FALSE when it gets to Curl_ftp_quit() */
+ bool cwddone; /* if it has been determined that the proper CWD combo
+ already has been done */
+ bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent
+ caching the current directory */
+ bool wait_data_conn; /* this is set TRUE if data connection is waited */
+ char *prevpath; /* conn->path from the previous transfer */
+ char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
+ and others (A/I or zero) */
+ int count1; /* general purpose counter for the state machine */
+ int count2; /* general purpose counter for the state machine */
+ int count3; /* general purpose counter for the state machine */
+ ftpstate state; /* always use ftp.c:state() to change state! */
+ ftpstate state_saved; /* transfer type saved to be reloaded after
+ data connection is established */
+ curl_off_t retr_size_saved; /* Size of retrieved file saved */
+ char * server_os; /* The target server operating system. */
+ curl_off_t known_filesize; /* file size is different from -1, if wildcard
+ LIST parsing was done and wc_statemach set
+ it */
+ /* newhost must be able to hold a full IP-style address in ASCII, which
+ in the IPv6 case means 5*8-1 = 39 letters */
+#define NEWHOST_BUFSIZE 48
+ char newhost[NEWHOST_BUFSIZE]; /* this is the pair to connect the DATA... */
+ unsigned short newport; /* connection to */
+
+};
+
+#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */
+
+#endif /* HEADER_CURL_FTP_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/ftplistparser.c b/external/libcurl_android/jni/libcurl/lib/ftplistparser.c
new file mode 100755
index 00000000..4a46dd13
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/ftplistparser.c
@@ -0,0 +1,1053 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/**
+ * Now implemented:
+ *
+ * 1) UNIX version 1
+ * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
+ * 2) UNIX version 2
+ * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
+ * 3) UNIX version 3
+ * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog
+ * 4) UNIX symlink
+ * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000
+ * 5) DOS style
+ * 01-29-97 11:32PM <DIR> prog
+ */
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "fileinfo.h"
+#include "llist.h"
+#include "strtoofft.h"
+#include "rawstr.h"
+#include "ftp.h"
+#include "ftplistparser.h"
+#include "curl_fnmatch.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* allocs buffer which will contain one line of LIST command response */
+#define FTP_BUFFER_ALLOCSIZE 160
+
+typedef enum {
+ PL_UNIX_TOTALSIZE = 0,
+ PL_UNIX_FILETYPE,
+ PL_UNIX_PERMISSION,
+ PL_UNIX_HLINKS,
+ PL_UNIX_USER,
+ PL_UNIX_GROUP,
+ PL_UNIX_SIZE,
+ PL_UNIX_TIME,
+ PL_UNIX_FILENAME,
+ PL_UNIX_SYMLINK
+} pl_unix_mainstate;
+
+typedef union {
+ enum {
+ PL_UNIX_TOTALSIZE_INIT = 0,
+ PL_UNIX_TOTALSIZE_READING
+ } total_dirsize;
+
+ enum {
+ PL_UNIX_HLINKS_PRESPACE = 0,
+ PL_UNIX_HLINKS_NUMBER
+ } hlinks;
+
+ enum {
+ PL_UNIX_USER_PRESPACE = 0,
+ PL_UNIX_USER_PARSING
+ } user;
+
+ enum {
+ PL_UNIX_GROUP_PRESPACE = 0,
+ PL_UNIX_GROUP_NAME
+ } group;
+
+ enum {
+ PL_UNIX_SIZE_PRESPACE = 0,
+ PL_UNIX_SIZE_NUMBER
+ } size;
+
+ enum {
+ PL_UNIX_TIME_PREPART1 = 0,
+ PL_UNIX_TIME_PART1,
+ PL_UNIX_TIME_PREPART2,
+ PL_UNIX_TIME_PART2,
+ PL_UNIX_TIME_PREPART3,
+ PL_UNIX_TIME_PART3
+ } time;
+
+ enum {
+ PL_UNIX_FILENAME_PRESPACE = 0,
+ PL_UNIX_FILENAME_NAME,
+ PL_UNIX_FILENAME_WINDOWSEOL
+ } filename;
+
+ enum {
+ PL_UNIX_SYMLINK_PRESPACE = 0,
+ PL_UNIX_SYMLINK_NAME,
+ PL_UNIX_SYMLINK_PRETARGET1,
+ PL_UNIX_SYMLINK_PRETARGET2,
+ PL_UNIX_SYMLINK_PRETARGET3,
+ PL_UNIX_SYMLINK_PRETARGET4,
+ PL_UNIX_SYMLINK_TARGET,
+ PL_UNIX_SYMLINK_WINDOWSEOL
+ } symlink;
+} pl_unix_substate;
+
+typedef enum {
+ PL_WINNT_DATE = 0,
+ PL_WINNT_TIME,
+ PL_WINNT_DIRORSIZE,
+ PL_WINNT_FILENAME
+} pl_winNT_mainstate;
+
+typedef union {
+ enum {
+ PL_WINNT_TIME_PRESPACE = 0,
+ PL_WINNT_TIME_TIME
+ } time;
+ enum {
+ PL_WINNT_DIRORSIZE_PRESPACE = 0,
+ PL_WINNT_DIRORSIZE_CONTENT
+ } dirorsize;
+ enum {
+ PL_WINNT_FILENAME_PRESPACE = 0,
+ PL_WINNT_FILENAME_CONTENT,
+ PL_WINNT_FILENAME_WINEOL
+ } filename;
+} pl_winNT_substate;
+
+/* This struct is used in wildcard downloading - for parsing LIST response */
+struct ftp_parselist_data {
+ enum {
+ OS_TYPE_UNKNOWN = 0,
+ OS_TYPE_UNIX,
+ OS_TYPE_WIN_NT
+ } os_type;
+
+ union {
+ struct {
+ pl_unix_mainstate main;
+ pl_unix_substate sub;
+ } UNIX;
+
+ struct {
+ pl_winNT_mainstate main;
+ pl_winNT_substate sub;
+ } NT;
+ } state;
+
+ CURLcode error;
+ struct curl_fileinfo *file_data;
+ unsigned int item_length;
+ size_t item_offset;
+ struct {
+ size_t filename;
+ size_t user;
+ size_t group;
+ size_t time;
+ size_t perm;
+ size_t symlink_target;
+ } offsets;
+};
+
+struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
+{
+ return calloc(1, sizeof(struct ftp_parselist_data));
+}
+
+
+void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
+{
+ if(*pl_data)
+ free(*pl_data);
+ *pl_data = NULL;
+}
+
+
+CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
+{
+ return pl_data->error;
+}
+
+
+#define FTP_LP_MALFORMATED_PERM 0x01000000
+
+static int ftp_pl_get_permission(const char *str)
+{
+ int permissions = 0;
+ /* USER */
+ if(str[0] == 'r')
+ permissions |= 1 << 8;
+ else if(str[0] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[1] == 'w')
+ permissions |= 1 << 7;
+ else if(str[1] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+
+ if(str[2] == 'x')
+ permissions |= 1 << 6;
+ else if(str[2] == 's') {
+ permissions |= 1 << 6;
+ permissions |= 1 << 11;
+ }
+ else if(str[2] == 'S')
+ permissions |= 1 << 11;
+ else if(str[2] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ /* GROUP */
+ if(str[3] == 'r')
+ permissions |= 1 << 5;
+ else if(str[3] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[4] == 'w')
+ permissions |= 1 << 4;
+ else if(str[4] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[5] == 'x')
+ permissions |= 1 << 3;
+ else if(str[5] == 's') {
+ permissions |= 1 << 3;
+ permissions |= 1 << 10;
+ }
+ else if(str[5] == 'S')
+ permissions |= 1 << 10;
+ else if(str[5] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ /* others */
+ if(str[6] == 'r')
+ permissions |= 1 << 2;
+ else if(str[6] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[7] == 'w')
+ permissions |= 1 << 1;
+ else if(str[7] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+ if(str[8] == 'x')
+ permissions |= 1;
+ else if(str[8] == 't') {
+ permissions |= 1;
+ permissions |= 1 << 9;
+ }
+ else if(str[8] == 'T')
+ permissions |= 1 << 9;
+ else if(str[8] != '-')
+ permissions |= FTP_LP_MALFORMATED_PERM;
+
+ return permissions;
+}
+
+static void PL_ERROR(struct connectdata *conn, CURLcode err)
+{
+ struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
+ struct ftp_parselist_data *parser = tmpdata->parser;
+ if(parser->file_data)
+ Curl_fileinfo_dtor(NULL, parser->file_data);
+ parser->file_data = NULL;
+ parser->error = err;
+}
+
+static bool ftp_pl_gettime(struct ftp_parselist_data *parser, char *string)
+{
+ (void)parser;
+ (void)string;
+ /* TODO
+ * There could be possible parse timestamp from server. Leaving unimplemented
+ * for now.
+ * If you want implement this, please add CURLFINFOFLAG_KNOWN_TIME flag to
+ * parser->file_data->flags
+ *
+ * Ftp servers are giving usually these formats:
+ * Apr 11 1998 (unknown time.. set it to 00:00:00?)
+ * Apr 11 12:21 (unknown year -> set it to NOW() time?)
+ * 08-05-09 02:49PM (ms-dos format)
+ * 20100421092538 -> for MLST/MLSD response
+ */
+
+ return FALSE;
+}
+
+static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
+ struct curl_fileinfo *finfo)
+{
+ curl_fnmatch_callback compare;
+ struct WildcardData *wc = &conn->data->wildcard;
+ struct ftp_wc_tmpdata *tmpdata = wc->tmp;
+ struct curl_llist *llist = wc->filelist;
+ struct ftp_parselist_data *parser = tmpdata->parser;
+ bool add = TRUE;
+
+ /* move finfo pointers to b_data */
+ char *str = finfo->b_data;
+ finfo->filename = str + parser->offsets.filename;
+ finfo->strings.group = parser->offsets.group ?
+ str + parser->offsets.group : NULL;
+ finfo->strings.perm = parser->offsets.perm ?
+ str + parser->offsets.perm : NULL;
+ finfo->strings.target = parser->offsets.symlink_target ?
+ str + parser->offsets.symlink_target : NULL;
+ finfo->strings.time = str + parser->offsets.time;
+ finfo->strings.user = parser->offsets.user ?
+ str + parser->offsets.user : NULL;
+
+ /* get correct fnmatch callback */
+ compare = conn->data->set.fnmatch;
+ if(!compare)
+ compare = Curl_fnmatch;
+
+ /* filter pattern-corresponding filenames */
+ if(compare(conn->data->set.fnmatch_data, wc->pattern,
+ finfo->filename) == 0) {
+ /* discard symlink which is containing multiple " -> " */
+ if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
+ (strstr(finfo->strings.target, " -> "))) {
+ add = FALSE;
+ }
+ }
+ else {
+ add = FALSE;
+ }
+
+ if(add) {
+ if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
+ Curl_fileinfo_dtor(NULL, finfo);
+ tmpdata->parser->file_data = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ Curl_fileinfo_dtor(NULL, finfo);
+ }
+
+ tmpdata->parser->file_data = NULL;
+ return CURLE_OK;
+}
+
+size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
+ void *connptr)
+{
+ size_t bufflen = size*nmemb;
+ struct connectdata *conn = (struct connectdata *)connptr;
+ struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
+ struct ftp_parselist_data *parser = tmpdata->parser;
+ struct curl_fileinfo *finfo;
+ unsigned long i = 0;
+ CURLcode rc;
+
+ if(parser->error) { /* error in previous call */
+ /* scenario:
+ * 1. call => OK..
+ * 2. call => OUT_OF_MEMORY (or other error)
+ * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
+ * in wc_statemach()
+ */
+ return bufflen;
+ }
+
+ if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
+ /* considering info about FILE response format */
+ parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ?
+ OS_TYPE_WIN_NT : OS_TYPE_UNIX;
+ }
+
+ while(i < bufflen) { /* FSM */
+
+ char c = buffer[i];
+ if(!parser->file_data) { /* tmp file data is not allocated yet */
+ parser->file_data = Curl_fileinfo_alloc();
+ if(!parser->file_data) {
+ parser->error = CURLE_OUT_OF_MEMORY;
+ return bufflen;
+ }
+ parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
+ if(!parser->file_data->b_data) {
+ PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
+ return bufflen;
+ }
+ parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
+ parser->item_offset = 0;
+ parser->item_length = 0;
+ }
+
+ finfo = parser->file_data;
+ finfo->b_data[finfo->b_used++] = c;
+
+ if(finfo->b_used >= finfo->b_size - 1) {
+ /* if it is important, extend buffer space for file data */
+ char *tmp = realloc(finfo->b_data,
+ finfo->b_size + FTP_BUFFER_ALLOCSIZE);
+ if(tmp) {
+ finfo->b_size += FTP_BUFFER_ALLOCSIZE;
+ finfo->b_data = tmp;
+ }
+ else {
+ Curl_fileinfo_dtor(NULL, parser->file_data);
+ parser->file_data = NULL;
+ parser->error = CURLE_OUT_OF_MEMORY;
+ PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
+ return bufflen;
+ }
+ }
+
+ switch (parser->os_type) {
+ case OS_TYPE_UNIX:
+ switch (parser->state.UNIX.main) {
+ case PL_UNIX_TOTALSIZE:
+ switch(parser->state.UNIX.sub.total_dirsize) {
+ case PL_UNIX_TOTALSIZE_INIT:
+ if(c == 't') {
+ parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING;
+ parser->item_length++;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ /* start FSM again not considering size of directory */
+ finfo->b_used = 0;
+ i--;
+ }
+ break;
+ case PL_UNIX_TOTALSIZE_READING:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->item_length--;
+ finfo->b_used--;
+ }
+ else if(c == '\n') {
+ finfo->b_data[parser->item_length - 1] = 0;
+ if(strncmp("total ", finfo->b_data, 6) == 0) {
+ char *endptr = finfo->b_data+6;
+ /* here we can deal with directory size, pass the leading white
+ spaces and then the digits */
+ while(ISSPACE(*endptr))
+ endptr++;
+ while(ISDIGIT(*endptr))
+ endptr++;
+ if(*endptr != 0) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ finfo->b_used = 0;
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_FILETYPE:
+ switch (c) {
+ case '-':
+ finfo->filetype = CURLFILETYPE_FILE;
+ break;
+ case 'd':
+ finfo->filetype = CURLFILETYPE_DIRECTORY;
+ break;
+ case 'l':
+ finfo->filetype = CURLFILETYPE_SYMLINK;
+ break;
+ case 'p':
+ finfo->filetype = CURLFILETYPE_NAMEDPIPE;
+ break;
+ case 's':
+ finfo->filetype = CURLFILETYPE_SOCKET;
+ break;
+ case 'c':
+ finfo->filetype = CURLFILETYPE_DEVICE_CHAR;
+ break;
+ case 'b':
+ finfo->filetype = CURLFILETYPE_DEVICE_BLOCK;
+ break;
+ case 'D':
+ finfo->filetype = CURLFILETYPE_DOOR;
+ break;
+ default:
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ parser->state.UNIX.main = PL_UNIX_PERMISSION;
+ parser->item_length = 0;
+ parser->item_offset = 1;
+ break;
+ case PL_UNIX_PERMISSION:
+ parser->item_length++;
+ if(parser->item_length <= 9) {
+ if(!strchr("rwx-tTsS", c)) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ else if(parser->item_length == 10) {
+ unsigned int perm;
+ if(c != ' ') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ finfo->b_data[10] = 0; /* terminate permissions */
+ perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
+ if(perm & FTP_LP_MALFORMATED_PERM) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM;
+ parser->file_data->perm = perm;
+ parser->offsets.perm = parser->item_offset;
+
+ parser->item_length = 0;
+ parser->state.UNIX.main = PL_UNIX_HLINKS;
+ parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
+ }
+ break;
+ case PL_UNIX_HLINKS:
+ switch(parser->state.UNIX.sub.hlinks) {
+ case PL_UNIX_HLINKS_PRESPACE:
+ if(c != ' ') {
+ if(c >= '0' && c <= '9') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_HLINKS_NUMBER:
+ parser->item_length ++;
+ if(c == ' ') {
+ char *p;
+ long int hlinks;
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
+ if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
+ parser->file_data->hardlinks = hlinks;
+ }
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ parser->state.UNIX.main = PL_UNIX_USER;
+ parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
+ }
+ else if(c < '0' || c > '9') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_USER:
+ switch(parser->state.UNIX.sub.user) {
+ case PL_UNIX_USER_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
+ }
+ break;
+ case PL_UNIX_USER_PARSING:
+ parser->item_length++;
+ if(c == ' ') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.user = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_GROUP;
+ parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
+ parser->item_offset = 0;
+ parser->item_length = 0;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_GROUP:
+ switch(parser->state.UNIX.sub.group) {
+ case PL_UNIX_GROUP_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
+ }
+ break;
+ case PL_UNIX_GROUP_NAME:
+ parser->item_length++;
+ if(c == ' ') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.group = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_SIZE;
+ parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
+ parser->item_offset = 0;
+ parser->item_length = 0;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_SIZE:
+ switch(parser->state.UNIX.sub.size) {
+ case PL_UNIX_SIZE_PRESPACE:
+ if(c != ' ') {
+ if(c >= '0' && c <= '9') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_SIZE_NUMBER:
+ parser->item_length++;
+ if(c == ' ') {
+ char *p;
+ curl_off_t fsize;
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
+ if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
+ fsize != CURL_OFF_T_MIN) {
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->file_data->size = fsize;
+ }
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ parser->state.UNIX.main = PL_UNIX_TIME;
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
+ }
+ else if(!ISDIGIT(c)) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_TIME:
+ switch(parser->state.UNIX.sub.time) {
+ case PL_UNIX_TIME_PREPART1:
+ if(c != ' ') {
+ if(ISALNUM(c)) {
+ parser->item_offset = finfo->b_used -1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_TIME_PART1:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
+ }
+ else if(!ISALNUM(c) && c != '.') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_UNIX_TIME_PREPART2:
+ parser->item_length++;
+ if(c != ' ') {
+ if(ISALNUM(c)) {
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_TIME_PART2:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
+ }
+ else if(!ISALNUM(c) && c != '.') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_UNIX_TIME_PREPART3:
+ parser->item_length++;
+ if(c != ' ') {
+ if(ISALNUM(c)) {
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_TIME_PART3:
+ parser->item_length++;
+ if(c == ' ') {
+ finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
+ parser->offsets.time = parser->item_offset;
+ if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) {
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
+ }
+ if(finfo->filetype == CURLFILETYPE_SYMLINK) {
+ parser->state.UNIX.main = PL_UNIX_SYMLINK;
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILENAME;
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
+ }
+ }
+ else if(!ISALNUM(c) && c != '.' && c != ':') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_FILENAME:
+ switch(parser->state.UNIX.sub.filename) {
+ case PL_UNIX_FILENAME_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
+ }
+ break;
+ case PL_UNIX_FILENAME_NAME:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->item_length--;
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
+ }
+ else if(c == '\n') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ rc = ftp_pl_insert_finfo(conn, finfo);
+ if(rc) {
+ PL_ERROR(conn, rc);
+ return bufflen;
+ }
+ }
+ break;
+ case PL_UNIX_FILENAME_WINDOWSEOL:
+ if(c == '\n') {
+ finfo->b_data[parser->item_offset + parser->item_length] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ rc = ftp_pl_insert_finfo(conn, finfo);
+ if(rc) {
+ PL_ERROR(conn, rc);
+ return bufflen;
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_SYMLINK:
+ switch(parser->state.UNIX.sub.symlink) {
+ case PL_UNIX_SYMLINK_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_NAME:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
+ }
+ else if(c == '\r' || c == '\n') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET1:
+ parser->item_length++;
+ if(c == '-') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
+ }
+ else if(c == '\r' || c == '\n') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET2:
+ parser->item_length++;
+ if(c == '>') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
+ }
+ else if(c == '\r' || c == '\n') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET3:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
+ /* now place where is symlink following */
+ finfo->b_data[parser->item_offset + parser->item_length - 4] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ }
+ else if(c == '\r' || c == '\n') {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET4:
+ if(c != '\r' && c != '\n') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_UNIX_SYMLINK_TARGET:
+ parser->item_length ++;
+ if(c == '\r') {
+ parser->item_length --;
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
+ }
+ else if(c == '\n') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.symlink_target = parser->item_offset;
+ rc = ftp_pl_insert_finfo(conn, finfo);
+ if(rc) {
+ PL_ERROR(conn, rc);
+ return bufflen;
+ }
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ }
+ break;
+ case PL_UNIX_SYMLINK_WINDOWSEOL:
+ if(c == '\n') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.symlink_target = parser->item_offset;
+ rc = ftp_pl_insert_finfo(conn, finfo);
+ if(rc) {
+ PL_ERROR(conn, rc);
+ return bufflen;
+ }
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case OS_TYPE_WIN_NT:
+ switch(parser->state.NT.main) {
+ case PL_WINNT_DATE:
+ parser->item_length++;
+ if(parser->item_length < 9) {
+ if(!strchr("0123456789-", c)) { /* only simple control */
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ else if(parser->item_length == 9) {
+ if(c == ' ') {
+ parser->state.NT.main = PL_WINNT_TIME;
+ parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ case PL_WINNT_TIME:
+ parser->item_length++;
+ switch(parser->state.NT.sub.time) {
+ case PL_WINNT_TIME_PRESPACE:
+ if(!ISSPACE(c)) {
+ parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
+ }
+ break;
+ case PL_WINNT_TIME_TIME:
+ if(c == ' ') {
+ parser->offsets.time = parser->item_offset;
+ finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
+ parser->state.NT.main = PL_WINNT_DIRORSIZE;
+ parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
+ parser->item_length = 0;
+ }
+ else if(!strchr("APM0123456789:", c)) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ case PL_WINNT_DIRORSIZE:
+ switch(parser->state.NT.sub.dirorsize) {
+ case PL_WINNT_DIRORSIZE_PRESPACE:
+ if(c == ' ') {
+
+ }
+ else {
+ parser->item_offset = finfo->b_used - 1;
+ parser->item_length = 1;
+ parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
+ }
+ break;
+ case PL_WINNT_DIRORSIZE_CONTENT:
+ parser->item_length ++;
+ if(c == ' ') {
+ finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
+ if(strcmp("<DIR>", finfo->b_data + parser->item_offset) == 0) {
+ finfo->filetype = CURLFILETYPE_DIRECTORY;
+ finfo->size = 0;
+ }
+ else {
+ char *endptr;
+ finfo->size = curlx_strtoofft(finfo->b_data +
+ parser->item_offset,
+ &endptr, 10);
+ if(!*endptr) {
+ if(finfo->size == CURL_OFF_T_MAX ||
+ finfo->size == CURL_OFF_T_MIN) {
+ if(errno == ERANGE) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ /* correct file type */
+ parser->file_data->filetype = CURLFILETYPE_FILE;
+ }
+
+ parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->item_length = 0;
+ parser->state.NT.main = PL_WINNT_FILENAME;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ break;
+ }
+ break;
+ case PL_WINNT_FILENAME:
+ switch (parser->state.NT.sub.filename) {
+ case PL_WINNT_FILENAME_PRESPACE:
+ if(c != ' ') {
+ parser->item_offset = finfo->b_used -1;
+ parser->item_length = 1;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
+ }
+ break;
+ case PL_WINNT_FILENAME_CONTENT:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
+ finfo->b_data[finfo->b_used - 1] = 0;
+ }
+ else if(c == '\n') {
+ parser->offsets.filename = parser->item_offset;
+ finfo->b_data[finfo->b_used - 1] = 0;
+ parser->offsets.filename = parser->item_offset;
+ rc = ftp_pl_insert_finfo(conn, finfo);
+ if(rc) {
+ PL_ERROR(conn, rc);
+ return bufflen;
+ }
+ parser->state.NT.main = PL_WINNT_DATE;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ break;
+ case PL_WINNT_FILENAME_WINEOL:
+ if(c == '\n') {
+ parser->offsets.filename = parser->item_offset;
+ rc = ftp_pl_insert_finfo(conn, finfo);
+ if(rc) {
+ PL_ERROR(conn, rc);
+ return bufflen;
+ }
+ parser->state.NT.main = PL_WINNT_DATE;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ default:
+ return bufflen+1;
+ }
+
+ i++;
+ }
+
+ return bufflen;
+}
+
+#endif /* CURL_DISABLE_FTP */
diff --git a/external/libcurl_android/jni/libcurl/lib/ftplistparser.h b/external/libcurl_android/jni/libcurl/lib/ftplistparser.h
new file mode 100755
index 00000000..96764e2a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/ftplistparser.h
@@ -0,0 +1,41 @@
+#ifndef HEADER_CURL_FTPLISTPARSER_H
+#define HEADER_CURL_FTPLISTPARSER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+
+/* WRITEFUNCTION callback for parsing LIST responses */
+size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
+ void *connptr);
+
+struct ftp_parselist_data; /* defined inside ftplibparser.c */
+
+CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data);
+
+struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void);
+
+void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data);
+
+#endif /* CURL_DISABLE_FTP */
+#endif /* HEADER_CURL_FTPLISTPARSER_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/getenv.c b/external/libcurl_android/jni/libcurl/lib/getenv.c
new file mode 100755
index 00000000..36215aab
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/getenv.c
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "curl_memory.h"
+
+#include "memdebug.h"
+
+static
+char *GetEnv(const char *variable)
+{
+#ifdef _WIN32_WCE
+ return NULL;
+#else
+#ifdef WIN32
+ char env[MAX_PATH]; /* MAX_PATH is from windef.h */
+ char *temp = getenv(variable);
+ env[0] = '\0';
+ if(temp != NULL)
+ ExpandEnvironmentStringsA(temp, env, sizeof(env));
+ return (env[0] != '\0')?strdup(env):NULL;
+#else
+ char *env = getenv(variable);
+ return (env && env[0])?strdup(env):NULL;
+#endif
+#endif
+}
+
+char *curl_getenv(const char *v)
+{
+ return GetEnv(v);
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/getinfo.c b/external/libcurl_android/jni/libcurl/lib/getinfo.c
new file mode 100755
index 00000000..8905d361
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/getinfo.c
@@ -0,0 +1,381 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "getinfo.h"
+
+#include "curl_memory.h"
+#include "vtls/vtls.h"
+#include "connect.h" /* Curl_getconnectinfo() */
+#include "progress.h"
+
+/* Make this the last #include */
+#include "memdebug.h"
+
+/*
+ * This is supposed to be called in the beginning of a perform() session
+ * and should reset all session-info variables
+ */
+CURLcode Curl_initinfo(struct SessionHandle *data)
+{
+ struct Progress *pro = &data->progress;
+ struct PureInfo *info =&data->info;
+
+ pro->t_nslookup = 0;
+ pro->t_connect = 0;
+ pro->t_appconnect = 0;
+ pro->t_pretransfer = 0;
+ pro->t_starttransfer = 0;
+ pro->timespent = 0;
+ pro->t_redirect = 0;
+
+ info->httpcode = 0;
+ info->httpproxycode = 0;
+ info->httpversion = 0;
+ info->filetime = -1; /* -1 is an illegal time and thus means unknown */
+ info->timecond = FALSE;
+
+ if(info->contenttype)
+ free(info->contenttype);
+ info->contenttype = NULL;
+
+ info->header_size = 0;
+ info->request_size = 0;
+ info->numconnects = 0;
+
+ info->conn_primary_ip[0] = '\0';
+ info->conn_local_ip[0] = '\0';
+ info->conn_primary_port = 0;
+ info->conn_local_port = 0;
+
+ return CURLE_OK;
+}
+
+static CURLcode getinfo_char(struct SessionHandle *data, CURLINFO info,
+ char **param_charp)
+{
+ switch(info) {
+ case CURLINFO_EFFECTIVE_URL:
+ *param_charp = data->change.url?data->change.url:(char *)"";
+ break;
+ case CURLINFO_CONTENT_TYPE:
+ *param_charp = data->info.contenttype;
+ break;
+ case CURLINFO_PRIVATE:
+ *param_charp = (char *) data->set.private_data;
+ break;
+ case CURLINFO_FTP_ENTRY_PATH:
+ /* Return the entrypath string from the most recent connection.
+ This pointer was copied from the connectdata structure by FTP.
+ The actual string may be free()ed by subsequent libcurl calls so
+ it must be copied to a safer area before the next libcurl call.
+ Callers must never free it themselves. */
+ *param_charp = data->state.most_recent_ftp_entrypath;
+ break;
+ case CURLINFO_REDIRECT_URL:
+ /* Return the URL this request would have been redirected to if that
+ option had been enabled! */
+ *param_charp = data->info.wouldredirect;
+ break;
+ case CURLINFO_PRIMARY_IP:
+ /* Return the ip address of the most recent (primary) connection */
+ *param_charp = data->info.conn_primary_ip;
+ break;
+ case CURLINFO_LOCAL_IP:
+ /* Return the source/local ip address of the most recent (primary)
+ connection */
+ *param_charp = data->info.conn_local_ip;
+ break;
+ case CURLINFO_RTSP_SESSION_ID:
+ *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
+ break;
+
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
+ long *param_longp)
+{
+ curl_socket_t sockfd;
+
+ union {
+ unsigned long *to_ulong;
+ long *to_long;
+ } lptr;
+
+ switch(info) {
+ case CURLINFO_RESPONSE_CODE:
+ *param_longp = data->info.httpcode;
+ break;
+ case CURLINFO_HTTP_CONNECTCODE:
+ *param_longp = data->info.httpproxycode;
+ break;
+ case CURLINFO_FILETIME:
+ *param_longp = data->info.filetime;
+ break;
+ case CURLINFO_HEADER_SIZE:
+ *param_longp = data->info.header_size;
+ break;
+ case CURLINFO_REQUEST_SIZE:
+ *param_longp = data->info.request_size;
+ break;
+ case CURLINFO_SSL_VERIFYRESULT:
+ *param_longp = data->set.ssl.certverifyresult;
+ break;
+ case CURLINFO_REDIRECT_COUNT:
+ *param_longp = data->set.followlocation;
+ break;
+ case CURLINFO_HTTPAUTH_AVAIL:
+ lptr.to_long = param_longp;
+ *lptr.to_ulong = data->info.httpauthavail;
+ break;
+ case CURLINFO_PROXYAUTH_AVAIL:
+ lptr.to_long = param_longp;
+ *lptr.to_ulong = data->info.proxyauthavail;
+ break;
+ case CURLINFO_OS_ERRNO:
+ *param_longp = data->state.os_errno;
+ break;
+ case CURLINFO_NUM_CONNECTS:
+ *param_longp = data->info.numconnects;
+ break;
+ case CURLINFO_LASTSOCKET:
+ sockfd = Curl_getconnectinfo(data, NULL);
+
+ /* note: this is not a good conversion for systems with 64 bit sockets and
+ 32 bit longs */
+ if(sockfd != CURL_SOCKET_BAD)
+ *param_longp = (long)sockfd;
+ else
+ /* this interface is documented to return -1 in case of badness, which
+ may not be the same as the CURL_SOCKET_BAD value */
+ *param_longp = -1;
+ break;
+ case CURLINFO_PRIMARY_PORT:
+ /* Return the (remote) port of the most recent (primary) connection */
+ *param_longp = data->info.conn_primary_port;
+ break;
+ case CURLINFO_LOCAL_PORT:
+ /* Return the local port of the most recent (primary) connection */
+ *param_longp = data->info.conn_local_port;
+ break;
+ case CURLINFO_CONDITION_UNMET:
+ /* return if the condition prevented the document to get transferred */
+ *param_longp = data->info.timecond ? 1L : 0L;
+ break;
+ case CURLINFO_RTSP_CLIENT_CSEQ:
+ *param_longp = data->state.rtsp_next_client_CSeq;
+ break;
+ case CURLINFO_RTSP_SERVER_CSEQ:
+ *param_longp = data->state.rtsp_next_server_CSeq;
+ break;
+ case CURLINFO_RTSP_CSEQ_RECV:
+ *param_longp = data->state.rtsp_CSeq_recv;
+ break;
+
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode getinfo_double(struct SessionHandle *data, CURLINFO info,
+ double *param_doublep)
+{
+ switch(info) {
+ case CURLINFO_TOTAL_TIME:
+ *param_doublep = data->progress.timespent;
+ break;
+ case CURLINFO_NAMELOOKUP_TIME:
+ *param_doublep = data->progress.t_nslookup;
+ break;
+ case CURLINFO_CONNECT_TIME:
+ *param_doublep = data->progress.t_connect;
+ break;
+ case CURLINFO_APPCONNECT_TIME:
+ *param_doublep = data->progress.t_appconnect;
+ break;
+ case CURLINFO_PRETRANSFER_TIME:
+ *param_doublep = data->progress.t_pretransfer;
+ break;
+ case CURLINFO_STARTTRANSFER_TIME:
+ *param_doublep = data->progress.t_starttransfer;
+ break;
+ case CURLINFO_SIZE_UPLOAD:
+ *param_doublep = (double)data->progress.uploaded;
+ break;
+ case CURLINFO_SIZE_DOWNLOAD:
+ *param_doublep = (double)data->progress.downloaded;
+ break;
+ case CURLINFO_SPEED_DOWNLOAD:
+ *param_doublep = (double)data->progress.dlspeed;
+ break;
+ case CURLINFO_SPEED_UPLOAD:
+ *param_doublep = (double)data->progress.ulspeed;
+ break;
+ case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
+ *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
+ (double)data->progress.size_dl:-1;
+ break;
+ case CURLINFO_CONTENT_LENGTH_UPLOAD:
+ *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
+ (double)data->progress.size_ul:-1;
+ break;
+ case CURLINFO_REDIRECT_TIME:
+ *param_doublep = data->progress.t_redirect;
+ break;
+
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
+ struct curl_slist **param_slistp)
+{
+ union {
+ struct curl_certinfo * to_certinfo;
+ struct curl_slist * to_slist;
+ } ptr;
+
+ switch(info) {
+ case CURLINFO_SSL_ENGINES:
+ *param_slistp = Curl_ssl_engines_list(data);
+ break;
+ case CURLINFO_COOKIELIST:
+ *param_slistp = Curl_cookie_list(data);
+ break;
+ case CURLINFO_CERTINFO:
+ /* Return the a pointer to the certinfo struct. Not really an slist
+ pointer but we can pretend it is here */
+ ptr.to_certinfo = &data->info.certs;
+ *param_slistp = ptr.to_slist;
+ break;
+ case CURLINFO_TLS_SESSION:
+ {
+ struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
+ param_slistp;
+ struct curl_tlssessioninfo *tsi = &data->tsi;
+ struct connectdata *conn = data->easy_conn;
+ unsigned int sockindex = 0;
+ void *internals = NULL;
+
+ *tsip = tsi;
+ tsi->backend = CURLSSLBACKEND_NONE;
+ tsi->internals = NULL;
+
+ if(!conn)
+ break;
+
+ /* Find the active ("in use") SSL connection, if any */
+ while((sockindex < sizeof(conn->ssl) / sizeof(conn->ssl[0])) &&
+ (!conn->ssl[sockindex].use))
+ sockindex++;
+
+ if(sockindex == sizeof(conn->ssl) / sizeof(conn->ssl[0]))
+ break; /* no SSL session found */
+
+ /* Return the TLS session information from the relevant backend */
+#ifdef USE_SSLEAY
+ internals = conn->ssl[sockindex].ctx;
+#endif
+#ifdef USE_GNUTLS
+ internals = conn->ssl[sockindex].session;
+#endif
+#ifdef USE_NSS
+ internals = conn->ssl[sockindex].handle;
+#endif
+#ifdef USE_QSOSSL
+ internals = conn->ssl[sockindex].handle;
+#endif
+#ifdef USE_GSKIT
+ internals = conn->ssl[sockindex].handle;
+#endif
+ if(internals) {
+ tsi->backend = Curl_ssl_backend();
+ tsi->internals = internals;
+ }
+ /* NOTE: For other SSL backends, it is not immediately clear what data
+ to return from 'struct ssl_connect_data'; thus, for now we keep the
+ backend as CURLSSLBACKEND_NONE in those cases, which should be
+ interpreted as "not supported" */
+ }
+ break;
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
+{
+ va_list arg;
+ long *param_longp=NULL;
+ double *param_doublep=NULL;
+ char **param_charp=NULL;
+ struct curl_slist **param_slistp=NULL;
+ int type;
+ /* default return code is to error out! */
+ CURLcode ret = CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(!data)
+ return ret;
+
+ va_start(arg, info);
+
+ type = CURLINFO_TYPEMASK & (int)info;
+ switch(type) {
+ case CURLINFO_STRING:
+ param_charp = va_arg(arg, char **);
+ if(NULL != param_charp)
+ ret = getinfo_char(data, info, param_charp);
+ break;
+ case CURLINFO_LONG:
+ param_longp = va_arg(arg, long *);
+ if(NULL != param_longp)
+ ret = getinfo_long(data, info, param_longp);
+ break;
+ case CURLINFO_DOUBLE:
+ param_doublep = va_arg(arg, double *);
+ if(NULL != param_doublep)
+ ret = getinfo_double(data, info, param_doublep);
+ break;
+ case CURLINFO_SLIST:
+ param_slistp = va_arg(arg, struct curl_slist **);
+ if(NULL != param_slistp)
+ ret = getinfo_slist(data, info, param_slistp);
+ break;
+ default:
+ break;
+ }
+
+ va_end(arg);
+ return ret;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/getinfo.h b/external/libcurl_android/jni/libcurl/lib/getinfo.h
new file mode 100755
index 00000000..3879ff73
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/getinfo.h
@@ -0,0 +1,27 @@
+#ifndef HEADER_CURL_GETINFO_H
+#define HEADER_CURL_GETINFO_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...);
+CURLcode Curl_initinfo(struct SessionHandle *data);
+
+#endif /* HEADER_CURL_GETINFO_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/gopher.c b/external/libcurl_android/jni/libcurl/lib/gopher.c
new file mode 100755
index 00000000..b1dd65ff
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/gopher.c
@@ -0,0 +1,169 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_GOPHER
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+
+#include "progress.h"
+#include "strequal.h"
+#include "gopher.h"
+#include "rawstr.h"
+#include "select.h"
+#include "url.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Forward declarations.
+ */
+
+static CURLcode gopher_do(struct connectdata *conn, bool *done);
+
+/*
+ * Gopher protocol handler.
+ * This is also a nice simple template to build off for simple
+ * connect-command-download protocols.
+ */
+
+const struct Curl_handler Curl_handler_gopher = {
+ "GOPHER", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ gopher_do, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_GOPHER, /* defport */
+ CURLPROTO_GOPHER, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+static CURLcode gopher_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result=CURLE_OK;
+ struct SessionHandle *data=conn->data;
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+
+ curl_off_t *bytecount = &data->req.bytecount;
+ char *path = data->state.path;
+ char *sel;
+ char *sel_org = NULL;
+ ssize_t amount, k;
+
+ *done = TRUE; /* unconditionally */
+
+ /* Create selector. Degenerate cases: / and /1 => convert to "" */
+ if(strlen(path) <= 2)
+ sel = (char *)"";
+ else {
+ char *newp;
+ size_t j, i;
+ int len;
+
+ /* Otherwise, drop / and the first character (i.e., item type) ... */
+ newp = path;
+ newp+=2;
+
+ /* ... then turn ? into TAB for search servers, Veronica, etc. ... */
+ j = strlen(newp);
+ for(i=0; i<j; i++)
+ if(newp[i] == '?')
+ newp[i] = '\x09';
+
+ /* ... and finally unescape */
+ sel = curl_easy_unescape(data, newp, 0, &len);
+ if(!sel)
+ return CURLE_OUT_OF_MEMORY;
+ sel_org = sel;
+ }
+
+ /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is
+ sent, which could be sizeable with long selectors. */
+ k = curlx_uztosz(strlen(sel));
+
+ for(;;) {
+ result = Curl_write(conn, sockfd, sel, k, &amount);
+ if(CURLE_OK == result) { /* Which may not have written it all! */
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
+ if(result) {
+ Curl_safefree(sel_org);
+ return result;
+ }
+ k -= amount;
+ sel += amount;
+ if(k < 1)
+ break; /* but it did write it all */
+ }
+ else {
+ failf(data, "Failed sending Gopher request");
+ Curl_safefree(sel_org);
+ return result;
+ }
+ /* Don't busyloop. The entire loop thing is a work-around as it causes a
+ BLOCKING behavior which is a NO-NO. This function should rather be
+ split up in a do and a doing piece where the pieces that aren't
+ possible to send now will be sent in the doing function repeatedly
+ until the entire request is sent.
+
+ Wait a while for the socket to be writable. Note that this doesn't
+ acknowledge the timeout.
+ */
+ Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 100);
+ }
+
+ Curl_safefree(sel_org);
+
+ /* We can use Curl_sendf to send the terminal \r\n relatively safely and
+ save allocing another string/doing another _write loop. */
+ result = Curl_sendf(sockfd, conn, "\r\n");
+ if(result != CURLE_OK) {
+ failf(data, "Failed sending Gopher request");
+ return result;
+ }
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
+ if(result)
+ return result;
+
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
+ -1, NULL); /* no upload */
+ return CURLE_OK;
+}
+#endif /*CURL_DISABLE_GOPHER*/
diff --git a/external/libcurl_android/jni/libcurl/lib/gopher.h b/external/libcurl_android/jni/libcurl/lib/gopher.h
new file mode 100755
index 00000000..38bbc4b7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/gopher.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_GOPHER_H
+#define HEADER_CURL_GOPHER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef CURL_DISABLE_GOPHER
+extern const struct Curl_handler Curl_handler_gopher;
+#endif
+
+#endif /* HEADER_CURL_GOPHER_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/hash.c b/external/libcurl_android/jni/libcurl/lib/hash.c
new file mode 100755
index 00000000..4a12e1a7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hash.c
@@ -0,0 +1,400 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "hash.h"
+#include "llist.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static void
+hash_element_dtor(void *user, void *element)
+{
+ struct curl_hash *h = (struct curl_hash *) user;
+ struct curl_hash_element *e = (struct curl_hash_element *) element;
+
+ Curl_safefree(e->key);
+
+ if(e->ptr) {
+ h->dtor(e->ptr);
+ e->ptr = NULL;
+ }
+
+ e->key_len = 0;
+
+ free(e);
+}
+
+/* return 1 on error, 0 is fine */
+int
+Curl_hash_init(struct curl_hash *h,
+ int slots,
+ hash_function hfunc,
+ comp_function comparator,
+ curl_hash_dtor dtor)
+{
+ int i;
+
+ if(!slots || !hfunc || !comparator ||!dtor) {
+ return 1; /* failure */
+ }
+
+ h->hash_func = hfunc;
+ h->comp_func = comparator;
+ h->dtor = dtor;
+ h->size = 0;
+ h->slots = slots;
+
+ h->table = malloc(slots * sizeof(struct curl_llist *));
+ if(h->table) {
+ for(i = 0; i < slots; ++i) {
+ h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
+ if(!h->table[i]) {
+ while(i--) {
+ Curl_llist_destroy(h->table[i], NULL);
+ h->table[i] = NULL;
+ }
+ free(h->table);
+ h->table = NULL;
+ h->slots = 0;
+ return 1; /* failure */
+ }
+ }
+ return 0; /* fine */
+ }
+ else {
+ h->slots = 0;
+ return 1; /* failure */
+ }
+}
+
+struct curl_hash *
+Curl_hash_alloc(int slots,
+ hash_function hfunc,
+ comp_function comparator,
+ curl_hash_dtor dtor)
+{
+ struct curl_hash *h;
+
+ if(!slots || !hfunc || !comparator ||!dtor) {
+ return NULL; /* failure */
+ }
+
+ h = malloc(sizeof(struct curl_hash));
+ if(h) {
+ if(Curl_hash_init(h, slots, hfunc, comparator, dtor)) {
+ /* failure */
+ free(h);
+ h = NULL;
+ }
+ }
+
+ return h;
+}
+
+
+
+static struct curl_hash_element *
+mk_hash_element(const void *key, size_t key_len, const void *p)
+{
+ struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element));
+
+ if(he) {
+ void *dupkey = malloc(key_len);
+ if(dupkey) {
+ /* copy the key */
+ memcpy(dupkey, key, key_len);
+
+ he->key = dupkey;
+ he->key_len = key_len;
+ he->ptr = (void *) p;
+ }
+ else {
+ /* failed to duplicate the key, free memory and fail */
+ free(he);
+ he = NULL;
+ }
+ }
+ return he;
+}
+
+#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)]
+
+/* Insert the data in the hash. If there already was a match in the hash,
+ * that data is replaced.
+ *
+ * @unittest: 1305
+ */
+void *
+Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
+{
+ struct curl_hash_element *he;
+ struct curl_llist_element *le;
+ struct curl_llist *l = FETCH_LIST (h, key, key_len);
+
+ for(le = l->head; le; le = le->next) {
+ he = (struct curl_hash_element *) le->ptr;
+ if(h->comp_func(he->key, he->key_len, key, key_len)) {
+ Curl_llist_remove(l, le, (void *)h);
+ --h->size;
+ break;
+ }
+ }
+
+ he = mk_hash_element(key, key_len, p);
+ if(he) {
+ if(Curl_llist_insert_next(l, l->tail, he)) {
+ ++h->size;
+ return p; /* return the new entry */
+ }
+ /*
+ * Couldn't insert it, destroy the 'he' element and the key again. We
+ * don't call hash_element_dtor() since that would also call the
+ * "destructor" for the actual data 'p'. When we fail, we shall not touch
+ * that data.
+ */
+ free(he->key);
+ free(he);
+ }
+
+ return NULL; /* failure */
+}
+
+/* remove the identified hash entry, returns non-zero on failure */
+int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
+{
+ struct curl_llist_element *le;
+ struct curl_hash_element *he;
+ struct curl_llist *l = FETCH_LIST(h, key, key_len);
+
+ for(le = l->head; le; le = le->next) {
+ he = le->ptr;
+ if(h->comp_func(he->key, he->key_len, key, key_len)) {
+ Curl_llist_remove(l, le, (void *) h);
+ --h->size;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+void *
+Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
+{
+ struct curl_llist_element *le;
+ struct curl_hash_element *he;
+ struct curl_llist *l;
+
+ if(h) {
+ l = FETCH_LIST(h, key, key_len);
+ for(le = l->head; le; le = le->next) {
+ he = le->ptr;
+ if(h->comp_func(he->key, he->key_len, key, key_len)) {
+ return he->ptr;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST)
+void
+Curl_hash_apply(curl_hash *h, void *user,
+ void (*cb)(void *user, void *ptr))
+{
+ struct curl_llist_element *le;
+ int i;
+
+ for(i = 0; i < h->slots; ++i) {
+ for(le = (h->table[i])->head;
+ le;
+ le = le->next) {
+ curl_hash_element *el = le->ptr;
+ cb(user, el->ptr);
+ }
+ }
+}
+#endif
+
+void
+Curl_hash_clean(struct curl_hash *h)
+{
+ int i;
+
+ for(i = 0; i < h->slots; ++i) {
+ Curl_llist_destroy(h->table[i], (void *) h);
+ h->table[i] = NULL;
+ }
+
+ Curl_safefree(h->table);
+ h->size = 0;
+ h->slots = 0;
+}
+
+void
+Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
+ int (*comp)(void *, void *))
+{
+ struct curl_llist_element *le;
+ struct curl_llist_element *lnext;
+ struct curl_llist *list;
+ int i;
+
+ if(!h)
+ return;
+
+ for(i = 0; i < h->slots; ++i) {
+ list = h->table[i];
+ le = list->head; /* get first list entry */
+ while(le) {
+ struct curl_hash_element *he = le->ptr;
+ lnext = le->next;
+ /* ask the callback function if we shall remove this entry or not */
+ if(comp(user, he->ptr)) {
+ Curl_llist_remove(list, le, (void *) h);
+ --h->size; /* one less entry in the hash now */
+ }
+ le = lnext;
+ }
+ }
+}
+
+void
+Curl_hash_destroy(struct curl_hash *h)
+{
+ if(!h)
+ return;
+
+ Curl_hash_clean(h);
+
+ free(h);
+}
+
+size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num)
+{
+ const char* key_str = (const char *) key;
+ const char *end = key_str + key_length;
+ unsigned long h = 5381;
+
+ while(key_str < end) {
+ h += h << 5;
+ h ^= (unsigned long) *key_str++;
+ }
+
+ return (h % slots_num);
+}
+
+size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, size_t key2_len)
+{
+ char *key1 = (char *)k1;
+ char *key2 = (char *)k2;
+
+ if(key1_len == key2_len &&
+ *key1 == *key2 &&
+ memcmp(key1, key2, key1_len) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void Curl_hash_start_iterate(struct curl_hash *hash,
+ struct curl_hash_iterator *iter)
+{
+ iter->hash = hash;
+ iter->slot_index = 0;
+ iter->current_element = NULL;
+}
+
+struct curl_hash_element *
+Curl_hash_next_element(struct curl_hash_iterator *iter)
+{
+ int i;
+ struct curl_hash *h = iter->hash;
+
+ /* Get the next element in the current list, if any */
+ if(iter->current_element)
+ iter->current_element = iter->current_element->next;
+
+ /* If we have reached the end of the list, find the next one */
+ if(!iter->current_element) {
+ for(i = iter->slot_index;i < h->slots;i++) {
+ if(h->table[i]->head) {
+ iter->current_element = h->table[i]->head;
+ iter->slot_index = i+1;
+ break;
+ }
+ }
+ }
+
+ if(iter->current_element) {
+ struct curl_hash_element *he = iter->current_element->ptr;
+ return he;
+ }
+ else {
+ iter->current_element = NULL;
+ return NULL;
+ }
+}
+
+#if 0 /* useful function for debugging hashes and their contents */
+void Curl_hash_print(struct curl_hash *h,
+ void (*func)(void *))
+{
+ struct curl_hash_iterator iter;
+ struct curl_hash_element *he;
+ int last_index = -1;
+
+ if(!h)
+ return;
+
+ fprintf(stderr, "=Hash dump=\n");
+
+ Curl_hash_start_iterate(h, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ if(iter.slot_index != last_index) {
+ fprintf(stderr, "index %d:", iter.slot_index);
+ if(last_index >= 0) {
+ fprintf(stderr, "\n");
+ }
+ last_index = iter.slot_index;
+ }
+
+ if(func)
+ func(he->ptr);
+ else
+ fprintf(stderr, " [%p]", (void *)he->ptr);
+
+ he = Curl_hash_next_element(&iter);
+ }
+ fprintf(stderr, "\n");
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/hash.h b/external/libcurl_android/jni/libcurl/lib/hash.h
new file mode 100755
index 00000000..aa935d4e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hash.h
@@ -0,0 +1,106 @@
+#ifndef HEADER_CURL_HASH_H
+#define HEADER_CURL_HASH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <stddef.h>
+
+#include "llist.h"
+
+/* Hash function prototype */
+typedef size_t (*hash_function) (void* key,
+ size_t key_length,
+ size_t slots_num);
+
+/*
+ Comparator function prototype. Compares two keys.
+*/
+typedef size_t (*comp_function) (void* key1,
+ size_t key1_len,
+ void*key2,
+ size_t key2_len);
+
+typedef void (*curl_hash_dtor)(void *);
+
+struct curl_hash {
+ struct curl_llist **table;
+
+ /* Hash function to be used for this hash table */
+ hash_function hash_func;
+
+ /* Comparator function to compare keys */
+ comp_function comp_func;
+ curl_hash_dtor dtor;
+ int slots;
+ size_t size;
+};
+
+struct curl_hash_element {
+ void *ptr;
+ char *key;
+ size_t key_len;
+};
+
+struct curl_hash_iterator {
+ struct curl_hash *hash;
+ int slot_index;
+ struct curl_llist_element *current_element;
+};
+
+int Curl_hash_init(struct curl_hash *h,
+ int slots,
+ hash_function hfunc,
+ comp_function comparator,
+ curl_hash_dtor dtor);
+
+struct curl_hash *Curl_hash_alloc(int slots,
+ hash_function hfunc,
+ comp_function comparator,
+ curl_hash_dtor dtor);
+
+void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p);
+int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len);
+void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len);
+void Curl_hash_apply(struct curl_hash *h, void *user,
+ void (*cb)(void *user, void *ptr));
+int Curl_hash_count(struct curl_hash *h);
+void Curl_hash_clean(struct curl_hash *h);
+void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
+ int (*comp)(void *, void *));
+void Curl_hash_destroy(struct curl_hash *h);
+
+size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num);
+size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2,
+ size_t key2_len);
+
+void Curl_hash_start_iterate(struct curl_hash *hash,
+ struct curl_hash_iterator *iter);
+struct curl_hash_element *
+Curl_hash_next_element(struct curl_hash_iterator *iter);
+
+void Curl_hash_print(struct curl_hash *h,
+ void (*func)(void *));
+
+
+#endif /* HEADER_CURL_HASH_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/hmac.c b/external/libcurl_android/jni/libcurl/lib/hmac.c
new file mode 100755
index 00000000..dace8203
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hmac.c
@@ -0,0 +1,133 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC2104 Keyed-Hashing for Message Authentication
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+
+#include "curl_hmac.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Generic HMAC algorithm.
+ *
+ * This module computes HMAC digests based on any hash function. Parameters
+ * and computing procedures are set-up dynamically at HMAC computation
+ * context initialisation.
+ */
+
+static const unsigned char hmac_ipad = 0x36;
+static const unsigned char hmac_opad = 0x5C;
+
+
+
+HMAC_context *
+Curl_HMAC_init(const HMAC_params * hashparams,
+ const unsigned char * key,
+ unsigned int keylen)
+{
+ size_t i;
+ HMAC_context * ctxt;
+ unsigned char * hkey;
+ unsigned char b;
+
+ /* Create HMAC context. */
+ i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize +
+ hashparams->hmac_resultlen;
+ ctxt = malloc(i);
+
+ if(!ctxt)
+ return ctxt;
+
+ ctxt->hmac_hash = hashparams;
+ ctxt->hmac_hashctxt1 = (void *) (ctxt + 1);
+ ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 +
+ hashparams->hmac_ctxtsize);
+
+ /* If the key is too long, replace it by its hash digest. */
+ if(keylen > hashparams->hmac_maxkeylen) {
+ (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen);
+ hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize;
+ (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1);
+ key = hkey;
+ keylen = hashparams->hmac_resultlen;
+ }
+
+ /* Prime the two hash contexts with the modified key. */
+ (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
+ (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2);
+
+ for(i = 0; i < keylen; i++) {
+ b = (unsigned char)(*key ^ hmac_ipad);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1);
+ b = (unsigned char)(*key++ ^ hmac_opad);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1);
+ }
+
+ for(; i < hashparams->hmac_maxkeylen; i++) {
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1);
+ }
+
+ /* Done, return pointer to HMAC context. */
+ return ctxt;
+}
+
+int Curl_HMAC_update(HMAC_context * ctxt,
+ const unsigned char * data,
+ unsigned int len)
+{
+ /* Update first hash calculation. */
+ (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len);
+ return 0;
+}
+
+
+int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result)
+{
+ const HMAC_params * hashparams = ctxt->hmac_hash;
+
+ /* Do not get result if called with a null parameter: only release
+ storage. */
+
+ if(!result)
+ result = (unsigned char *) ctxt->hmac_hashctxt2 +
+ ctxt->hmac_hash->hmac_ctxtsize;
+
+ (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1);
+ (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2,
+ result, hashparams->hmac_resultlen);
+ (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2);
+ free((char *) ctxt);
+ return 0;
+}
+
+#endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/external/libcurl_android/jni/libcurl/lib/hostasyn.c b/external/libcurl_android/jni/libcurl/lib/hostasyn.c
new file mode 100755
index 00000000..8151b671
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hostasyn.c
@@ -0,0 +1,157 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for builds using asynchronous name resolves
+ **********************************************************************/
+#ifdef CURLRES_ASYNCH
+
+/*
+ * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread()
+ * or getaddrinfo_thread() when we got the name resolved (or not!).
+ *
+ * If the status argument is CURL_ASYNC_SUCCESS, this function takes
+ * ownership of the Curl_addrinfo passed, storing the resolved data
+ * in the DNS cache.
+ *
+ * The storage operation locks and unlocks the DNS cache.
+ */
+CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+ int status,
+ struct Curl_addrinfo *ai)
+{
+ struct Curl_dns_entry *dns = NULL;
+ CURLcode rc = CURLE_OK;
+
+ conn->async.status = status;
+
+ if(CURL_ASYNC_SUCCESS == status) {
+ if(ai) {
+ struct SessionHandle *data = conn->data;
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ dns = Curl_cache_addr(data, ai,
+ conn->async.hostname,
+ conn->async.port);
+ if(!dns) {
+ /* failed to store, cleanup and return error */
+ Curl_freeaddrinfo(ai);
+ rc = CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ }
+ else {
+ rc = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ conn->async.dns = dns;
+
+ /* Set async.done TRUE last in this function since it may be used multi-
+ threaded and once this is TRUE the other thread may read fields from the
+ async struct */
+ conn->async.done = TRUE;
+
+ /* ipv4: The input hostent struct will be freed by ares when we return from
+ this function */
+ return rc;
+}
+
+/* Call this function after Curl_connect() has returned async=TRUE and
+ then a successful name resolve has been received.
+
+ Note: this function disconnects and frees the conn data in case of
+ resolve failure */
+CURLcode Curl_async_resolved(struct connectdata *conn,
+ bool *protocol_done)
+{
+ CURLcode code;
+
+ if(conn->async.dns) {
+ conn->dns_entry = conn->async.dns;
+ conn->async.dns = NULL;
+ }
+
+ code = Curl_setup_conn(conn, protocol_done);
+
+ if(code)
+ /* We're not allowed to return failure with memory left allocated
+ in the connectdata struct, free those here */
+ Curl_disconnect(conn, FALSE); /* close the connection */
+
+ return code;
+}
+
+/*
+ * Curl_getaddrinfo() is the generic low-level name resolve API within this
+ * source file. There are several versions of this function - for different
+ * name resolve layers (selected at build-time). They all take this same set
+ * of arguments
+ */
+Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
+}
+
+#endif /* CURLRES_ASYNCH */
diff --git a/external/libcurl_android/jni/libcurl/lib/hostcheck.c b/external/libcurl_android/jni/libcurl/lib/hostcheck.c
new file mode 100755
index 00000000..42eb2ee7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hostcheck.c
@@ -0,0 +1,148 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \
+ defined(USE_GSKIT)
+/* these backends use functions from this file */
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "hostcheck.h"
+#include "rawstr.h"
+#include "inet_pton.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Match a hostname against a wildcard pattern.
+ * E.g.
+ * "foo.host.com" matches "*.host.com".
+ *
+ * We use the matching rule described in RFC6125, section 6.4.3.
+ * http://tools.ietf.org/html/rfc6125#section-6.4.3
+ *
+ * In addition: ignore trailing dots in the host names and wildcards, so that
+ * the names are used normalized. This is what the browsers do.
+ *
+ * Do not allow wildcard matching on IP numbers. There are apparently
+ * certificates being used with an IP address in the CN field, thus making no
+ * apparent distinction between a name and an IP. We need to detect the use of
+ * an IP address and not wildcard match on such names.
+ *
+ * NOTE: hostmatch() gets called with copied buffers so that it can modify the
+ * contents at will.
+ */
+
+static int hostmatch(char *hostname, char *pattern)
+{
+ const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
+ int wildcard_enabled;
+ size_t prefixlen, suffixlen;
+ struct in_addr ignored;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 si6;
+#endif
+
+ /* normalize pattern and hostname by stripping off trailing dots */
+ size_t len = strlen(hostname);
+ if(hostname[len-1]=='.')
+ hostname[len-1]=0;
+ len = strlen(pattern);
+ if(pattern[len-1]=='.')
+ pattern[len-1]=0;
+
+ pattern_wildcard = strchr(pattern, '*');
+ if(pattern_wildcard == NULL)
+ return Curl_raw_equal(pattern, hostname) ?
+ CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+
+ /* detect IP address as hostname and fail the match if so */
+ if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
+ return CURL_HOST_NOMATCH;
+#ifdef ENABLE_IPV6
+ else if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0)
+ return CURL_HOST_NOMATCH;
+#endif
+
+ /* We require at least 2 dots in pattern to avoid too wide wildcard
+ match. */
+ wildcard_enabled = 1;
+ pattern_label_end = strchr(pattern, '.');
+ if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
+ pattern_wildcard > pattern_label_end ||
+ Curl_raw_nequal(pattern, "xn--", 4)) {
+ wildcard_enabled = 0;
+ }
+ if(!wildcard_enabled)
+ return Curl_raw_equal(pattern, hostname) ?
+ CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+
+ hostname_label_end = strchr(hostname, '.');
+ if(hostname_label_end == NULL ||
+ !Curl_raw_equal(pattern_label_end, hostname_label_end))
+ return CURL_HOST_NOMATCH;
+
+ /* The wildcard must match at least one character, so the left-most
+ label of the hostname is at least as large as the left-most label
+ of the pattern. */
+ if(hostname_label_end - hostname < pattern_label_end - pattern)
+ return CURL_HOST_NOMATCH;
+
+ prefixlen = pattern_wildcard - pattern;
+ suffixlen = pattern_label_end - (pattern_wildcard+1);
+ return Curl_raw_nequal(pattern, hostname, prefixlen) &&
+ Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen,
+ suffixlen) ?
+ CURL_HOST_MATCH : CURL_HOST_NOMATCH;
+}
+
+int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
+{
+ char *matchp;
+ char *hostp;
+ int res = 0;
+ if(!match_pattern || !*match_pattern ||
+ !hostname || !*hostname) /* sanity check */
+ ;
+ else {
+ matchp = strdup(match_pattern);
+ if(matchp) {
+ hostp = strdup(hostname);
+ if(hostp) {
+ if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
+ res= 1;
+ free(hostp);
+ }
+ free(matchp);
+ }
+ }
+
+ return res;
+}
+
+#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT */
diff --git a/external/libcurl_android/jni/libcurl/lib/hostcheck.h b/external/libcurl_android/jni/libcurl/lib/hostcheck.h
new file mode 100755
index 00000000..f4a517a8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hostcheck.h
@@ -0,0 +1,32 @@
+#ifndef HEADER_CURL_HOSTCHECK_H
+#define HEADER_CURL_HOSTCHECK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+#define CURL_HOST_NOMATCH 0
+#define CURL_HOST_MATCH 1
+int Curl_cert_hostcheck(const char *match_pattern, const char *hostname);
+
+#endif /* HEADER_CURL_HOSTCHECK_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/hostip.c b/external/libcurl_android/jni/libcurl/lib/hostip.c
new file mode 100755
index 00000000..73b3f820
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hostip.c
@@ -0,0 +1,857 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "inet_ntop.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#if defined(CURLRES_SYNCH) && \
+ defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)
+/* alarm-based timeouts can only be used with all the dependencies satisfied */
+#define USE_ALARM_TIMEOUT
+#endif
+
+/*
+ * hostip.c explained
+ * ==================
+ *
+ * The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c
+ * source file are these:
+ *
+ * CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use
+ * that. The host may not be able to resolve IPv6, but we don't really have to
+ * take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4
+ * defined.
+ *
+ * CURLRES_ARES - is defined if libcurl is built to use c-ares for
+ * asynchronous name resolves. This can be Windows or *nix.
+ *
+ * CURLRES_THREADED - is defined if libcurl is built to run under (native)
+ * Windows, and then the name resolve will be done in a new thread, and the
+ * supported API will be the same as for ares-builds.
+ *
+ * If any of the two previous are defined, CURLRES_ASYNCH is defined too. If
+ * libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is
+ * defined.
+ *
+ * The host*.c sources files are split up like this:
+ *
+ * hostip.c - method-independent resolver functions and utility functions
+ * hostasyn.c - functions for asynchronous name resolves
+ * hostsyn.c - functions for synchronous name resolves
+ * hostip4.c - ipv4-specific functions
+ * hostip6.c - ipv6-specific functions
+ *
+ * The two asynchronous name resolver backends are implemented in:
+ * asyn-ares.c - functions for ares-using name resolves
+ * asyn-thread.c - functions for threaded name resolves
+
+ * The hostip.h is the united header file for all this. It defines the
+ * CURLRES_* defines based on the config*.h and curl_setup.h defines.
+ */
+
+/* These two symbols are for the global DNS cache */
+static struct curl_hash hostname_cache;
+static int host_cache_initialized;
+
+static void freednsentry(void *freethis);
+
+/*
+ * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
+ * Global DNS cache is general badness. Do not use. This will be removed in
+ * a future version. Use the share interface instead!
+ *
+ * Returns a struct curl_hash pointer on success, NULL on failure.
+ */
+struct curl_hash *Curl_global_host_cache_init(void)
+{
+ int rc = 0;
+ if(!host_cache_initialized) {
+ rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str,
+ Curl_str_key_compare, freednsentry);
+ if(!rc)
+ host_cache_initialized = 1;
+ }
+ return rc?NULL:&hostname_cache;
+}
+
+/*
+ * Destroy and cleanup the global DNS cache
+ */
+void Curl_global_host_cache_dtor(void)
+{
+ if(host_cache_initialized) {
+ /* first make sure that any custom "CURLOPT_RESOLVE" names are
+ cleared off */
+ Curl_hostcache_clean(NULL, &hostname_cache);
+ /* then free the remaining hash completely */
+ Curl_hash_clean(&hostname_cache);
+ host_cache_initialized = 0;
+ }
+}
+
+/*
+ * Return # of adresses in a Curl_addrinfo struct
+ */
+int Curl_num_addresses(const Curl_addrinfo *addr)
+{
+ int i = 0;
+ while(addr) {
+ addr = addr->ai_next;
+ i++;
+ }
+ return i;
+}
+
+/*
+ * Curl_printable_address() returns a printable version of the 1st address
+ * given in the 'ai' argument. The result will be stored in the buf that is
+ * bufsize bytes big.
+ *
+ * If the conversion fails, it returns NULL.
+ */
+const char *
+Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
+{
+ const struct sockaddr_in *sa4;
+ const struct in_addr *ipaddr4;
+#ifdef ENABLE_IPV6
+ const struct sockaddr_in6 *sa6;
+ const struct in6_addr *ipaddr6;
+#endif
+
+ switch (ai->ai_family) {
+ case AF_INET:
+ sa4 = (const void *)ai->ai_addr;
+ ipaddr4 = &sa4->sin_addr;
+ return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf,
+ bufsize);
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ sa6 = (const void *)ai->ai_addr;
+ ipaddr6 = &sa6->sin6_addr;
+ return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf,
+ bufsize);
+#endif
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * Return a hostcache id string for the provided host + port, to be used by
+ * the DNS caching.
+ */
+static char *
+create_hostcache_id(const char *name, int port)
+{
+ /* create and return the new allocated entry */
+ char *id = aprintf("%s:%d", name, port);
+ char *ptr = id;
+ if(ptr) {
+ /* lower case the name part */
+ while(*ptr && (*ptr != ':')) {
+ *ptr = (char)TOLOWER(*ptr);
+ ptr++;
+ }
+ }
+ return id;
+}
+
+struct hostcache_prune_data {
+ long cache_timeout;
+ time_t now;
+};
+
+/*
+ * This function is set as a callback to be called for every entry in the DNS
+ * cache when we want to prune old unused entries.
+ *
+ * Returning non-zero means remove the entry, return 0 to keep it in the
+ * cache.
+ */
+static int
+hostcache_timestamp_remove(void *datap, void *hc)
+{
+ struct hostcache_prune_data *data =
+ (struct hostcache_prune_data *) datap;
+ struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
+
+ return !c->inuse && (data->now - c->timestamp >= data->cache_timeout);
+}
+
+/*
+ * Prune the DNS cache. This assumes that a lock has already been taken.
+ */
+static void
+hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now)
+{
+ struct hostcache_prune_data user;
+
+ user.cache_timeout = cache_timeout;
+ user.now = now;
+
+ Curl_hash_clean_with_criterium(hostcache,
+ (void *) &user,
+ hostcache_timestamp_remove);
+}
+
+/*
+ * Library-wide function for pruning the DNS cache. This function takes and
+ * returns the appropriate locks.
+ */
+void Curl_hostcache_prune(struct SessionHandle *data)
+{
+ time_t now;
+
+ if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
+ /* cache forever means never prune, and NULL hostcache means
+ we can't do it */
+ return;
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ time(&now);
+
+ /* Remove outdated and unused entries from the hostcache */
+ hostcache_prune(data->dns.hostcache,
+ data->set.dns_cache_timeout,
+ now);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+}
+
+/*
+ * Check if the entry should be pruned. Assumes a locked cache.
+ */
+static int
+remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns)
+{
+ struct hostcache_prune_data user;
+
+ if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache ||
+ dns->inuse)
+ /* cache forever means never prune, and NULL hostcache means we can't do
+ it, if it still is in use then we leave it */
+ return 0;
+
+ time(&user.now);
+ user.cache_timeout = data->set.dns_cache_timeout;
+
+ if(!hostcache_timestamp_remove(&user,dns) )
+ return 0;
+
+ Curl_hash_clean_with_criterium(data->dns.hostcache,
+ (void *) &user,
+ hostcache_timestamp_remove);
+
+ return 1;
+}
+
+
+#ifdef HAVE_SIGSETJMP
+/* Beware this is a global and unique instance. This is used to store the
+ return address that we can jump back to from inside a signal handler. This
+ is not thread-safe stuff. */
+sigjmp_buf curl_jmpenv;
+#endif
+
+/*
+ * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
+ *
+ * Curl_resolv() checks initially and multi_runsingle() checks each time
+ * it discovers the handle in the state WAITRESOLVE whether the hostname
+ * has already been resolved and the address has already been stored in
+ * the DNS cache. This short circuits waiting for a lot of pending
+ * lookups for the same hostname requested by different handles.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ */
+struct Curl_dns_entry *
+Curl_fetch_addr(struct connectdata *conn,
+ const char *hostname,
+ int port, int *stale)
+{
+ char *entry_id = NULL;
+ struct Curl_dns_entry *dns = NULL;
+ size_t entry_len;
+ struct SessionHandle *data = conn->data;
+
+ /* Create an entry id, based upon the hostname and port */
+ entry_id = create_hostcache_id(hostname, port);
+ /* If we can't create the entry id, fail */
+ if(!entry_id)
+ return dns;
+
+ entry_len = strlen(entry_id);
+
+ /* See if its already in our dns cache */
+ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
+
+ /* free the allocated entry_id again */
+ free(entry_id);
+
+ /* See whether the returned entry is stale. Done before we release lock */
+ *stale = remove_entry_if_stale(data, dns);
+ if(*stale)
+ dns = NULL; /* the memory deallocation is being handled by the hash */
+
+ return dns;
+}
+
+/*
+ * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
+ *
+ * When calling Curl_resolv() has resulted in a response with a returned
+ * address, we call this function to store the information in the dns
+ * cache etc
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
+ */
+struct Curl_dns_entry *
+Curl_cache_addr(struct SessionHandle *data,
+ Curl_addrinfo *addr,
+ const char *hostname,
+ int port)
+{
+ char *entry_id;
+ size_t entry_len;
+ struct Curl_dns_entry *dns;
+ struct Curl_dns_entry *dns2;
+
+ /* Create an entry id, based upon the hostname and port */
+ entry_id = create_hostcache_id(hostname, port);
+ /* If we can't create the entry id, fail */
+ if(!entry_id)
+ return NULL;
+ entry_len = strlen(entry_id);
+
+ /* Create a new cache entry */
+ dns = calloc(1, sizeof(struct Curl_dns_entry));
+ if(!dns) {
+ free(entry_id);
+ return NULL;
+ }
+
+ dns->inuse = 0; /* init to not used */
+ dns->addr = addr; /* this is the address(es) */
+ time(&dns->timestamp);
+ if(dns->timestamp == 0)
+ dns->timestamp = 1; /* zero indicates that entry isn't in hash table */
+
+ /* Store the resolved data in our DNS cache. */
+ dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1,
+ (void *)dns);
+ if(!dns2) {
+ free(dns);
+ free(entry_id);
+ return NULL;
+ }
+
+ dns = dns2;
+ dns->inuse++; /* mark entry as in-use */
+
+ /* free the allocated entry_id */
+ free(entry_id);
+
+ return dns;
+}
+
+/*
+ * Curl_resolv() is the main name resolve function within libcurl. It resolves
+ * a name and returns a pointer to the entry in the 'entry' argument (if one
+ * is provided). This function might return immediately if we're using asynch
+ * resolves. See the return codes.
+ *
+ * The cache entry we return will get its 'inuse' counter increased when this
+ * function is used. You MUST call Curl_resolv_unlock() later (when you're
+ * done using this struct) to decrease the counter again.
+ *
+ * In debug mode, we specifically test for an interface name "LocalHost"
+ * and resolve "localhost" instead as a means to permit test cases
+ * to connect to a local test server with any host name.
+ *
+ * Return codes:
+ *
+ * CURLRESOLV_ERROR (-1) = error, no pointer
+ * CURLRESOLV_RESOLVED (0) = OK, pointer provided
+ * CURLRESOLV_PENDING (1) = waiting for response, no pointer
+ */
+
+int Curl_resolv(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ struct Curl_dns_entry **entry)
+{
+ struct Curl_dns_entry *dns = NULL;
+ struct SessionHandle *data = conn->data;
+ CURLcode result;
+ int stale, rc = CURLRESOLV_ERROR; /* default to failure */
+
+ *entry = NULL;
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ dns = Curl_fetch_addr(conn, hostname, port, &stale);
+
+ infof(data, "Hostname was %sfound in DNS cache\n", dns||stale?"":"NOT ");
+ if(stale)
+ infof(data, "Hostname in DNS cache was stale, zapped\n");
+
+
+ if(dns) {
+ dns->inuse++; /* we use it! */
+ rc = CURLRESOLV_RESOLVED;
+ }
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ if(!dns) {
+ /* The entry was not in the cache. Resolve it to IP address */
+
+ Curl_addrinfo *addr;
+ int respwait;
+
+ /* Check what IP specifics the app has requested and if we can provide it.
+ * If not, bail out. */
+ if(!Curl_ipvalid(conn))
+ return CURLRESOLV_ERROR;
+
+ /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
+ non-zero value indicating that we need to wait for the response to the
+ resolve call */
+ addr = Curl_getaddrinfo(conn,
+#ifdef DEBUGBUILD
+ (data->set.str[STRING_DEVICE]
+ && !strcmp(data->set.str[STRING_DEVICE],
+ "LocalHost"))?"localhost":
+#endif
+ hostname, port, &respwait);
+
+ if(!addr) {
+ if(respwait) {
+ /* the response to our resolve call will come asynchronously at
+ a later time, good or bad */
+ /* First, check that we haven't received the info by now */
+ result = Curl_resolver_is_resolved(conn, &dns);
+ if(result) /* error detected */
+ return CURLRESOLV_ERROR;
+ if(dns)
+ rc = CURLRESOLV_RESOLVED; /* pointer provided */
+ else
+ rc = CURLRESOLV_PENDING; /* no info yet */
+ }
+ }
+ else {
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ /* we got a response, store it in the cache */
+ dns = Curl_cache_addr(data, addr, hostname, port);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ if(!dns)
+ /* returned failure, bail out nicely */
+ Curl_freeaddrinfo(addr);
+ else
+ rc = CURLRESOLV_RESOLVED;
+ }
+ }
+
+ *entry = dns;
+
+ return rc;
+}
+
+#ifdef USE_ALARM_TIMEOUT
+/*
+ * This signal handler jumps back into the main libcurl code and continues
+ * execution. This effectively causes the remainder of the application to run
+ * within a signal handler which is nonportable and could lead to problems.
+ */
+static
+RETSIGTYPE alarmfunc(int sig)
+{
+ /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
+ (void)sig;
+ siglongjmp(curl_jmpenv, 1);
+ return;
+}
+#endif /* USE_ALARM_TIMEOUT */
+
+/*
+ * Curl_resolv_timeout() is the same as Curl_resolv() but specifies a
+ * timeout. This function might return immediately if we're using asynch
+ * resolves. See the return codes.
+ *
+ * The cache entry we return will get its 'inuse' counter increased when this
+ * function is used. You MUST call Curl_resolv_unlock() later (when you're
+ * done using this struct) to decrease the counter again.
+ *
+ * If built with a synchronous resolver and use of signals is not
+ * disabled by the application, then a nonzero timeout will cause a
+ * timeout after the specified number of milliseconds. Otherwise, timeout
+ * is ignored.
+ *
+ * Return codes:
+ *
+ * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired
+ * CURLRESOLV_ERROR (-1) = error, no pointer
+ * CURLRESOLV_RESOLVED (0) = OK, pointer provided
+ * CURLRESOLV_PENDING (1) = waiting for response, no pointer
+ */
+
+int Curl_resolv_timeout(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ struct Curl_dns_entry **entry,
+ long timeoutms)
+{
+#ifdef USE_ALARM_TIMEOUT
+#ifdef HAVE_SIGACTION
+ struct sigaction keep_sigact; /* store the old struct here */
+ volatile bool keep_copysig = FALSE; /* wether old sigact has been saved */
+ struct sigaction sigact;
+#else
+#ifdef HAVE_SIGNAL
+ void (*keep_sigact)(int); /* store the old handler here */
+#endif /* HAVE_SIGNAL */
+#endif /* HAVE_SIGACTION */
+ volatile long timeout;
+ volatile unsigned int prev_alarm = 0;
+ struct SessionHandle *data = conn->data;
+#endif /* USE_ALARM_TIMEOUT */
+ int rc;
+
+ *entry = NULL;
+
+ if(timeoutms < 0)
+ /* got an already expired timeout */
+ return CURLRESOLV_TIMEDOUT;
+
+#ifdef USE_ALARM_TIMEOUT
+ if(data->set.no_signal)
+ /* Ignore the timeout when signals are disabled */
+ timeout = 0;
+ else
+ timeout = timeoutms;
+
+ if(!timeout)
+ /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
+ return Curl_resolv(conn, hostname, port, entry);
+
+ if(timeout < 1000)
+ /* The alarm() function only provides integer second resolution, so if
+ we want to wait less than one second we must bail out already now. */
+ return CURLRESOLV_TIMEDOUT;
+
+ /*************************************************************
+ * Set signal handler to catch SIGALRM
+ * Store the old value to be able to set it back later!
+ *************************************************************/
+#ifdef HAVE_SIGACTION
+ sigaction(SIGALRM, NULL, &sigact);
+ keep_sigact = sigact;
+ keep_copysig = TRUE; /* yes, we have a copy */
+ sigact.sa_handler = alarmfunc;
+#ifdef SA_RESTART
+ /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
+ sigact.sa_flags &= ~SA_RESTART;
+#endif
+ /* now set the new struct */
+ sigaction(SIGALRM, &sigact, NULL);
+#else /* HAVE_SIGACTION */
+ /* no sigaction(), revert to the much lamer signal() */
+#ifdef HAVE_SIGNAL
+ keep_sigact = signal(SIGALRM, alarmfunc);
+#endif
+#endif /* HAVE_SIGACTION */
+
+ /* alarm() makes a signal get sent when the timeout fires off, and that
+ will abort system calls */
+ prev_alarm = alarm(curlx_sltoui(timeout/1000L));
+
+ /* This allows us to time-out from the name resolver, as the timeout
+ will generate a signal and we will siglongjmp() from that here.
+ This technique has problems (see alarmfunc).
+ This should be the last thing we do before calling Curl_resolv(),
+ as otherwise we'd have to worry about variables that get modified
+ before we invoke Curl_resolv() (and thus use "volatile"). */
+ if(sigsetjmp(curl_jmpenv, 1)) {
+ /* this is coming from a siglongjmp() after an alarm signal */
+ failf(data, "name lookup timed out");
+ rc = CURLRESOLV_ERROR;
+ goto clean_up;
+ }
+
+#else
+#ifndef CURLRES_ASYNCH
+ if(timeoutms)
+ infof(conn->data, "timeout on name lookup is not supported\n");
+#else
+ (void)timeoutms; /* timeoutms not used with an async resolver */
+#endif
+#endif /* USE_ALARM_TIMEOUT */
+
+ /* Perform the actual name resolution. This might be interrupted by an
+ * alarm if it takes too long.
+ */
+ rc = Curl_resolv(conn, hostname, port, entry);
+
+#ifdef USE_ALARM_TIMEOUT
+clean_up:
+
+ if(!prev_alarm)
+ /* deactivate a possibly active alarm before uninstalling the handler */
+ alarm(0);
+
+#ifdef HAVE_SIGACTION
+ if(keep_copysig) {
+ /* we got a struct as it looked before, now put that one back nice
+ and clean */
+ sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
+ }
+#else
+#ifdef HAVE_SIGNAL
+ /* restore the previous SIGALRM handler */
+ signal(SIGALRM, keep_sigact);
+#endif
+#endif /* HAVE_SIGACTION */
+
+ /* switch back the alarm() to either zero or to what it was before minus
+ the time we spent until now! */
+ if(prev_alarm) {
+ /* there was an alarm() set before us, now put it back */
+ unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
+
+ /* the alarm period is counted in even number of seconds */
+ unsigned long alarm_set = prev_alarm - elapsed_ms/1000;
+
+ if(!alarm_set ||
+ ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
+ /* if the alarm time-left reached zero or turned "negative" (counted
+ with unsigned values), we should fire off a SIGALRM here, but we
+ won't, and zero would be to switch it off so we never set it to
+ less than 1! */
+ alarm(1);
+ rc = CURLRESOLV_TIMEDOUT;
+ failf(data, "Previous alarm fired off!");
+ }
+ else
+ alarm((unsigned int)alarm_set);
+ }
+#endif /* USE_ALARM_TIMEOUT */
+
+ return rc;
+}
+
+/*
+ * Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
+ * made, the struct may be destroyed due to pruning. It is important that only
+ * one unlock is made for each Curl_resolv() call.
+ *
+ * May be called with 'data' == NULL for global cache.
+ */
+void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
+{
+ DEBUGASSERT(dns && (dns->inuse>0));
+
+ if(data && data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ dns->inuse--;
+ /* only free if nobody is using AND it is not in hostcache (timestamp ==
+ 0) */
+ if(dns->inuse == 0 && dns->timestamp == 0) {
+ Curl_freeaddrinfo(dns->addr);
+ free(dns);
+ }
+
+ if(data && data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+}
+
+/*
+ * File-internal: free a cache dns entry.
+ */
+static void freednsentry(void *freethis)
+{
+ struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
+
+ /* mark the entry as not in hostcache */
+ p->timestamp = 0;
+ if(p->inuse == 0) {
+ Curl_freeaddrinfo(p->addr);
+ free(p);
+ }
+}
+
+/*
+ * Curl_mk_dnscache() creates a new DNS cache and returns the handle for it.
+ */
+struct curl_hash *Curl_mk_dnscache(void)
+{
+ return Curl_hash_alloc(7, Curl_hash_str, Curl_str_key_compare, freednsentry);
+}
+
+static int hostcache_inuse(void *data, void *hc)
+{
+ struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
+
+ if(c->inuse == 1)
+ Curl_resolv_unlock(data, c);
+
+ return 1; /* free all entries */
+}
+
+/*
+ * Curl_hostcache_clean()
+ *
+ * This _can_ be called with 'data' == NULL but then of course no locking
+ * can be done!
+ */
+
+void Curl_hostcache_clean(struct SessionHandle *data,
+ struct curl_hash *hash)
+{
+ /* Entries added to the hostcache with the CURLOPT_RESOLVE function are
+ * still present in the cache with the inuse counter set to 1. Detect them
+ * and cleanup!
+ */
+ Curl_hash_clean_with_criterium(hash, data, hostcache_inuse);
+}
+
+
+CURLcode Curl_loadhostpairs(struct SessionHandle *data)
+{
+ struct curl_slist *hostp;
+ char hostname[256];
+ char address[256];
+ int port;
+
+ for(hostp = data->change.resolve; hostp; hostp = hostp->next ) {
+ if(!hostp->data)
+ continue;
+ if(hostp->data[0] == '-') {
+ /* TODO: mark an entry for removal */
+ }
+ else if(3 == sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port,
+ address)) {
+ struct Curl_dns_entry *dns;
+ Curl_addrinfo *addr;
+ char *entry_id;
+ size_t entry_len;
+
+ addr = Curl_str2addr(address, port);
+ if(!addr) {
+ infof(data, "Resolve %s found illegal!\n", hostp->data);
+ continue;
+ }
+
+ /* Create an entry id, based upon the hostname and port */
+ entry_id = create_hostcache_id(hostname, port);
+ /* If we can't create the entry id, fail */
+ if(!entry_id) {
+ Curl_freeaddrinfo(addr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ entry_len = strlen(entry_id);
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ /* See if its already in our dns cache */
+ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
+
+ /* free the allocated entry_id again */
+ free(entry_id);
+
+ if(!dns)
+ /* if not in the cache already, put this host in the cache */
+ dns = Curl_cache_addr(data, addr, hostname, port);
+ else
+ /* this is a duplicate, free it again */
+ Curl_freeaddrinfo(addr);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ if(!dns) {
+ Curl_freeaddrinfo(addr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ infof(data, "Added %s:%d:%s to DNS cache\n",
+ hostname, port, address);
+ }
+ }
+ data->change.resolve = NULL; /* dealt with now */
+
+ return CURLE_OK;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/hostip.h b/external/libcurl_android/jni/libcurl/lib/hostip.h
new file mode 100755
index 00000000..44046519
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hostip.h
@@ -0,0 +1,250 @@
+#ifndef HEADER_CURL_HOSTIP_H
+#define HEADER_CURL_HOSTIP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "hash.h"
+#include "curl_addrinfo.h"
+#include "asyn.h"
+
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
+
+#ifdef NETWARE
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+/* Allocate enough memory to hold the full name information structs and
+ * everything. OSF1 is known to require at least 8872 bytes. The buffer
+ * required for storing all possible aliases and IP numbers is according to
+ * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes!
+ */
+#define CURL_HOSTENT_SIZE 9000
+
+#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this
+ many seconds for a name resolve */
+
+#define CURL_ASYNC_SUCCESS CURLE_OK
+
+struct addrinfo;
+struct hostent;
+struct SessionHandle;
+struct connectdata;
+
+/*
+ * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
+ * Global DNS cache is general badness. Do not use. This will be removed in
+ * a future version. Use the share interface instead!
+ *
+ * Returns a struct curl_hash pointer on success, NULL on failure.
+ */
+struct curl_hash *Curl_global_host_cache_init(void);
+void Curl_global_host_cache_dtor(void);
+
+struct Curl_dns_entry {
+ Curl_addrinfo *addr;
+ /* timestamp == 0 -- entry not in hostcache
+ timestamp != 0 -- entry is in hostcache */
+ time_t timestamp;
+ long inuse; /* use-counter, make very sure you decrease this
+ when you're done using the address you received */
+};
+
+/*
+ * Curl_resolv() returns an entry with the info for the specified host
+ * and port.
+ *
+ * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
+ * use, or we'll leak memory!
+ */
+/* return codes */
+#define CURLRESOLV_TIMEDOUT -2
+#define CURLRESOLV_ERROR -1
+#define CURLRESOLV_RESOLVED 0
+#define CURLRESOLV_PENDING 1
+int Curl_resolv(struct connectdata *conn, const char *hostname,
+ int port, struct Curl_dns_entry **dnsentry);
+int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
+ int port, struct Curl_dns_entry **dnsentry,
+ long timeoutms);
+
+#ifdef CURLRES_IPV6
+/*
+ * Curl_ipv6works() returns TRUE if ipv6 seems to work.
+ */
+bool Curl_ipv6works(void);
+#else
+#define Curl_ipv6works() FALSE
+#endif
+
+/*
+ * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
+ * been set and returns TRUE if they are OK.
+ */
+bool Curl_ipvalid(struct connectdata *conn);
+
+
+/*
+ * Curl_getaddrinfo() is the generic low-level name resolve API within this
+ * source file. There are several versions of this function - for different
+ * name resolve layers (selected at build-time). They all take this same set
+ * of arguments
+ */
+Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
+
+
+/* unlock a previously resolved dns entry */
+void Curl_resolv_unlock(struct SessionHandle *data,
+ struct Curl_dns_entry *dns);
+
+/* for debugging purposes only: */
+void Curl_scan_cache_used(void *user, void *ptr);
+
+/* make a new dns cache and return the handle */
+struct curl_hash *Curl_mk_dnscache(void);
+
+/* prune old entries from the DNS cache */
+void Curl_hostcache_prune(struct SessionHandle *data);
+
+/* Return # of adresses in a Curl_addrinfo struct */
+int Curl_num_addresses (const Curl_addrinfo *addr);
+
+#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
+int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
+ GETNAMEINFO_TYPE_ARG2 salen,
+ char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
+ char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
+ GETNAMEINFO_TYPE_ARG7 flags,
+ int line, const char *source);
+#endif
+
+/* IPv4 threadsafe resolve function used for synch and asynch builds */
+Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port);
+
+CURLcode Curl_async_resolved(struct connectdata *conn,
+ bool *protocol_connect);
+
+#ifndef CURLRES_ASYNCH
+#define Curl_async_resolved(x,y) CURLE_OK
+#endif
+
+/*
+ * Curl_addrinfo_callback() is used when we build with any asynch specialty.
+ * Handles end of async request processing. Inserts ai into hostcache when
+ * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
+ * request completed whether successful or failed.
+ */
+CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+ int status,
+ Curl_addrinfo *ai);
+
+/*
+ * Curl_printable_address() returns a printable version of the 1st address
+ * given in the 'ip' argument. The result will be stored in the buf that is
+ * bufsize bytes big.
+ */
+const char *Curl_printable_address(const Curl_addrinfo *ip,
+ char *buf, size_t bufsize);
+
+/*
+ * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ */
+struct Curl_dns_entry *
+Curl_fetch_addr(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *stale);
+
+/*
+ * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
+ */
+struct Curl_dns_entry *
+Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr,
+ const char *hostname, int port);
+
+#ifndef INADDR_NONE
+#define CURL_INADDR_NONE (in_addr_t) ~0
+#else
+#define CURL_INADDR_NONE INADDR_NONE
+#endif
+
+#ifdef HAVE_SIGSETJMP
+/* Forward-declaration of variable defined in hostip.c. Beware this
+ * is a global and unique instance. This is used to store the return
+ * address that we can jump back to from inside a signal handler.
+ * This is not thread-safe stuff.
+ */
+extern sigjmp_buf curl_jmpenv;
+#endif
+
+/*
+ * Function provided by the resolver backend to set DNS servers to use.
+ */
+CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
+
+/*
+ * Function provided by the resolver backend to set
+ * outgoing interface to use for DNS requests
+ */
+CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+ const char *interf);
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv4 address to use as source address for DNS requests
+ */
+CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+ const char *local_ip4);
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv6 address to use as source address for DNS requests
+ */
+CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+ const char *local_ip6);
+
+/*
+ * Clean off entries from the cache
+ */
+void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash);
+
+/*
+ * Destroy the hostcache of this handle.
+ */
+void Curl_hostcache_destroy(struct SessionHandle *data);
+
+/*
+ * Populate the cache with specified entries from CURLOPT_RESOLVE.
+ */
+CURLcode Curl_loadhostpairs(struct SessionHandle *data);
+
+#endif /* HEADER_CURL_HOSTIP_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/hostip4.c b/external/libcurl_android/jni/libcurl/lib/hostip4.c
new file mode 100755
index 00000000..1e39f4a9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hostip4.c
@@ -0,0 +1,310 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "inet_pton.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for plain-ipv4 builds
+ **********************************************************************/
+#ifdef CURLRES_IPV4 /* plain ipv4 code coming up */
+/*
+ * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
+ * been set and returns TRUE if they are OK.
+ */
+bool Curl_ipvalid(struct connectdata *conn)
+{
+ if(conn->ip_version == CURL_IPRESOLVE_V6)
+ /* an ipv6 address was requested and we can't get/use one */
+ return FALSE;
+
+ return TRUE; /* OK, proceed */
+}
+
+#ifdef CURLRES_SYNCH
+
+/*
+ * Curl_getaddrinfo() - the ipv4 synchronous version.
+ *
+ * The original code to this function was from the Dancer source code, written
+ * by Bjorn Reese, it has since been patched and modified considerably.
+ *
+ * gethostbyname_r() is the thread-safe version of the gethostbyname()
+ * function. When we build for plain IPv4, we attempt to use this
+ * function. There are _three_ different gethostbyname_r() versions, and we
+ * detect which one this platform supports in the configure script and set up
+ * the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or
+ * HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME
+ * has the corresponding rules. This is primarily on *nix. Note that some unix
+ * flavours have thread-safe versions of the plain gethostbyname() etc.
+ *
+ */
+Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ Curl_addrinfo *ai = NULL;
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)conn;
+#endif
+
+ *waitp = 0; /* synchronous response only */
+
+ ai = Curl_ipv4_resolve_r(hostname, port);
+ if(!ai)
+ infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
+
+ return ai;
+}
+#endif /* CURLRES_SYNCH */
+#endif /* CURLRES_IPV4 */
+
+#if defined(CURLRES_IPV4) && !defined(CURLRES_ARES)
+
+/*
+ * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function.
+ *
+ * This is used for both synchronous and asynchronous resolver builds,
+ * implying that only threadsafe code and function calls may be used.
+ *
+ */
+Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
+ int port)
+{
+#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3)
+ int res;
+#endif
+ Curl_addrinfo *ai = NULL;
+ struct hostent *h = NULL;
+ struct in_addr in;
+ struct hostent *buf = NULL;
+
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+
+#if defined(HAVE_GETADDRINFO_THREADSAFE)
+ else {
+ struct addrinfo hints;
+ char sbuf[12];
+ char *sbufptr = NULL;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ if(port) {
+ snprintf(sbuf, sizeof(sbuf), "%d", port);
+ sbufptr = sbuf;
+ }
+
+ (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai);
+
+#elif defined(HAVE_GETHOSTBYNAME_R)
+ /*
+ * gethostbyname_r() is the preferred resolve function for many platforms.
+ * Since there are three different versions of it, the following code is
+ * somewhat #ifdef-ridden.
+ */
+ else {
+ int h_errnop;
+
+ buf = calloc(1, CURL_HOSTENT_SIZE);
+ if(!buf)
+ return NULL; /* major failure */
+ /*
+ * The clearing of the buffer is a workaround for a gethostbyname_r bug in
+ * qnx nto and it is also _required_ for some of these functions on some
+ * platforms.
+ */
+
+#if defined(HAVE_GETHOSTBYNAME_R_5)
+ /* Solaris, IRIX and more */
+ h = gethostbyname_r(hostname,
+ (struct hostent *)buf,
+ (char *)buf + sizeof(struct hostent),
+ CURL_HOSTENT_SIZE - sizeof(struct hostent),
+ &h_errnop);
+
+ /* If the buffer is too small, it returns NULL and sets errno to
+ * ERANGE. The errno is thread safe if this is compiled with
+ * -D_REENTRANT as then the 'errno' variable is a macro defined to get
+ * used properly for threads.
+ */
+
+ if(h) {
+ ;
+ }
+ else
+#elif defined(HAVE_GETHOSTBYNAME_R_6)
+ /* Linux */
+
+ (void)gethostbyname_r(hostname,
+ (struct hostent *)buf,
+ (char *)buf + sizeof(struct hostent),
+ CURL_HOSTENT_SIZE - sizeof(struct hostent),
+ &h, /* DIFFERENCE */
+ &h_errnop);
+ /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
+ * sudden this function returns EAGAIN if the given buffer size is too
+ * small. Previous versions are known to return ERANGE for the same
+ * problem.
+ *
+ * This wouldn't be such a big problem if older versions wouldn't
+ * sometimes return EAGAIN on a common failure case. Alas, we can't
+ * assume that EAGAIN *or* ERANGE means ERANGE for any given version of
+ * glibc.
+ *
+ * For now, we do that and thus we may call the function repeatedly and
+ * fail for older glibc versions that return EAGAIN, until we run out of
+ * buffer size (step_size grows beyond CURL_HOSTENT_SIZE).
+ *
+ * If anyone has a better fix, please tell us!
+ *
+ * -------------------------------------------------------------------
+ *
+ * On October 23rd 2003, Dan C dug up more details on the mysteries of
+ * gethostbyname_r() in glibc:
+ *
+ * In glibc 2.2.5 the interface is different (this has also been
+ * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't
+ * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32
+ * (shipped/upgraded by Redhat 7.2) don't show this behavior!
+ *
+ * In this "buggy" version, the return code is -1 on error and 'errno'
+ * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a
+ * thread-safe variable.
+ */
+
+ if(!h) /* failure */
+#elif defined(HAVE_GETHOSTBYNAME_R_3)
+ /* AIX, Digital Unix/Tru64, HPUX 10, more? */
+
+ /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
+ * the plain fact that it does not return unique full buffers on each
+ * call, but instead several of the pointers in the hostent structs will
+ * point to the same actual data! This have the unfortunate down-side that
+ * our caching system breaks down horribly. Luckily for us though, AIX 4.3
+ * and more recent versions have a "completely thread-safe"[*] libc where
+ * all the data is stored in thread-specific memory areas making calls to
+ * the plain old gethostbyname() work fine even for multi-threaded
+ * programs.
+ *
+ * This AIX 4.3 or later detection is all made in the configure script.
+ *
+ * Troels Walsted Hansen helped us work this out on March 3rd, 2003.
+ *
+ * [*] = much later we've found out that it isn't at all "completely
+ * thread-safe", but at least the gethostbyname() function is.
+ */
+
+ if(CURL_HOSTENT_SIZE >=
+ (sizeof(struct hostent)+sizeof(struct hostent_data))) {
+
+ /* August 22nd, 2000: Albert Chin-A-Young brought an updated version
+ * that should work! September 20: Richard Prescott worked on the buffer
+ * size dilemma.
+ */
+
+ res = gethostbyname_r(hostname,
+ (struct hostent *)buf,
+ (struct hostent_data *)((char *)buf +
+ sizeof(struct hostent)));
+ h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */
+ }
+ else
+ res = -1; /* failure, too smallish buffer size */
+
+ if(!res) { /* success */
+
+ h = buf; /* result expected in h */
+
+ /* This is the worst kind of the different gethostbyname_r() interfaces.
+ * Since we don't know how big buffer this particular lookup required,
+ * we can't realloc down the huge alloc without doing closer analysis of
+ * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every
+ * name lookup. Fixing this would require an extra malloc() and then
+ * calling Curl_addrinfo_copy() that subsequent realloc()s down the new
+ * memory area to the actually used amount.
+ */
+ }
+ else
+#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */
+ {
+ h = NULL; /* set return code to NULL */
+ free(buf);
+ }
+#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
+ /*
+ * Here is code for platforms that don't have a thread safe
+ * getaddrinfo() nor gethostbyname_r() function or for which
+ * gethostbyname() is the preferred one.
+ */
+ else {
+ h = gethostbyname((void*)hostname);
+#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
+ }
+
+ if(h) {
+ ai = Curl_he2ai(h, port);
+
+ if(buf) /* used a *_r() function */
+ free(buf);
+ }
+
+ return ai;
+}
+#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */
diff --git a/external/libcurl_android/jni/libcurl/lib/hostip6.c b/external/libcurl_android/jni/libcurl/lib/hostip6.c
new file mode 100755
index 00000000..8327004c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hostip6.c
@@ -0,0 +1,224 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+#include "inet_pton.h"
+#include "connect.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for ipv6-enabled builds
+ **********************************************************************/
+#ifdef CURLRES_IPV6
+
+
+#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
+/* These are strictly for memory tracing and are using the same style as the
+ * family otherwise present in memdebug.c. I put these ones here since they
+ * require a bunch of structs I didn't want to include in memdebug.c
+ */
+
+/*
+ * For CURLRES_ARS, this should be written using ares_gethostbyaddr()
+ * (ignoring the fact c-ares doesn't return 'serv').
+ */
+
+int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
+ GETNAMEINFO_TYPE_ARG2 salen,
+ char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
+ char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
+ GETNAMEINFO_TYPE_ARG7 flags,
+ int line, const char *source)
+{
+ int res = (getnameinfo)(sa, salen,
+ host, hostlen,
+ serv, servlen,
+ flags);
+ if(0 == res)
+ /* success */
+ curl_memlog("GETNAME %s:%d getnameinfo()\n",
+ source, line);
+ else
+ curl_memlog("GETNAME %s:%d getnameinfo() failed = %d\n",
+ source, line, res);
+ return res;
+}
+#endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */
+
+/*
+ * Curl_ipv6works() returns TRUE if ipv6 seems to work.
+ */
+bool Curl_ipv6works(void)
+{
+ /* the nature of most system is that IPv6 status doesn't come and go
+ during a program's lifetime so we only probe the first time and then we
+ have the info kept for fast re-use */
+ static int ipv6_works = -1;
+ if(-1 == ipv6_works) {
+ /* probe to see if we have a working IPv6 stack */
+ curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if(s == CURL_SOCKET_BAD)
+ /* an ipv6 address was requested but we can't get/use one */
+ ipv6_works = 0;
+ else {
+ ipv6_works = 1;
+ Curl_closesocket(NULL, s);
+ }
+ }
+ return (ipv6_works>0)?TRUE:FALSE;
+}
+
+/*
+ * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
+ * been set and returns TRUE if they are OK.
+ */
+bool Curl_ipvalid(struct connectdata *conn)
+{
+ if(conn->ip_version == CURL_IPRESOLVE_V6)
+ return Curl_ipv6works();
+ return TRUE;
+}
+
+#if defined(CURLRES_SYNCH)
+
+#ifdef DEBUG_ADDRINFO
+static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
+{
+ printf("dump_addrinfo:\n");
+ for(; ai; ai = ai->ai_next) {
+ char buf[INET6_ADDRSTRLEN];
+
+ printf(" fam %2d, CNAME %s, ",
+ ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
+ if(Curl_printable_address(ai, buf, sizeof(buf)))
+ printf("%s\n", buf);
+ else
+ printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO));
+ }
+}
+#else
+#define dump_addrinfo(x,y) Curl_nop_stmt
+#endif
+
+/*
+ * Curl_getaddrinfo() when built ipv6-enabled (non-threading and
+ * non-ares version).
+ *
+ * Returns name information about the given hostname and port number. If
+ * successful, the 'addrinfo' is returned and the forth argument will point to
+ * memory we need to free after use. That memory *MUST* be freed with
+ * Curl_freeaddrinfo(), nothing else.
+ */
+Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ struct addrinfo hints;
+ Curl_addrinfo *res;
+ int error;
+ char sbuf[12];
+ char *sbufptr = NULL;
+ char addrbuf[128];
+ int pf;
+ struct SessionHandle *data = conn->data;
+
+ *waitp = 0; /* synchronous response only */
+
+ /*
+ * Check if a limited name resolve has been requested.
+ */
+ switch(conn->ip_version) {
+ case CURL_IPRESOLVE_V4:
+ pf = PF_INET;
+ break;
+ case CURL_IPRESOLVE_V6:
+ pf = PF_INET6;
+ break;
+ default:
+ pf = PF_UNSPEC;
+ break;
+ }
+
+ if((pf != PF_INET) && !Curl_ipv6works())
+ /* the stack seems to be a non-ipv6 one */
+ pf = PF_INET;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pf;
+ hints.ai_socktype = conn->socktype;
+
+ if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||
+ (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) {
+ /* the given address is numerical only, prevent a reverse lookup */
+ hints.ai_flags = AI_NUMERICHOST;
+ }
+
+ if(port) {
+ snprintf(sbuf, sizeof(sbuf), "%d", port);
+ sbufptr=sbuf;
+ }
+ error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
+ if(error) {
+ infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
+ return NULL;
+ }
+
+ dump_addrinfo(conn, res);
+
+ return res;
+}
+#endif /* CURLRES_SYNCH */
+#endif /* CURLRES_IPV6 */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/hostsyn.c b/external/libcurl_android/jni/libcurl/lib/hostsyn.c
new file mode 100755
index 00000000..4ad3c63d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/hostsyn.c
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "strerror.h"
+#include "url.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for builds using synchronous name resolves
+ **********************************************************************/
+#ifdef CURLRES_SYNCH
+
+/*
+ * Function provided by the resolver backend to set DNS servers to use.
+ */
+CURLcode Curl_set_dns_servers(struct SessionHandle *data,
+ char *servers)
+{
+ (void)data;
+ (void)servers;
+ return CURLE_NOT_BUILT_IN;
+
+}
+
+/*
+ * Function provided by the resolver backend to set
+ * outgoing interface to use for DNS requests
+ */
+CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+ const char *interf)
+{
+ (void)data;
+ (void)interf;
+ return CURLE_NOT_BUILT_IN;
+}
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv4 address to use as source address for DNS requests
+ */
+CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+ const char *local_ip4)
+{
+ (void)data;
+ (void)local_ip4;
+ return CURLE_NOT_BUILT_IN;
+}
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv6 address to use as source address for DNS requests
+ */
+CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+ const char *local_ip6)
+{
+ (void)data;
+ (void)local_ip6;
+ return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* truly sync */
diff --git a/external/libcurl_android/jni/libcurl/lib/http.c b/external/libcurl_android/jni/libcurl/lib/http.c
new file mode 100755
index 00000000..35baa340
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http.c
@@ -0,0 +1,3664 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_HTTP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+#include "formdata.h"
+#include "progress.h"
+#include "curl_base64.h"
+#include "cookie.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "http_digest.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_wb.h"
+#include "http_negotiate.h"
+#include "url.h"
+#include "share.h"
+#include "hostip.h"
+#include "http.h"
+#include "curl_memory.h"
+#include "select.h"
+#include "parsedate.h" /* for the week day and month names */
+#include "strtoofft.h"
+#include "multiif.h"
+#include "rawstr.h"
+#include "content_encoding.h"
+#include "http_proxy.h"
+#include "warnless.h"
+#include "non-ascii.h"
+#include "bundles.h"
+#include "pipeline.h"
+#include "http2.h"
+#include "connect.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Forward declarations.
+ */
+
+static int http_getsock_do(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+static int http_should_fail(struct connectdata *conn);
+
+#ifdef USE_SSL
+static CURLcode https_connecting(struct connectdata *conn, bool *done);
+static int https_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+#else
+#define https_connecting(x,y) CURLE_COULDNT_CONNECT
+#endif
+
+/*
+ * HTTP handler interface.
+ */
+const struct Curl_handler Curl_handler_http = {
+ "HTTP", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_CREDSPERREQUEST /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTPS handler interface.
+ */
+const struct Curl_handler Curl_handler_https = {
+ "HTTPS", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ https_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ https_getsock, /* proto_getsock */
+ http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTPS, /* defport */
+ CURLPROTO_HTTPS, /* protocol */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */
+};
+#endif
+
+
+CURLcode Curl_http_setup_conn(struct connectdata *conn)
+{
+ /* allocate the HTTP-specific struct for the SessionHandle, only to survive
+ during this request */
+ DEBUGASSERT(conn->data->req.protop == NULL);
+
+ conn->data->req.protop = calloc(1, sizeof(struct HTTP));
+ if(!conn->data->req.protop)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+/*
+ * checkheaders() checks the linked list of custom HTTP headers for a
+ * particular header (prefix).
+ *
+ * Returns a pointer to the first matching header or NULL if none matched.
+ */
+char *Curl_checkheaders(const struct connectdata *conn,
+ const char *thisheader)
+{
+ struct curl_slist *head;
+ size_t thislen = strlen(thisheader);
+ struct SessionHandle *data = conn->data;
+
+ for(head = data->set.headers;head; head=head->next) {
+ if(Curl_raw_nequal(head->data, thisheader, thislen))
+ return head->data;
+ }
+ return NULL;
+}
+
+/*
+ * checkProxyHeaders() checks the linked list of custom proxy headers
+ * if proxy headers are not available, then it will lookup into http header
+ * link list
+ *
+ * It takes a connectdata struct as input instead of the SessionHandle simply
+ * to know if this is a proxy request or not, as it then might check a
+ * different header list.
+ *
+ */
+char *Curl_checkProxyheaders(const struct connectdata *conn,
+ const char *thisheader)
+{
+ struct curl_slist *head;
+ size_t thislen = strlen(thisheader);
+ struct SessionHandle *data = conn->data;
+
+ for(head = (conn->bits.proxy && data->set.sep_headers)?
+ data->set.proxyheaders:data->set.headers;
+ head; head=head->next) {
+ if(Curl_raw_nequal(head->data, thisheader, thislen))
+ return head->data;
+ }
+ return NULL;
+}
+
+/*
+ * Strip off leading and trailing whitespace from the value in the
+ * given HTTP header line and return a strdupped copy. Returns NULL in
+ * case of allocation failure. Returns an empty string if the header value
+ * consists entirely of whitespace.
+ */
+char *Curl_copy_header_value(const char *header)
+{
+ const char *start;
+ const char *end;
+ char *value;
+ size_t len;
+
+ DEBUGASSERT(header);
+
+ /* Find the end of the header name */
+ while(*header && (*header != ':'))
+ ++header;
+
+ if(*header)
+ /* Skip over colon */
+ ++header;
+
+ /* Find the first non-space letter */
+ start = header;
+ while(*start && ISSPACE(*start))
+ start++;
+
+ /* data is in the host encoding so
+ use '\r' and '\n' instead of 0x0d and 0x0a */
+ end = strchr(start, '\r');
+ if(!end)
+ end = strchr(start, '\n');
+ if(!end)
+ end = strchr(start, '\0');
+ if(!end)
+ return NULL;
+
+ /* skip all trailing space letters */
+ while((end > start) && ISSPACE(*end))
+ end--;
+
+ /* get length of the type */
+ len = end - start + 1;
+
+ value = malloc(len + 1);
+ if(!value)
+ return NULL;
+
+ memcpy(value, start, len);
+ value[len] = 0; /* zero terminate */
+
+ return value;
+}
+
+/*
+ * http_output_basic() sets up an Authorization: header (or the proxy version)
+ * for HTTP Basic authentication.
+ *
+ * Returns CURLcode.
+ */
+static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
+{
+ size_t size = 0;
+ char *authorization = NULL;
+ struct SessionHandle *data = conn->data;
+ char **userp;
+ const char *user;
+ const char *pwd;
+ CURLcode error;
+
+ if(proxy) {
+ userp = &conn->allocptr.proxyuserpwd;
+ user = conn->proxyuser;
+ pwd = conn->proxypasswd;
+ }
+ else {
+ userp = &conn->allocptr.userpwd;
+ user = conn->user;
+ pwd = conn->passwd;
+ }
+
+ snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
+
+ error = Curl_base64_encode(data,
+ data->state.buffer, strlen(data->state.buffer),
+ &authorization, &size);
+ if(error)
+ return error;
+
+ if(!authorization)
+ return CURLE_REMOTE_ACCESS_DENIED;
+
+ Curl_safefree(*userp);
+ *userp = aprintf("%sAuthorization: Basic %s\r\n",
+ proxy?"Proxy-":"",
+ authorization);
+ free(authorization);
+ if(!*userp)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+/* pickoneauth() selects the most favourable authentication method from the
+ * ones available and the ones we want.
+ *
+ * return TRUE if one was picked
+ */
+static bool pickoneauth(struct auth *pick)
+{
+ bool picked;
+ /* only deal with authentication we want */
+ unsigned long avail = pick->avail & pick->want;
+ picked = TRUE;
+
+ /* The order of these checks is highly relevant, as this will be the order
+ of preference in case of the existence of multiple accepted types. */
+ if(avail & CURLAUTH_NEGOTIATE)
+ pick->picked = CURLAUTH_NEGOTIATE;
+ else if(avail & CURLAUTH_DIGEST)
+ pick->picked = CURLAUTH_DIGEST;
+ else if(avail & CURLAUTH_NTLM)
+ pick->picked = CURLAUTH_NTLM;
+ else if(avail & CURLAUTH_NTLM_WB)
+ pick->picked = CURLAUTH_NTLM_WB;
+ else if(avail & CURLAUTH_BASIC)
+ pick->picked = CURLAUTH_BASIC;
+ else {
+ pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
+ picked = FALSE;
+ }
+ pick->avail = CURLAUTH_NONE; /* clear it here */
+
+ return picked;
+}
+
+/*
+ * Curl_http_perhapsrewind()
+ *
+ * If we are doing POST or PUT {
+ * If we have more data to send {
+ * If we are doing NTLM {
+ * Keep sending since we must not disconnect
+ * }
+ * else {
+ * If there is more than just a little data left to send, close
+ * the current connection by force.
+ * }
+ * }
+ * If we have sent any data {
+ * If we don't have track of all the data {
+ * call app to tell it to rewind
+ * }
+ * else {
+ * rewind internally so that the operation can restart fine
+ * }
+ * }
+ * }
+ */
+static CURLcode http_perhapsrewind(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ struct HTTP *http = data->req.protop;
+ curl_off_t bytessent;
+ curl_off_t expectsend = -1; /* default is unknown */
+
+ if(!http)
+ /* If this is still NULL, we have not reach very far and we can safely
+ skip this rewinding stuff */
+ return CURLE_OK;
+
+ switch(data->set.httpreq) {
+ case HTTPREQ_GET:
+ case HTTPREQ_HEAD:
+ return CURLE_OK;
+ default:
+ break;
+ }
+
+ bytessent = http->writebytecount;
+
+ if(conn->bits.authneg)
+ /* This is a state where we are known to be negotiating and we don't send
+ any data then. */
+ expectsend = 0;
+ else {
+ /* figure out how much data we are expected to send */
+ switch(data->set.httpreq) {
+ case HTTPREQ_POST:
+ if(data->set.postfieldsize != -1)
+ expectsend = data->set.postfieldsize;
+ else if(data->set.postfields)
+ expectsend = (curl_off_t)strlen(data->set.postfields);
+ break;
+ case HTTPREQ_PUT:
+ if(data->state.infilesize != -1)
+ expectsend = data->state.infilesize;
+ break;
+ case HTTPREQ_POST_FORM:
+ expectsend = http->postsize;
+ break;
+ default:
+ break;
+ }
+ }
+
+ conn->bits.rewindaftersend = FALSE; /* default */
+
+ if((expectsend == -1) || (expectsend > bytessent)) {
+ /* There is still data left to send */
+ if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
+ (data->state.authhost.picked == CURLAUTH_NTLM) ||
+ (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
+ (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
+ if(((expectsend - bytessent) < 2000) ||
+ (conn->ntlm.state != NTLMSTATE_NONE) ||
+ (conn->proxyntlm.state != NTLMSTATE_NONE)) {
+ /* The NTLM-negotiation has started *OR* there is just a little (<2K)
+ data left to send, keep on sending. */
+
+ /* rewind data when completely done sending! */
+ if(!conn->bits.authneg) {
+ conn->bits.rewindaftersend = TRUE;
+ infof(data, "Rewind stream after send\n");
+ }
+
+ return CURLE_OK;
+ }
+ if(conn->bits.close)
+ /* this is already marked to get closed */
+ return CURLE_OK;
+
+ infof(data, "NTLM send, close instead of sending %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ (curl_off_t)(expectsend - bytessent));
+ }
+
+ /* This is not NTLM or many bytes left to send: close
+ */
+ connclose(conn, "Mid-auth HTTP and much data left to send");
+ data->req.size = 0; /* don't download any more than 0 bytes */
+
+ /* There still is data left to send, but this connection is marked for
+ closure so we can safely do the rewind right now */
+ }
+
+ if(bytessent)
+ /* we rewind now at once since if we already sent something */
+ return Curl_readrewind(conn);
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_http_auth_act() gets called when all HTTP headers have been received
+ * and it checks what authentication methods that are available and decides
+ * which one (if any) to use. It will set 'newurl' if an auth method was
+ * picked.
+ */
+
+CURLcode Curl_http_auth_act(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ bool pickhost = FALSE;
+ bool pickproxy = FALSE;
+ CURLcode code = CURLE_OK;
+
+ if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
+ /* this is a transient response code, ignore */
+ return CURLE_OK;
+
+ if(data->state.authproblem)
+ return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
+
+ if(conn->bits.user_passwd &&
+ ((data->req.httpcode == 401) ||
+ (conn->bits.authneg && data->req.httpcode < 300))) {
+ pickhost = pickoneauth(&data->state.authhost);
+ if(!pickhost)
+ data->state.authproblem = TRUE;
+ }
+ if(conn->bits.proxy_user_passwd &&
+ ((data->req.httpcode == 407) ||
+ (conn->bits.authneg && data->req.httpcode < 300))) {
+ pickproxy = pickoneauth(&data->state.authproxy);
+ if(!pickproxy)
+ data->state.authproblem = TRUE;
+ }
+
+ if(pickhost || pickproxy) {
+ /* In case this is GSS auth, the newurl field is already allocated so
+ we must make sure to free it before allocating a new one. As figured
+ out in bug #2284386 */
+ Curl_safefree(data->req.newurl);
+ data->req.newurl = strdup(data->change.url); /* clone URL */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+
+ if((data->set.httpreq != HTTPREQ_GET) &&
+ (data->set.httpreq != HTTPREQ_HEAD) &&
+ !conn->bits.rewindaftersend) {
+ code = http_perhapsrewind(conn);
+ if(code)
+ return code;
+ }
+ }
+
+ else if((data->req.httpcode < 300) &&
+ (!data->state.authhost.done) &&
+ conn->bits.authneg) {
+ /* no (known) authentication available,
+ authentication is not "done" yet and
+ no authentication seems to be required and
+ we didn't try HEAD or GET */
+ if((data->set.httpreq != HTTPREQ_GET) &&
+ (data->set.httpreq != HTTPREQ_HEAD)) {
+ data->req.newurl = strdup(data->change.url); /* clone URL */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+ data->state.authhost.done = TRUE;
+ }
+ }
+ if(http_should_fail(conn)) {
+ failf (data, "The requested URL returned error: %d",
+ data->req.httpcode);
+ code = CURLE_HTTP_RETURNED_ERROR;
+ }
+
+ return code;
+}
+
+
+/*
+ * Output the correct authentication header depending on the auth type
+ * and whether or not it is to a proxy.
+ */
+static CURLcode
+output_auth_headers(struct connectdata *conn,
+ struct auth *authstatus,
+ const char *request,
+ const char *path,
+ bool proxy)
+{
+ struct SessionHandle *data = conn->data;
+ const char *auth=NULL;
+ CURLcode result = CURLE_OK;
+#ifdef USE_SPNEGO
+ struct negotiatedata *negdata = proxy?
+ &data->state.proxyneg:&data->state.negotiate;
+#endif
+
+#ifdef CURL_DISABLE_CRYPTO_AUTH
+ (void)request;
+ (void)path;
+#endif
+
+#ifdef USE_SPNEGO
+ negdata->state = GSS_AUTHNONE;
+ if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
+ negdata->context && !GSS_ERROR(negdata->status)) {
+ auth="Negotiate";
+ result = Curl_output_negotiate(conn, proxy);
+ if(result)
+ return result;
+ authstatus->done = TRUE;
+ negdata->state = GSS_AUTHSENT;
+ }
+ else
+#endif
+#ifdef USE_NTLM
+ if(authstatus->picked == CURLAUTH_NTLM) {
+ auth="NTLM";
+ result = Curl_output_ntlm(conn, proxy);
+ if(result)
+ return result;
+ }
+ else
+#endif
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ if(authstatus->picked == CURLAUTH_NTLM_WB) {
+ auth="NTLM_WB";
+ result = Curl_output_ntlm_wb(conn, proxy);
+ if(result)
+ return result;
+ }
+ else
+#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(authstatus->picked == CURLAUTH_DIGEST) {
+ auth="Digest";
+ result = Curl_output_digest(conn,
+ proxy,
+ (const unsigned char *)request,
+ (const unsigned char *)path);
+ if(result)
+ return result;
+ }
+ else
+#endif
+ if(authstatus->picked == CURLAUTH_BASIC) {
+ /* Basic */
+ if((proxy && conn->bits.proxy_user_passwd &&
+ !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
+ (!proxy && conn->bits.user_passwd &&
+ !Curl_checkheaders(conn, "Authorization:"))) {
+ auth="Basic";
+ result = http_output_basic(conn, proxy);
+ if(result)
+ return result;
+ }
+ /* NOTE: this function should set 'done' TRUE, as the other auth
+ functions work that way */
+ authstatus->done = TRUE;
+ }
+
+ if(auth) {
+ infof(data, "%s auth using %s with user '%s'\n",
+ proxy?"Proxy":"Server", auth,
+ proxy?(conn->proxyuser?conn->proxyuser:""):
+ (conn->user?conn->user:""));
+ authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
+ }
+ else
+ authstatus->multi = FALSE;
+
+ return CURLE_OK;
+}
+
+/**
+ * Curl_http_output_auth() setups the authentication headers for the
+ * host/proxy and the correct authentication
+ * method. conn->data->state.authdone is set to TRUE when authentication is
+ * done.
+ *
+ * @param conn all information about the current connection
+ * @param request pointer to the request keyword
+ * @param path pointer to the requested path
+ * @param proxytunnel boolean if this is the request setting up a "proxy
+ * tunnel"
+ *
+ * @returns CURLcode
+ */
+CURLcode
+Curl_http_output_auth(struct connectdata *conn,
+ const char *request,
+ const char *path,
+ bool proxytunnel) /* TRUE if this is the request setting
+ up the proxy tunnel */
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct auth *authhost;
+ struct auth *authproxy;
+
+ DEBUGASSERT(data);
+
+ authhost = &data->state.authhost;
+ authproxy = &data->state.authproxy;
+
+ if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
+ conn->bits.user_passwd)
+ /* continue please */ ;
+ else {
+ authhost->done = TRUE;
+ authproxy->done = TRUE;
+ return CURLE_OK; /* no authentication with no user or password */
+ }
+
+ if(authhost->want && !authhost->picked)
+ /* The app has selected one or more methods, but none has been picked
+ so far by a server round-trip. Then we set the picked one to the
+ want one, and if this is one single bit it'll be used instantly. */
+ authhost->picked = authhost->want;
+
+ if(authproxy->want && !authproxy->picked)
+ /* The app has selected one or more methods, but none has been picked so
+ far by a proxy round-trip. Then we set the picked one to the want one,
+ and if this is one single bit it'll be used instantly. */
+ authproxy->picked = authproxy->want;
+
+#ifndef CURL_DISABLE_PROXY
+ /* Send proxy authentication header if needed */
+ if(conn->bits.httpproxy &&
+ (conn->bits.tunnel_proxy == proxytunnel)) {
+ result = output_auth_headers(conn, authproxy, request, path, TRUE);
+ if(result)
+ return result;
+ }
+ else
+#else
+ (void)proxytunnel;
+#endif /* CURL_DISABLE_PROXY */
+ /* we have no proxy so let's pretend we're done authenticating
+ with it */
+ authproxy->done = TRUE;
+
+ /* To prevent the user+password to get sent to other than the original
+ host due to a location-follow, we do some weirdo checks here */
+ if(!data->state.this_is_a_follow ||
+ conn->bits.netrc ||
+ !data->state.first_host ||
+ data->set.http_disable_hostname_check_before_authentication ||
+ Curl_raw_equal(data->state.first_host, conn->host.name)) {
+ result = output_auth_headers(conn, authhost, request, path, FALSE);
+ }
+ else
+ authhost->done = TRUE;
+
+ return result;
+}
+
+
+/*
+ * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
+ * headers. They are dealt with both in the transfer.c main loop and in the
+ * proxy CONNECT loop.
+ */
+
+CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
+ const char *auth) /* the first non-space */
+{
+ /*
+ * This resource requires authentication
+ */
+ struct SessionHandle *data = conn->data;
+
+#ifdef USE_SPNEGO
+ struct negotiatedata *negdata = proxy?
+ &data->state.proxyneg:&data->state.negotiate;
+#endif
+ unsigned long *availp;
+ struct auth *authp;
+
+ if(proxy) {
+ availp = &data->info.proxyauthavail;
+ authp = &data->state.authproxy;
+ }
+ else {
+ availp = &data->info.httpauthavail;
+ authp = &data->state.authhost;
+ }
+
+ /*
+ * Here we check if we want the specific single authentication (using ==) and
+ * if we do, we initiate usage of it.
+ *
+ * If the provided authentication is wanted as one out of several accepted
+ * types (using &), we OR this authentication type to the authavail
+ * variable.
+ *
+ * Note:
+ *
+ * ->picked is first set to the 'want' value (one or more bits) before the
+ * request is sent, and then it is again set _after_ all response 401/407
+ * headers have been received but then only to a single preferred method
+ * (bit).
+ *
+ */
+
+ while(*auth) {
+#ifdef USE_SPNEGO
+ if(checkprefix("Negotiate", auth)) {
+ int neg;
+ *availp |= CURLAUTH_NEGOTIATE;
+ authp->avail |= CURLAUTH_NEGOTIATE;
+
+ if(authp->picked == CURLAUTH_NEGOTIATE) {
+ if(negdata->state == GSS_AUTHSENT || negdata->state == GSS_AUTHNONE) {
+ neg = Curl_input_negotiate(conn, proxy, auth);
+ if(neg == 0) {
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(data->change.url);
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+ data->state.authproblem = FALSE;
+ /* we received a GSS auth token and we dealt with it fine */
+ negdata->state = GSS_AUTHRECV;
+ }
+ else
+ data->state.authproblem = TRUE;
+ }
+ }
+ }
+ else
+#endif
+#ifdef USE_NTLM
+ /* NTLM support requires the SSL crypto libs */
+ if(checkprefix("NTLM", auth)) {
+ *availp |= CURLAUTH_NTLM;
+ authp->avail |= CURLAUTH_NTLM;
+ if(authp->picked == CURLAUTH_NTLM ||
+ authp->picked == CURLAUTH_NTLM_WB) {
+ /* NTLM authentication is picked and activated */
+ CURLcode ntlm =
+ Curl_input_ntlm(conn, proxy, auth);
+ if(CURLE_OK == ntlm) {
+ data->state.authproblem = FALSE;
+#ifdef NTLM_WB_ENABLED
+ if(authp->picked == CURLAUTH_NTLM_WB) {
+ *availp &= ~CURLAUTH_NTLM;
+ authp->avail &= ~CURLAUTH_NTLM;
+ *availp |= CURLAUTH_NTLM_WB;
+ authp->avail |= CURLAUTH_NTLM_WB;
+
+ /* Get the challenge-message which will be passed to
+ * ntlm_auth for generating the type 3 message later */
+ while(*auth && ISSPACE(*auth))
+ auth++;
+ if(checkprefix("NTLM", auth)) {
+ auth += strlen("NTLM");
+ while(*auth && ISSPACE(*auth))
+ auth++;
+ if(*auth)
+ if((conn->challenge_header = strdup(auth)) == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ }
+ else {
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
+ }
+ else
+#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(checkprefix("Digest", auth)) {
+ if((authp->avail & CURLAUTH_DIGEST) != 0) {
+ infof(data, "Ignoring duplicate digest auth header.\n");
+ }
+ else {
+ CURLdigest dig;
+ *availp |= CURLAUTH_DIGEST;
+ authp->avail |= CURLAUTH_DIGEST;
+
+ /* We call this function on input Digest headers even if Digest
+ * authentication isn't activated yet, as we need to store the
+ * incoming data from this header in case we are gonna use
+ * Digest. */
+ dig = Curl_input_digest(conn, proxy, auth);
+
+ if(CURLDIGEST_FINE != dig) {
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
+ }
+ else
+#endif
+ if(checkprefix("Basic", auth)) {
+ *availp |= CURLAUTH_BASIC;
+ authp->avail |= CURLAUTH_BASIC;
+ if(authp->picked == CURLAUTH_BASIC) {
+ /* We asked for Basic authentication but got a 40X back
+ anyway, which basically means our name+password isn't
+ valid. */
+ authp->avail = CURLAUTH_NONE;
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
+
+ /* there may be multiple methods on one line, so keep reading */
+ while(*auth && *auth != ',') /* read up to the next comma */
+ auth++;
+ if(*auth == ',') /* if we're on a comma, skip it */
+ auth++;
+ while(*auth && ISSPACE(*auth))
+ auth++;
+ }
+ return CURLE_OK;
+}
+
+/**
+ * http_should_fail() determines whether an HTTP response has gotten us
+ * into an error state or not.
+ *
+ * @param conn all information about the current connection
+ *
+ * @retval 0 communications should continue
+ *
+ * @retval 1 communications should not continue
+ */
+static int http_should_fail(struct connectdata *conn)
+{
+ struct SessionHandle *data;
+ int httpcode;
+
+ DEBUGASSERT(conn);
+ data = conn->data;
+ DEBUGASSERT(data);
+
+ httpcode = data->req.httpcode;
+
+ /*
+ ** If we haven't been asked to fail on error,
+ ** don't fail.
+ */
+ if(!data->set.http_fail_on_error)
+ return 0;
+
+ /*
+ ** Any code < 400 is never terminal.
+ */
+ if(httpcode < 400)
+ return 0;
+
+ /*
+ ** Any code >= 400 that's not 401 or 407 is always
+ ** a terminal error
+ */
+ if((httpcode != 401) &&
+ (httpcode != 407))
+ return 1;
+
+ /*
+ ** All we have left to deal with is 401 and 407
+ */
+ DEBUGASSERT((httpcode == 401) || (httpcode == 407));
+
+ /*
+ ** Examine the current authentication state to see if this
+ ** is an error. The idea is for this function to get
+ ** called after processing all the headers in a response
+ ** message. So, if we've been to asked to authenticate a
+ ** particular stage, and we've done it, we're OK. But, if
+ ** we're already completely authenticated, it's not OK to
+ ** get another 401 or 407.
+ **
+ ** It is possible for authentication to go stale such that
+ ** the client needs to reauthenticate. Once that info is
+ ** available, use it here.
+ */
+
+ /*
+ ** Either we're not authenticating, or we're supposed to
+ ** be authenticating something else. This is an error.
+ */
+ if((httpcode == 401) && !conn->bits.user_passwd)
+ return TRUE;
+ if((httpcode == 407) && !conn->bits.proxy_user_passwd)
+ return TRUE;
+
+ return data->state.authproblem;
+}
+
+/*
+ * readmoredata() is a "fread() emulation" to provide POST and/or request
+ * data. It is used when a huge POST is to be made and the entire chunk wasn't
+ * sent in the first send(). This function will then be called from the
+ * transfer.c loop when more data is to be sent to the peer.
+ *
+ * Returns the amount of bytes it filled the buffer with.
+ */
+static size_t readmoredata(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct HTTP *http = conn->data->req.protop;
+ size_t fullsize = size * nitems;
+
+ if(0 == http->postsize)
+ /* nothing to return */
+ return 0;
+
+ /* make sure that a HTTP request is never sent away chunked! */
+ conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
+
+ if(http->postsize <= (curl_off_t)fullsize) {
+ memcpy(buffer, http->postdata, (size_t)http->postsize);
+ fullsize = (size_t)http->postsize;
+
+ if(http->backup.postsize) {
+ /* move backup data into focus and continue on that */
+ http->postdata = http->backup.postdata;
+ http->postsize = http->backup.postsize;
+ conn->fread_func = http->backup.fread_func;
+ conn->fread_in = http->backup.fread_in;
+
+ http->sending++; /* move one step up */
+
+ http->backup.postsize=0;
+ }
+ else
+ http->postsize = 0;
+
+ return fullsize;
+ }
+
+ memcpy(buffer, http->postdata, fullsize);
+ http->postdata += fullsize;
+ http->postsize -= fullsize;
+
+ return fullsize;
+}
+
+/* ------------------------------------------------------------------------- */
+/* add_buffer functions */
+
+/*
+ * Curl_add_buffer_init() sets up and returns a fine buffer struct
+ */
+Curl_send_buffer *Curl_add_buffer_init(void)
+{
+ return calloc(1, sizeof(Curl_send_buffer));
+}
+
+/*
+ * Curl_add_buffer_send() sends a header buffer and frees all associated
+ * memory. Body data may be appended to the header data if desired.
+ *
+ * Returns CURLcode
+ */
+CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
+ struct connectdata *conn,
+
+ /* add the number of sent bytes to this
+ counter */
+ long *bytes_written,
+
+ /* how much of the buffer contains body data */
+ size_t included_body_bytes,
+ int socketindex)
+
+{
+ ssize_t amount;
+ CURLcode res;
+ char *ptr;
+ size_t size;
+ struct HTTP *http = conn->data->req.protop;
+ size_t sendsize;
+ curl_socket_t sockfd;
+ size_t headersize;
+
+ DEBUGASSERT(socketindex <= SECONDARYSOCKET);
+
+ sockfd = conn->sock[socketindex];
+
+ /* The looping below is required since we use non-blocking sockets, but due
+ to the circumstances we will just loop and try again and again etc */
+
+ ptr = in->buffer;
+ size = in->size_used;
+
+ headersize = size - included_body_bytes; /* the initial part that isn't body
+ is header */
+
+ DEBUGASSERT(size > included_body_bytes);
+
+ res = Curl_convert_to_network(conn->data, ptr, headersize);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(res) {
+ /* conversion failed, free memory and return to the caller */
+ if(in->buffer)
+ free(in->buffer);
+ free(in);
+ return res;
+ }
+
+
+ if(conn->handler->flags & PROTOPT_SSL) {
+ /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
+ when we speak HTTPS, as if only a fraction of it is sent now, this data
+ needs to fit into the normal read-callback buffer later on and that
+ buffer is using this size.
+ */
+
+ sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
+
+ /* OpenSSL is very picky and we must send the SAME buffer pointer to the
+ library when we attempt to re-send this buffer. Sending the same data
+ is not enough, we must use the exact same address. For this reason, we
+ must copy the data to the uploadbuffer first, since that is the buffer
+ we will be using if this send is retried later.
+ */
+ memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
+ ptr = conn->data->state.uploadbuffer;
+ }
+ else
+ sendsize = size;
+
+ res = Curl_write(conn, sockfd, ptr, sendsize, &amount);
+
+ if(CURLE_OK == res) {
+ /*
+ * Note that we may not send the entire chunk at once, and we have a set
+ * number of data bytes at the end of the big buffer (out of which we may
+ * only send away a part).
+ */
+ /* how much of the header that was sent */
+ size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
+ size_t bodylen = amount - headlen;
+
+ if(conn->data->set.verbose) {
+ /* this data _may_ contain binary stuff */
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
+ if(bodylen) {
+ /* there was body data sent beyond the initial header part, pass that
+ on to the debug callback too */
+ Curl_debug(conn->data, CURLINFO_DATA_OUT,
+ ptr+headlen, bodylen, conn);
+ }
+ }
+ if(bodylen)
+ /* since we sent a piece of the body here, up the byte counter for it
+ accordingly */
+ http->writebytecount += bodylen;
+
+ /* 'amount' can never be a very large value here so typecasting it so a
+ signed 31 bit value should not cause problems even if ssize_t is
+ 64bit */
+ *bytes_written += (long)amount;
+
+ if(http) {
+ if((size_t)amount != size) {
+ /* The whole request could not be sent in one system call. We must
+ queue it up and send it later when we get the chance. We must not
+ loop here and wait until it might work again. */
+
+ size -= amount;
+
+ ptr = in->buffer + amount;
+
+ /* backup the currently set pointers */
+ http->backup.fread_func = conn->fread_func;
+ http->backup.fread_in = conn->fread_in;
+ http->backup.postdata = http->postdata;
+ http->backup.postsize = http->postsize;
+
+ /* set the new pointers for the request-sending */
+ conn->fread_func = (curl_read_callback)readmoredata;
+ conn->fread_in = (void *)conn;
+ http->postdata = ptr;
+ http->postsize = (curl_off_t)size;
+
+ http->send_buffer = in;
+ http->sending = HTTPSEND_REQUEST;
+
+ return CURLE_OK;
+ }
+ http->sending = HTTPSEND_BODY;
+ /* the full buffer was sent, clean up and return */
+ }
+ else {
+ if((size_t)amount != size)
+ /* We have no continue-send mechanism now, fail. This can only happen
+ when this function is used from the CONNECT sending function. We
+ currently (stupidly) assume that the whole request is always sent
+ away in the first single chunk.
+
+ This needs FIXing.
+ */
+ return CURLE_SEND_ERROR;
+ else
+ conn->writechannel_inuse = FALSE;
+ }
+ }
+ if(in->buffer)
+ free(in->buffer);
+ free(in);
+
+ return res;
+}
+
+
+/*
+ * add_bufferf() add the formatted input to the buffer.
+ */
+CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
+{
+ char *s;
+ va_list ap;
+ va_start(ap, fmt);
+ s = vaprintf(fmt, ap); /* this allocs a new string to append */
+ va_end(ap);
+
+ if(s) {
+ CURLcode result = Curl_add_buffer(in, s, strlen(s));
+ free(s);
+ return result;
+ }
+ /* If we failed, we cleanup the whole buffer and return error */
+ if(in->buffer)
+ free(in->buffer);
+ free(in);
+ return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * add_buffer() appends a memory chunk to the existing buffer
+ */
+CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
+{
+ char *new_rb;
+ size_t new_size;
+
+ if(~size < in->size_used) {
+ /* If resulting used size of send buffer would wrap size_t, cleanup
+ the whole buffer and return error. Otherwise the required buffer
+ size will fit into a single allocatable memory chunk */
+ Curl_safefree(in->buffer);
+ free(in);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!in->buffer ||
+ ((in->size_used + size) > (in->size_max - 1))) {
+
+ /* If current buffer size isn't enough to hold the result, use a
+ buffer size that doubles the required size. If this new size
+ would wrap size_t, then just use the largest possible one */
+
+ if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
+ (~(size*2) < (in->size_used*2)))
+ new_size = (size_t)-1;
+ else
+ new_size = (in->size_used+size)*2;
+
+ if(in->buffer)
+ /* we have a buffer, enlarge the existing one */
+ new_rb = realloc(in->buffer, new_size);
+ else
+ /* create a new buffer */
+ new_rb = malloc(new_size);
+
+ if(!new_rb) {
+ /* If we failed, we cleanup the whole buffer and return error */
+ Curl_safefree(in->buffer);
+ free(in);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ in->buffer = new_rb;
+ in->size_max = new_size;
+ }
+ memcpy(&in->buffer[in->size_used], inptr, size);
+
+ in->size_used += size;
+
+ return CURLE_OK;
+}
+
+/* end of the add_buffer functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+/*
+ * Curl_compareheader()
+ *
+ * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
+ * Pass headers WITH the colon.
+ */
+bool
+Curl_compareheader(const char *headerline, /* line to check */
+ const char *header, /* header keyword _with_ colon */
+ const char *content) /* content string to find */
+{
+ /* RFC2616, section 4.2 says: "Each header field consists of a name followed
+ * by a colon (":") and the field value. Field names are case-insensitive.
+ * The field value MAY be preceded by any amount of LWS, though a single SP
+ * is preferred." */
+
+ size_t hlen = strlen(header);
+ size_t clen;
+ size_t len;
+ const char *start;
+ const char *end;
+
+ if(!Curl_raw_nequal(headerline, header, hlen))
+ return FALSE; /* doesn't start with header */
+
+ /* pass the header */
+ start = &headerline[hlen];
+
+ /* pass all white spaces */
+ while(*start && ISSPACE(*start))
+ start++;
+
+ /* find the end of the header line */
+ end = strchr(start, '\r'); /* lines end with CRLF */
+ if(!end) {
+ /* in case there's a non-standard compliant line here */
+ end = strchr(start, '\n');
+
+ if(!end)
+ /* hm, there's no line ending here, use the zero byte! */
+ end = strchr(start, '\0');
+ }
+
+ len = end-start; /* length of the content part of the input line */
+ clen = strlen(content); /* length of the word to find */
+
+ /* find the content string in the rest of the line */
+ for(;len>=clen;len--, start++) {
+ if(Curl_raw_nequal(start, content, clen))
+ return TRUE; /* match! */
+ }
+
+ return FALSE; /* no match */
+}
+
+/*
+ * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
+ * the generic Curl_connect().
+ */
+CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode result;
+
+ /* We default to persistent connections. We set this already in this connect
+ function to make the re-use checks properly be able to check this bit. */
+ connkeep(conn, "HTTP default");
+
+ /* the CONNECT procedure might not have been completed */
+ result = Curl_proxy_connect(conn);
+ if(result)
+ return result;
+
+ if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+ /* nothing else to do except wait right now - we're not done here. */
+ return CURLE_OK;
+
+ if(conn->given->flags & PROTOPT_SSL) {
+ /* perform SSL initialization */
+ result = https_connecting(conn, done);
+ if(result)
+ return result;
+ }
+ else
+ *done = TRUE;
+
+ return CURLE_OK;
+}
+
+/* this returns the socket to wait for in the DO and DOING state for the multi
+ interface and then we're always _sending_ a request and thus we wait for
+ the single socket to become writable only */
+static int http_getsock_do(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ /* write mode */
+ (void)numsocks; /* unused, we trust it to be at least 1 */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_WRITESOCK(0);
+}
+
+#ifdef USE_SSL
+static CURLcode https_connecting(struct connectdata *conn, bool *done)
+{
+ CURLcode result;
+ DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
+
+ /* perform SSL initialization for this socket */
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
+ if(result)
+ connclose(conn, "Failed HTTPS connection");
+
+ return result;
+}
+#endif
+
+#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
+ defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS)
+/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
+ It should be made to query the generic SSL layer instead. */
+static int https_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ if(conn->handler->flags & PROTOPT_SSL) {
+ struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ /* write mode */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_WRITESOCK(0);
+ }
+ else if(connssl->connecting_state == ssl_connect_2_reading) {
+ /* read mode */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_READSOCK(0);
+ }
+ }
+ return CURLE_OK;
+}
+#else
+#ifdef USE_SSL
+static int https_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ (void)conn;
+ (void)socks;
+ (void)numsocks;
+ return GETSOCK_BLANK;
+}
+#endif /* USE_SSL */
+#endif /* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL */
+
+/*
+ * Curl_http_done() gets called from Curl_done() after a single HTTP request
+ * has been performed.
+ */
+
+CURLcode Curl_http_done(struct connectdata *conn,
+ CURLcode status, bool premature)
+{
+ struct SessionHandle *data = conn->data;
+ struct HTTP *http =data->req.protop;
+
+ Curl_unencode_cleanup(conn);
+
+#ifdef USE_SPNEGO
+ if(data->state.proxyneg.state == GSS_AUTHSENT ||
+ data->state.negotiate.state == GSS_AUTHSENT)
+ Curl_cleanup_negotiate(data);
+#endif
+
+ /* set the proper values (possibly modified on POST) */
+ conn->fread_func = data->set.fread_func; /* restore */
+ conn->fread_in = data->set.in; /* restore */
+ conn->seek_func = data->set.seek_func; /* restore */
+ conn->seek_client = data->set.seek_client; /* restore */
+
+ if(http == NULL)
+ return CURLE_OK;
+
+ if(http->send_buffer) {
+ Curl_send_buffer *buff = http->send_buffer;
+
+ free(buff->buffer);
+ free(buff);
+ http->send_buffer = NULL; /* clear the pointer */
+ }
+
+ if(HTTPREQ_POST_FORM == data->set.httpreq) {
+ data->req.bytecount = http->readbytecount + http->writebytecount;
+
+ Curl_formclean(&http->sendit); /* Now free that whole lot */
+ if(http->form.fp) {
+ /* a file being uploaded was left opened, close it! */
+ fclose(http->form.fp);
+ http->form.fp = NULL;
+ }
+ }
+ else if(HTTPREQ_PUT == data->set.httpreq)
+ data->req.bytecount = http->readbytecount + http->writebytecount;
+
+ if(status != CURLE_OK)
+ return (status);
+
+ if(!premature && /* this check is pointless when DONE is called before the
+ entire operation is complete */
+ !conn->bits.retry &&
+ !data->set.connect_only &&
+ ((http->readbytecount +
+ data->req.headerbytecount -
+ data->req.deductheadercount)) <= 0) {
+ /* If this connection isn't simply closed to be retried, AND nothing was
+ read from the HTTP server (that counts), this can't be right so we
+ return an error here */
+ failf(data, "Empty reply from server");
+ return CURLE_GOT_NOTHING;
+ }
+
+ return CURLE_OK;
+}
+
+
+/*
+ * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
+ * to avoid it include:
+ *
+ * - if the user specifically requested HTTP 1.0
+ * - if the server we are connected to only supports 1.0
+ * - if any server previously contacted to handle this request only supports
+ * 1.0.
+ */
+static bool use_http_1_1plus(const struct SessionHandle *data,
+ const struct connectdata *conn)
+{
+ return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
+ ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
+ ((conn->httpversion == 11) ||
+ ((conn->httpversion != 10) &&
+ (data->state.httpversion != 10))))) ? TRUE : FALSE;
+}
+
+/* check and possibly add an Expect: header */
+static CURLcode expect100(struct SessionHandle *data,
+ struct connectdata *conn,
+ Curl_send_buffer *req_buffer)
+{
+ CURLcode result = CURLE_OK;
+ const char *ptr;
+ data->state.expect100header = FALSE; /* default to false unless it is set
+ to TRUE below */
+ if(use_http_1_1plus(data, conn)) {
+ /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
+ 100-continue to the headers which actually speeds up post operations
+ (as there is one packet coming back from the web server) */
+ ptr = Curl_checkheaders(conn, "Expect:");
+ if(ptr) {
+ data->state.expect100header =
+ Curl_compareheader(ptr, "Expect:", "100-continue");
+ }
+ else {
+ result = Curl_add_bufferf(req_buffer,
+ "Expect: 100-continue\r\n");
+ if(result == CURLE_OK)
+ data->state.expect100header = TRUE;
+ }
+ }
+ return result;
+}
+
+enum proxy_use {
+ HEADER_SERVER, /* direct to server */
+ HEADER_PROXY, /* regular request to proxy */
+ HEADER_CONNECT /* sending CONNECT to a proxy */
+};
+
+CURLcode Curl_add_custom_headers(struct connectdata *conn,
+ bool is_connect,
+ Curl_send_buffer *req_buffer)
+{
+ char *ptr;
+ struct curl_slist *h[2];
+ struct curl_slist *headers;
+ int numlists=1; /* by default */
+ struct SessionHandle *data = conn->data;
+ int i;
+
+ enum proxy_use proxy;
+
+ if(is_connect)
+ proxy = HEADER_CONNECT;
+ else
+ proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
+ HEADER_PROXY:HEADER_SERVER;
+
+ switch(proxy) {
+ case HEADER_SERVER:
+ h[0] = data->set.headers;
+ break;
+ case HEADER_PROXY:
+ h[0] = data->set.headers;
+ if(data->set.sep_headers) {
+ h[1] = data->set.proxyheaders;
+ numlists++;
+ }
+ break;
+ case HEADER_CONNECT:
+ if(data->set.sep_headers)
+ h[0] = data->set.proxyheaders;
+ else
+ h[0] = data->set.headers;
+ break;
+ }
+
+ /* loop through one or two lists */
+ for(i=0; i < numlists; i++) {
+ headers = h[i];
+
+ while(headers) {
+ ptr = strchr(headers->data, ':');
+ if(ptr) {
+ /* we require a colon for this to be a true header */
+
+ ptr++; /* pass the colon */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+
+ if(*ptr) {
+ /* only send this if the contents was non-blank */
+
+ if(conn->allocptr.host &&
+ /* a Host: header was sent already, don't pass on any custom Host:
+ header as that will produce *two* in the same request! */
+ checkprefix("Host:", headers->data))
+ ;
+ else if(data->set.httpreq == HTTPREQ_POST_FORM &&
+ /* this header (extended by formdata.c) is sent later */
+ checkprefix("Content-Type:", headers->data))
+ ;
+ else if(conn->bits.authneg &&
+ /* while doing auth neg, don't allow the custom length since
+ we will force length zero then */
+ checkprefix("Content-Length", headers->data))
+ ;
+ else if(conn->allocptr.te &&
+ /* when asking for Transfer-Encoding, don't pass on a custom
+ Connection: */
+ checkprefix("Connection", headers->data))
+ ;
+ else {
+ CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
+ headers->data);
+ if(result)
+ return result;
+ }
+ }
+ }
+ else {
+ ptr = strchr(headers->data, ';');
+ if(ptr) {
+
+ ptr++; /* pass the semicolon */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+
+ if(*ptr) {
+ /* this may be used for something else in the future */
+ }
+ else {
+ if(*(--ptr) == ';') {
+ CURLcode result;
+
+ /* send no-value custom header if terminated by semicolon */
+ *ptr = ':';
+ result = Curl_add_bufferf(req_buffer, "%s\r\n",
+ headers->data);
+ if(result)
+ return result;
+ }
+ }
+ }
+ }
+ headers = headers->next;
+ }
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_add_timecondition(struct SessionHandle *data,
+ Curl_send_buffer *req_buffer)
+{
+ const struct tm *tm;
+ char *buf = data->state.buffer;
+ CURLcode result = CURLE_OK;
+ struct tm keeptime;
+
+ result = Curl_gmtime(data->set.timevalue, &keeptime);
+ if(result) {
+ failf(data, "Invalid TIMEVALUE");
+ return result;
+ }
+ tm = &keeptime;
+
+ /* The If-Modified-Since header family should have their times set in
+ * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
+ * represented in Greenwich Mean Time (GMT), without exception. For the
+ * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
+ * Time)." (see page 20 of RFC2616).
+ */
+
+ /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
+ snprintf(buf, BUFSIZE-1,
+ "%s, %02d %s %4d %02d:%02d:%02d GMT",
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+
+ switch(data->set.timecondition) {
+ case CURL_TIMECOND_IFMODSINCE:
+ default:
+ result = Curl_add_bufferf(req_buffer,
+ "If-Modified-Since: %s\r\n", buf);
+ break;
+ case CURL_TIMECOND_IFUNMODSINCE:
+ result = Curl_add_bufferf(req_buffer,
+ "If-Unmodified-Since: %s\r\n", buf);
+ break;
+ case CURL_TIMECOND_LASTMOD:
+ result = Curl_add_bufferf(req_buffer,
+ "Last-Modified: %s\r\n", buf);
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * Curl_http() gets called from the generic Curl_do() function when a HTTP
+ * request is to be performed. This creates and sends a properly constructed
+ * HTTP request.
+ */
+CURLcode Curl_http(struct connectdata *conn, bool *done)
+{
+ struct SessionHandle *data=conn->data;
+ CURLcode result=CURLE_OK;
+ struct HTTP *http;
+ const char *ppath = data->state.path;
+ bool paste_ftp_userpwd = FALSE;
+ char ftp_typecode[sizeof("/;type=?")] = "";
+ const char *host = conn->host.name;
+ const char *te = ""; /* transfer-encoding */
+ const char *ptr;
+ const char *request;
+ Curl_HttpReq httpreq = data->set.httpreq;
+ char *addcookies = NULL;
+ curl_off_t included_body = 0;
+ const char *httpstring;
+ Curl_send_buffer *req_buffer;
+ curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
+ int seekerr = CURL_SEEKFUNC_OK;
+
+ /* Always consider the DO phase done after this function call, even if there
+ may be parts of the request that is not yet sent, since we can deal with
+ the rest of the request in the PERFORM phase. */
+ *done = TRUE;
+
+ if(conn->httpversion < 20) { /* unless the connection is re-used and already
+ http2 */
+ switch (conn->negnpn) {
+ case NPN_HTTP2:
+ result = Curl_http2_init(conn);
+ if(result)
+ return result;
+
+ result = Curl_http2_setup(conn);
+ if(result)
+ return result;
+
+ result = Curl_http2_switched(conn);
+ if(result)
+ return result;
+ break;
+ case NPN_HTTP1_1:
+ /* continue with HTTP/1.1 when explicitly requested */
+ break;
+ default:
+ /* and as fallback */
+ break;
+ }
+ }
+ else {
+ /* prepare for a http2 request */
+ result = Curl_http2_setup(conn);
+ if(result)
+ return result;
+ }
+
+ http = data->req.protop;
+
+ if(!data->state.this_is_a_follow) {
+ /* this is not a followed location, get the original host name */
+ if(data->state.first_host)
+ /* Free to avoid leaking memory on multiple requests*/
+ free(data->state.first_host);
+
+ data->state.first_host = strdup(conn->host.name);
+ if(!data->state.first_host)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ http->writebytecount = http->readbytecount = 0;
+
+ if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
+ data->set.upload) {
+ httpreq = HTTPREQ_PUT;
+ }
+
+ /* Now set the 'request' pointer to the proper request string */
+ if(data->set.str[STRING_CUSTOMREQUEST])
+ request = data->set.str[STRING_CUSTOMREQUEST];
+ else {
+ if(data->set.opt_no_body)
+ request = "HEAD";
+ else {
+ DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
+ switch(httpreq) {
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ request = "POST";
+ break;
+ case HTTPREQ_PUT:
+ request = "PUT";
+ break;
+ default: /* this should never happen */
+ case HTTPREQ_GET:
+ request = "GET";
+ break;
+ case HTTPREQ_HEAD:
+ request = "HEAD";
+ break;
+ }
+ }
+ }
+
+ /* The User-Agent string might have been allocated in url.c already, because
+ it might have been used in the proxy connect, but if we have got a header
+ with the user-agent string specified, we erase the previously made string
+ here. */
+ if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
+ free(conn->allocptr.uagent);
+ conn->allocptr.uagent=NULL;
+ }
+
+ /* setup the authentication headers */
+ result = Curl_http_output_auth(conn, request, ppath, FALSE);
+ if(result)
+ return result;
+
+ if((data->state.authhost.multi || data->state.authproxy.multi) &&
+ (httpreq != HTTPREQ_GET) &&
+ (httpreq != HTTPREQ_HEAD)) {
+ /* Auth is required and we are not authenticated yet. Make a PUT or POST
+ with content-length zero as a "probe". */
+ conn->bits.authneg = TRUE;
+ }
+ else
+ conn->bits.authneg = FALSE;
+
+ Curl_safefree(conn->allocptr.ref);
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) {
+ conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ if(!conn->allocptr.ref)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else
+ conn->allocptr.ref = NULL;
+
+ if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
+ addcookies = data->set.str[STRING_COOKIE];
+
+ if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ data->set.str[STRING_ENCODING]) {
+ Curl_safefree(conn->allocptr.accept_encoding);
+ conn->allocptr.accept_encoding =
+ aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
+ if(!conn->allocptr.accept_encoding)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifdef HAVE_LIBZ
+ /* we only consider transfer-encoding magic if libz support is built-in */
+
+ if(!Curl_checkheaders(conn, "TE:") &&
+ data->set.http_transfer_encoding) {
+ /* When we are to insert a TE: header in the request, we must also insert
+ TE in a Connection: header, so we need to merge the custom provided
+ Connection: header and prevent the original to get sent. Note that if
+ the user has inserted his/hers own TE: header we don't do this magic
+ but then assume that the user will handle it all! */
+ char *cptr = Curl_checkheaders(conn, "Connection:");
+#define TE_HEADER "TE: gzip\r\n"
+
+ Curl_safefree(conn->allocptr.te);
+
+ /* Create the (updated) Connection: header */
+ conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
+ strdup("Connection: TE\r\n" TE_HEADER);
+
+ if(!conn->allocptr.te)
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif
+
+ if(conn->httpversion == 20)
+ /* In HTTP2 forbids Transfer-Encoding: chunked */
+ ptr = NULL;
+ else {
+ ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
+ if(ptr) {
+ /* Some kind of TE is requested, check if 'chunked' is chosen */
+ data->req.upload_chunky =
+ Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
+ }
+ else {
+ if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
+ data->set.upload &&
+ (data->state.infilesize == -1)) {
+ if(conn->bits.authneg)
+ /* don't enable chunked during auth neg */
+ ;
+ else if(use_http_1_1plus(data, conn)) {
+ /* HTTP, upload, unknown file size and not HTTP 1.0 */
+ data->req.upload_chunky = TRUE;
+ }
+ else {
+ failf(data, "Chunky upload is not supported by HTTP 1.0");
+ return CURLE_UPLOAD_FAILED;
+ }
+ }
+ else {
+ /* else, no chunky upload */
+ data->req.upload_chunky = FALSE;
+ }
+
+ if(data->req.upload_chunky)
+ te = "Transfer-Encoding: chunked\r\n";
+ }
+ }
+
+ Curl_safefree(conn->allocptr.host);
+
+ ptr = Curl_checkheaders(conn, "Host:");
+ if(ptr && (!data->state.this_is_a_follow ||
+ Curl_raw_equal(data->state.first_host, conn->host.name))) {
+#if !defined(CURL_DISABLE_COOKIES)
+ /* If we have a given custom Host: header, we extract the host name in
+ order to possibly use it for cookie reasons later on. We only allow the
+ custom Host: header if this is NOT a redirect, as setting Host: in the
+ redirected request is being out on thin ice. Except if the host name
+ is the same as the first one! */
+ char *cookiehost = Curl_copy_header_value(ptr);
+ if(!cookiehost)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*cookiehost)
+ /* ignore empty data */
+ free(cookiehost);
+ else {
+ /* If the host begins with '[', we start searching for the port after
+ the bracket has been closed */
+ int startsearch = 0;
+ if(*cookiehost == '[') {
+ char *closingbracket;
+ /* since the 'cookiehost' is an allocated memory area that will be
+ freed later we cannot simply increment the pointer */
+ memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
+ closingbracket = strchr(cookiehost, ']');
+ if(closingbracket)
+ *closingbracket = 0;
+ }
+ else {
+ char *colon = strchr(cookiehost + startsearch, ':');
+ if(colon)
+ *colon = 0; /* The host must not include an embedded port number */
+ }
+ Curl_safefree(conn->allocptr.cookiehost);
+ conn->allocptr.cookiehost = cookiehost;
+ }
+#endif
+
+ conn->allocptr.host = NULL;
+ }
+ else {
+ /* When building Host: headers, we must put the host name within
+ [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
+
+ if(((conn->given->protocol&CURLPROTO_HTTPS) &&
+ (conn->remote_port == PORT_HTTPS)) ||
+ ((conn->given->protocol&CURLPROTO_HTTP) &&
+ (conn->remote_port == PORT_HTTP)) )
+ /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
+ the port number in the host string */
+ conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
+ conn->bits.ipv6_ip?"[":"",
+ host,
+ conn->bits.ipv6_ip?"]":"");
+ else
+ conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
+ conn->bits.ipv6_ip?"[":"",
+ host,
+ conn->bits.ipv6_ip?"]":"",
+ conn->remote_port);
+
+ if(!conn->allocptr.host)
+ /* without Host: we can't make a nice request */
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+ /* Using a proxy but does not tunnel through it */
+
+ /* The path sent to the proxy is in fact the entire URL. But if the remote
+ host is a IDN-name, we must make sure that the request we produce only
+ uses the encoded host name! */
+ if(conn->host.dispname != conn->host.name) {
+ char *url = data->change.url;
+ ptr = strstr(url, conn->host.dispname);
+ if(ptr) {
+ /* This is where the display name starts in the URL, now replace this
+ part with the encoded name. TODO: This method of replacing the host
+ name is rather crude as I believe there's a slight risk that the
+ user has entered a user name or password that contain the host name
+ string. */
+ size_t currlen = strlen(conn->host.dispname);
+ size_t newlen = strlen(conn->host.name);
+ size_t urllen = strlen(url);
+
+ char *newurl;
+
+ newurl = malloc(urllen + newlen - currlen + 1);
+ if(newurl) {
+ /* copy the part before the host name */
+ memcpy(newurl, url, ptr - url);
+ /* append the new host name instead of the old */
+ memcpy(newurl + (ptr - url), conn->host.name, newlen);
+ /* append the piece after the host name */
+ memcpy(newurl + newlen + (ptr - url),
+ ptr + currlen, /* copy the trailing zero byte too */
+ urllen - (ptr-url) - currlen + 1);
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ data->change.url = newurl;
+ data->change.url_alloc = TRUE;
+ }
+ else
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ ppath = data->change.url;
+ if(checkprefix("ftp://", ppath)) {
+ if(data->set.proxy_transfer_mode) {
+ /* when doing ftp, append ;type=<a|i> if not present */
+ char *type = strstr(ppath, ";type=");
+ if(type && type[6] && type[7] == 0) {
+ switch (Curl_raw_toupper(type[6])) {
+ case 'A':
+ case 'D':
+ case 'I':
+ break;
+ default:
+ type = NULL;
+ }
+ }
+ if(!type) {
+ char *p = ftp_typecode;
+ /* avoid sending invalid URLs like ftp://example.com;type=i if the
+ * user specified ftp://example.com without the slash */
+ if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
+ *p++ = '/';
+ }
+ snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
+ data->set.prefer_ascii ? 'a' : 'i');
+ }
+ }
+ if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
+ paste_ftp_userpwd = TRUE;
+ }
+ }
+#endif /* CURL_DISABLE_PROXY */
+
+ if(HTTPREQ_POST_FORM == httpreq) {
+ /* we must build the whole post sequence first, so that we have a size of
+ the whole transfer before we start to send it */
+ result = Curl_getformdata(data, &http->sendit, data->set.httppost,
+ Curl_checkheaders(conn, "Content-Type:"),
+ &http->postsize);
+ if(result)
+ return result;
+ }
+
+ http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
+
+ if(( (HTTPREQ_POST == httpreq) ||
+ (HTTPREQ_POST_FORM == httpreq) ||
+ (HTTPREQ_PUT == httpreq) ) &&
+ data->state.resume_from) {
+ /**********************************************************************
+ * Resuming upload in HTTP means that we PUT or POST and that we have
+ * got a resume_from value set. The resume value has already created
+ * a Range: header that will be passed along. We need to "fast forward"
+ * the file the given number of bytes and decrease the assume upload
+ * file size before we continue this venture in the dark lands of HTTP.
+ *********************************************************************/
+
+ if(data->state.resume_from < 0 ) {
+ /*
+ * This is meant to get the size of the present remote-file by itself.
+ * We don't support this now. Bail out!
+ */
+ data->state.resume_from = 0;
+ }
+
+ if(data->state.resume_from && !data->state.this_is_a_follow) {
+ /* do we still game? */
+
+ /* Now, let's read off the proper amount of bytes from the
+ input. */
+ if(conn->seek_func) {
+ seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+ SEEK_SET);
+ }
+
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ return CURLE_READ_ERROR;
+ }
+ /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+ do {
+ size_t readthisamountnow =
+ (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
+ BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ data->set.fread_func(data->state.buffer, 1, readthisamountnow,
+ data->set.in);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
+ " bytes from the input", passed);
+ return CURLE_READ_ERROR;
+ }
+ } while(passed < data->state.resume_from);
+ }
+ }
+
+ /* now, decrease the size of the read */
+ if(data->state.infilesize>0) {
+ data->state.infilesize -= data->state.resume_from;
+
+ if(data->state.infilesize <= 0) {
+ failf(data, "File already completely uploaded");
+ return CURLE_PARTIAL_FILE;
+ }
+ }
+ /* we've passed, proceed as normal */
+ }
+ }
+ if(data->state.use_range) {
+ /*
+ * A range is selected. We use different headers whether we're downloading
+ * or uploading and we always let customized headers override our internal
+ * ones if any such are specified.
+ */
+ if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
+ !Curl_checkheaders(conn, "Range:")) {
+ /* if a line like this was already allocated, free the previous one */
+ if(conn->allocptr.rangeline)
+ free(conn->allocptr.rangeline);
+ conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
+ data->state.range);
+ }
+ else if((httpreq != HTTPREQ_GET) &&
+ !Curl_checkheaders(conn, "Content-Range:")) {
+
+ /* if a line like this was already allocated, free the previous one */
+ if(conn->allocptr.rangeline)
+ free(conn->allocptr.rangeline);
+
+ if(data->set.set_resume_from < 0) {
+ /* Upload resume was asked for, but we don't know the size of the
+ remote part so we tell the server (and act accordingly) that we
+ upload the whole file (again) */
+ conn->allocptr.rangeline =
+ aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.infilesize - 1, data->state.infilesize);
+
+ }
+ else if(data->state.resume_from) {
+ /* This is because "resume" was selected */
+ curl_off_t total_expected_size=
+ data->state.resume_from + data->state.infilesize;
+ conn->allocptr.rangeline =
+ aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.range, total_expected_size-1,
+ total_expected_size);
+ }
+ else {
+ /* Range was selected and then we just pass the incoming range and
+ append total size */
+ conn->allocptr.rangeline =
+ aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.range, data->state.infilesize);
+ }
+ if(!conn->allocptr.rangeline)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Use 1.1 unless the user specifically asked for 1.0 or the server only
+ supports 1.0 */
+ httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
+
+ /* initialize a dynamic send-buffer */
+ req_buffer = Curl_add_buffer_init();
+
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* add the main request stuff */
+ /* GET/HEAD/POST/PUT */
+ result = Curl_add_bufferf(req_buffer, "%s ", request);
+ if(result)
+ return result;
+
+ /* url */
+ if(paste_ftp_userpwd)
+ result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
+ conn->user, conn->passwd,
+ ppath + sizeof("ftp://") - 1);
+ else
+ result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
+ if(result)
+ return result;
+
+ result =
+ Curl_add_bufferf(req_buffer,
+ "%s" /* ftp typecode (;type=x) */
+ " HTTP/%s\r\n" /* HTTP version */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ "%s" /* range */
+ "%s" /* user agent */
+ "%s" /* host */
+ "%s" /* accept */
+ "%s" /* TE: */
+ "%s" /* accept-encoding */
+ "%s" /* referer */
+ "%s" /* Proxy-Connection */
+ "%s",/* transfer-encoding */
+
+ ftp_typecode,
+ httpstring,
+ conn->allocptr.proxyuserpwd?
+ conn->allocptr.proxyuserpwd:"",
+ conn->allocptr.userpwd?conn->allocptr.userpwd:"",
+ (data->state.use_range && conn->allocptr.rangeline)?
+ conn->allocptr.rangeline:"",
+ (data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ conn->allocptr.uagent)?
+ conn->allocptr.uagent:"",
+ (conn->allocptr.host?conn->allocptr.host:""),
+ http->p_accept?http->p_accept:"",
+ conn->allocptr.te?conn->allocptr.te:"",
+ (data->set.str[STRING_ENCODING] &&
+ *data->set.str[STRING_ENCODING] &&
+ conn->allocptr.accept_encoding)?
+ conn->allocptr.accept_encoding:"",
+ (data->change.referer && conn->allocptr.ref)?
+ conn->allocptr.ref:"" /* Referer: <data> */,
+ (conn->bits.httpproxy &&
+ !conn->bits.tunnel_proxy &&
+ !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
+ "Proxy-Connection: Keep-Alive\r\n":"",
+ te
+ );
+
+ /*
+ * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
+ * with basic and digest, it will be freed anyway by the next request
+ */
+
+ Curl_safefree (conn->allocptr.userpwd);
+ conn->allocptr.userpwd = NULL;
+
+ if(result)
+ return result;
+
+ if(!(conn->handler->flags&PROTOPT_SSL) &&
+ (data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
+ /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
+ over SSL */
+ result = Curl_http2_request_upgrade(req_buffer, conn);
+ if(result)
+ return result;
+ }
+
+#if !defined(CURL_DISABLE_COOKIES)
+ if(data->cookies || addcookies) {
+ struct Cookie *co=NULL; /* no cookies from start */
+ int count=0;
+
+ if(data->cookies) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ co = Curl_cookie_getlist(data->cookies,
+ conn->allocptr.cookiehost?
+ conn->allocptr.cookiehost:host,
+ data->state.path,
+ (conn->handler->protocol&CURLPROTO_HTTPS)?
+ TRUE:FALSE);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ if(co) {
+ struct Cookie *store=co;
+ /* now loop through all cookies that matched */
+ while(co) {
+ if(co->value) {
+ if(0 == count) {
+ result = Curl_add_bufferf(req_buffer, "Cookie: ");
+ if(result)
+ break;
+ }
+ result = Curl_add_bufferf(req_buffer,
+ "%s%s=%s", count?"; ":"",
+ co->name, co->value);
+ if(result)
+ break;
+ count++;
+ }
+ co = co->next; /* next cookie please */
+ }
+ Curl_cookie_freelist(store, FALSE); /* free the cookie list */
+ }
+ if(addcookies && (CURLE_OK == result)) {
+ if(!count)
+ result = Curl_add_bufferf(req_buffer, "Cookie: ");
+ if(CURLE_OK == result) {
+ result = Curl_add_bufferf(req_buffer, "%s%s",
+ count?"; ":"",
+ addcookies);
+ count++;
+ }
+ }
+ if(count && (CURLE_OK == result))
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+
+ if(result)
+ return result;
+ }
+#endif
+
+ if(data->set.timecondition) {
+ result = Curl_add_timecondition(data, req_buffer);
+ if(result)
+ return result;
+ }
+
+ result = Curl_add_custom_headers(conn, FALSE, req_buffer);
+ if(result)
+ return result;
+
+ http->postdata = NULL; /* nothing to post at this point */
+ Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */
+
+ /* If 'authdone' is FALSE, we must not set the write socket index to the
+ Curl_transfer() call below, as we're not ready to actually upload any
+ data yet. */
+
+ switch(httpreq) {
+
+ case HTTPREQ_POST_FORM:
+ if(!http->sendit || conn->bits.authneg) {
+ /* nothing to post! */
+ result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
+ if(result)
+ return result;
+
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+ if(result)
+ failf(data, "Failed sending POST request");
+ else
+ /* setup variables for the upcoming transfer */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
+ -1, NULL);
+ break;
+ }
+
+ if(Curl_FormInit(&http->form, http->sendit)) {
+ failf(data, "Internal HTTP POST error!");
+ return CURLE_HTTP_POST_ERROR;
+ }
+
+ /* Get the currently set callback function pointer and store that in the
+ form struct since we might want the actual user-provided callback later
+ on. The conn->fread_func pointer itself will be changed for the
+ multipart case to the function that returns a multipart formatted
+ stream. */
+ http->form.fread_func = conn->fread_func;
+
+ /* Set the read function to read from the generated form data */
+ conn->fread_func = (curl_read_callback)Curl_FormReader;
+ conn->fread_in = &http->form;
+
+ http->sending = HTTPSEND_BODY;
+
+ if(!data->req.upload_chunky &&
+ !Curl_checkheaders(conn, "Content-Length:")) {
+ /* only add Content-Length if not uploading chunked */
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", http->postsize);
+ if(result)
+ return result;
+ }
+
+ result = expect100(data, conn, req_buffer);
+ if(result)
+ return result;
+
+ {
+
+ /* Get Content-Type: line from Curl_formpostheader.
+ */
+ char *contentType;
+ size_t linelength=0;
+ contentType = Curl_formpostheader((void *)&http->form,
+ &linelength);
+ if(!contentType) {
+ failf(data, "Could not get Content-Type header line!");
+ return CURLE_HTTP_POST_ERROR;
+ }
+
+ result = Curl_add_buffer(req_buffer, contentType, linelength);
+ if(result)
+ return result;
+ }
+
+ /* make the request end in a true CRLF */
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ if(result)
+ return result;
+
+ /* set upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, http->postsize);
+
+ /* fire away the whole request to the server */
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+ if(result)
+ failf(data, "Failed sending POST request");
+ else
+ /* setup variables for the upcoming transfer */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
+ &http->readbytecount, FIRSTSOCKET,
+ &http->writebytecount);
+
+ if(result) {
+ Curl_formclean(&http->sendit); /* free that whole lot */
+ return result;
+ }
+
+ /* convert the form data */
+ result = Curl_convert_form(data, http->sendit);
+ if(result) {
+ Curl_formclean(&http->sendit); /* free that whole lot */
+ return result;
+ }
+
+ break;
+
+ case HTTPREQ_PUT: /* Let's PUT the data to the server! */
+
+ if(conn->bits.authneg)
+ postsize = 0;
+ else
+ postsize = data->state.infilesize;
+
+ if((postsize != -1) && !data->req.upload_chunky &&
+ !Curl_checkheaders(conn, "Content-Length:")) {
+ /* only add Content-Length if not uploading chunked */
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", postsize);
+ if(result)
+ return result;
+ }
+
+ if(postsize != 0) {
+ result = expect100(data, conn, req_buffer);
+ if(result)
+ return result;
+ }
+
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
+ if(result)
+ return result;
+
+ /* set the upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, postsize);
+
+ /* this sends the buffer and frees all the buffer resources */
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+ if(result)
+ failf(data, "Failed sending PUT request");
+ else
+ /* prepare for transfer */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
+ &http->readbytecount, postsize?FIRSTSOCKET:-1,
+ postsize?&http->writebytecount:NULL);
+ if(result)
+ return result;
+ break;
+
+ case HTTPREQ_POST:
+ /* this is the simple POST, using x-www-form-urlencoded style */
+
+ if(conn->bits.authneg)
+ postsize = 0;
+ else {
+ /* figure out the size of the postfields */
+ postsize = (data->set.postfieldsize != -1)?
+ data->set.postfieldsize:
+ (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
+ }
+
+ /* We only set Content-Length and allow a custom Content-Length if
+ we don't upload data chunked, as RFC2616 forbids us to set both
+ kinds of headers (Transfer-Encoding: chunked and Content-Length) */
+ if((postsize != -1) && !data->req.upload_chunky &&
+ !Curl_checkheaders(conn, "Content-Length:")) {
+ /* we allow replacing this header if not during auth negotiation,
+ although it isn't very wise to actually set your own */
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", postsize);
+ if(result)
+ return result;
+ }
+
+ if(!Curl_checkheaders(conn, "Content-Type:")) {
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Type: application/"
+ "x-www-form-urlencoded\r\n");
+ if(result)
+ return result;
+ }
+
+ /* For really small posts we don't use Expect: headers at all, and for
+ the somewhat bigger ones we allow the app to disable it. Just make
+ sure that the expect100header is always set to the preferred value
+ here. */
+ ptr = Curl_checkheaders(conn, "Expect:");
+ if(ptr) {
+ data->state.expect100header =
+ Curl_compareheader(ptr, "Expect:", "100-continue");
+ }
+ else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) {
+ result = expect100(data, conn, req_buffer);
+ if(result)
+ return result;
+ }
+ else
+ data->state.expect100header = FALSE;
+
+ if(data->set.postfields) {
+
+ /* In HTTP2, we send request body in DATA frame regardless of
+ its size. */
+ if(conn->httpversion != 20 &&
+ !data->state.expect100header &&
+ (postsize < MAX_INITIAL_POST_SIZE)) {
+ /* if we don't use expect: 100 AND
+ postsize is less than MAX_INITIAL_POST_SIZE
+
+ then append the post data to the HTTP request header. This limit
+ is no magic limit but only set to prevent really huge POSTs to
+ get the data duplicated with malloc() and family. */
+
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ if(result)
+ return result;
+
+ if(!data->req.upload_chunky) {
+ /* We're not sending it 'chunked', append it to the request
+ already now to reduce the number if send() calls */
+ result = Curl_add_buffer(req_buffer, data->set.postfields,
+ (size_t)postsize);
+ included_body = postsize;
+ }
+ else {
+ if(postsize) {
+ /* Append the POST data chunky-style */
+ result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
+ if(CURLE_OK == result) {
+ result = Curl_add_buffer(req_buffer, data->set.postfields,
+ (size_t)postsize);
+ if(CURLE_OK == result)
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ included_body = postsize + 2;
+ }
+ }
+ if(CURLE_OK == result)
+ result = Curl_add_buffer(req_buffer,
+ "\x30\x0d\x0a\x0d\x0a", 5);
+ /* 0 CR LF CR LF */
+ included_body += 5;
+ }
+ if(result)
+ return result;
+ /* Make sure the progress information is accurate */
+ Curl_pgrsSetUploadSize(data, postsize);
+ }
+ else {
+ /* A huge POST coming up, do data separate from the request */
+ http->postsize = postsize;
+ http->postdata = data->set.postfields;
+
+ http->sending = HTTPSEND_BODY;
+
+ conn->fread_func = (curl_read_callback)readmoredata;
+ conn->fread_in = (void *)conn;
+
+ /* set the upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, http->postsize);
+
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ if(result)
+ return result;
+ }
+ }
+ else {
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ if(result)
+ return result;
+
+ if(data->req.upload_chunky && conn->bits.authneg) {
+ /* Chunky upload is selected and we're negotiating auth still, send
+ end-of-data only */
+ result = Curl_add_buffer(req_buffer,
+ "\x30\x0d\x0a\x0d\x0a", 5);
+ /* 0 CR LF CR LF */
+ if(result)
+ return result;
+ }
+
+ else if(data->set.postfieldsize) {
+ /* set the upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
+
+ /* set the pointer to mark that we will send the post body using the
+ read callback, but only if we're not in authenticate
+ negotiation */
+ if(!conn->bits.authneg) {
+ http->postdata = (char *)&http->postdata;
+ http->postsize = postsize;
+ }
+ }
+ }
+ /* issue the request */
+ result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
+ (size_t)included_body, FIRSTSOCKET);
+
+ if(result)
+ failf(data, "Failed sending HTTP POST request");
+ else
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
+ &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
+ http->postdata?&http->writebytecount:NULL);
+ break;
+
+ default:
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ if(result)
+ return result;
+
+ /* issue the request */
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+
+ if(result)
+ failf(data, "Failed sending HTTP request");
+ else
+ /* HTTP GET/HEAD download: */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
+ http->postdata?FIRSTSOCKET:-1,
+ http->postdata?&http->writebytecount:NULL);
+ }
+ if(result)
+ return result;
+
+ if(http->writebytecount) {
+ /* if a request-body has been sent off, we make sure this progress is noted
+ properly */
+ Curl_pgrsSetUploadCounter(data, http->writebytecount);
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+
+ if(http->writebytecount >= postsize) {
+ /* already sent the entire request body, mark the "upload" as
+ complete */
+ infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
+ " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ http->writebytecount, postsize);
+ data->req.upload_done = TRUE;
+ data->req.keepon &= ~KEEP_SEND; /* we're done writing */
+ data->req.exp100 = EXP100_SEND_DATA; /* already sent */
+ }
+ }
+
+ return result;
+}
+
+/*
+ * checkhttpprefix()
+ *
+ * Returns TRUE if member of the list matches prefix of string
+ */
+static bool
+checkhttpprefix(struct SessionHandle *data,
+ const char *s)
+{
+ struct curl_slist *head = data->set.http200aliases;
+ bool rc = FALSE;
+#ifdef CURL_DOES_CONVERSIONS
+ /* convert from the network encoding using a scratch area */
+ char *scratch = strdup(s);
+ if(NULL == scratch) {
+ failf (data, "Failed to allocate memory for conversion!");
+ return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
+ }
+ if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(scratch);
+ return FALSE; /* can't return CURLE_foobar so return FALSE */
+ }
+ s = scratch;
+#endif /* CURL_DOES_CONVERSIONS */
+
+ while(head) {
+ if(checkprefix(head->data, s)) {
+ rc = TRUE;
+ break;
+ }
+ head = head->next;
+ }
+
+ if(!rc && (checkprefix("HTTP/", s)))
+ rc = TRUE;
+
+#ifdef CURL_DOES_CONVERSIONS
+ free(scratch);
+#endif /* CURL_DOES_CONVERSIONS */
+ return rc;
+}
+
+#ifndef CURL_DISABLE_RTSP
+static bool
+checkrtspprefix(struct SessionHandle *data,
+ const char *s)
+{
+
+#ifdef CURL_DOES_CONVERSIONS
+ /* convert from the network encoding using a scratch area */
+ char *scratch = strdup(s);
+ if(NULL == scratch) {
+ failf (data, "Failed to allocate memory for conversion!");
+ return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
+ }
+ if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(scratch);
+ return FALSE; /* can't return CURLE_foobar so return FALSE */
+ }
+ s = scratch;
+#else
+ (void)data; /* unused */
+#endif /* CURL_DOES_CONVERSIONS */
+ if(checkprefix("RTSP/", s))
+ return TRUE;
+ else
+ return FALSE;
+}
+#endif /* CURL_DISABLE_RTSP */
+
+static bool
+checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
+ const char *s)
+{
+#ifndef CURL_DISABLE_RTSP
+ if(conn->handler->protocol & CURLPROTO_RTSP)
+ return checkrtspprefix(data, s);
+#else
+ (void)conn;
+#endif /* CURL_DISABLE_RTSP */
+
+ return checkhttpprefix(data, s);
+}
+
+/*
+ * header_append() copies a chunk of data to the end of the already received
+ * header. We make sure that the full string fit in the allocated header
+ * buffer, or else we enlarge it.
+ */
+static CURLcode header_append(struct SessionHandle *data,
+ struct SingleRequest *k,
+ size_t length)
+{
+ if(k->hbuflen + length >= data->state.headersize) {
+ /* We enlarge the header buffer as it is too small */
+ char *newbuff;
+ size_t hbufp_index;
+ size_t newsize;
+
+ if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
+ /* The reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause
+ reallocs infinitely */
+ failf (data, "Avoided giant realloc for header (max is %d)!",
+ CURL_MAX_HTTP_HEADER);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
+ hbufp_index = k->hbufp - data->state.headerbuff;
+ newbuff = realloc(data->state.headerbuff, newsize);
+ if(!newbuff) {
+ failf (data, "Failed to alloc memory for big header!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->state.headersize=newsize;
+ data->state.headerbuff = newbuff;
+ k->hbufp = data->state.headerbuff + hbufp_index;
+ }
+ memcpy(k->hbufp, k->str_start, length);
+ k->hbufp += length;
+ k->hbuflen += length;
+ *k->hbufp = 0;
+
+ return CURLE_OK;
+}
+
+static void print_http_error(struct SessionHandle *data)
+{
+ struct SingleRequest *k = &data->req;
+ char *beg = k->p;
+
+ /* make sure that data->req.p points to the HTTP status line */
+ if(!strncmp(beg, "HTTP", 4)) {
+
+ /* skip to HTTP status code */
+ beg = strchr(beg, ' ');
+ if(beg && *++beg) {
+
+ /* find trailing CR */
+ char end_char = '\r';
+ char *end = strchr(beg, end_char);
+ if(!end) {
+ /* try to find LF (workaround for non-compliant HTTP servers) */
+ end_char = '\n';
+ end = strchr(beg, end_char);
+ }
+
+ if(end) {
+ /* temporarily replace CR or LF by NUL and print the error message */
+ *end = '\0';
+ failf(data, "The requested URL returned error: %s", beg);
+
+ /* restore the previously replaced CR or LF */
+ *end = end_char;
+ return;
+ }
+ }
+ }
+
+ /* fall-back to printing the HTTP status code only */
+ failf(data, "The requested URL returned error: %d", k->httpcode);
+}
+
+/*
+ * Read any HTTP header lines from the server and pass them to the client app.
+ */
+CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *stop_reading)
+{
+ CURLcode result;
+ struct SingleRequest *k = &data->req;
+
+ /* header line within buffer loop */
+ do {
+ size_t rest_length;
+ size_t full_length;
+ int writetype;
+
+ /* str_start is start of line within buf */
+ k->str_start = k->str;
+
+ /* data is in network encoding so use 0x0a instead of '\n' */
+ k->end_ptr = memchr(k->str_start, 0x0a, *nread);
+
+ if(!k->end_ptr) {
+ /* Not a complete header line within buffer, append the data to
+ the end of the headerbuff. */
+ result = header_append(data, k, *nread);
+ if(result)
+ return result;
+
+ if(!k->headerline && (k->hbuflen>5)) {
+ /* make a first check that this looks like a protocol header */
+ if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
+ /* this is not the beginning of a protocol first header line */
+ k->header = FALSE;
+ k->badheader = HEADER_ALLBAD;
+ break;
+ }
+ }
+
+ break; /* read more and try again */
+ }
+
+ /* decrease the size of the remaining (supposed) header line */
+ rest_length = (k->end_ptr - k->str)+1;
+ *nread -= (ssize_t)rest_length;
+
+ k->str = k->end_ptr + 1; /* move past new line */
+
+ full_length = k->str - k->str_start;
+
+ result = header_append(data, k, full_length);
+ if(result)
+ return result;
+
+ k->end_ptr = k->hbufp;
+ k->p = data->state.headerbuff;
+
+ /****
+ * We now have a FULL header line that p points to
+ *****/
+
+ if(!k->headerline) {
+ /* the first read header */
+ if((k->hbuflen>5) &&
+ !checkprotoprefix(data, conn, data->state.headerbuff)) {
+ /* this is not the beginning of a protocol first header line */
+ k->header = FALSE;
+ if(*nread)
+ /* since there's more, this is a partial bad header */
+ k->badheader = HEADER_PARTHEADER;
+ else {
+ /* this was all we read so it's all a bad header */
+ k->badheader = HEADER_ALLBAD;
+ *nread = (ssize_t)rest_length;
+ }
+ break;
+ }
+ }
+
+ /* headers are in network encoding so
+ use 0x0a and 0x0d instead of '\n' and '\r' */
+ if((0x0a == *k->p) || (0x0d == *k->p)) {
+ size_t headerlen;
+ /* Zero-length header line means end of headers! */
+
+#ifdef CURL_DOES_CONVERSIONS
+ if(0x0d == *k->p) {
+ *k->p = '\r'; /* replace with CR in host encoding */
+ k->p++; /* pass the CR byte */
+ }
+ if(0x0a == *k->p) {
+ *k->p = '\n'; /* replace with LF in host encoding */
+ k->p++; /* pass the LF byte */
+ }
+#else
+ if('\r' == *k->p)
+ k->p++; /* pass the \r byte */
+ if('\n' == *k->p)
+ k->p++; /* pass the \n byte */
+#endif /* CURL_DOES_CONVERSIONS */
+
+ if(100 <= k->httpcode && 199 >= k->httpcode) {
+ /*
+ * We have made a HTTP PUT or POST and this is 1.1-lingo
+ * that tells us that the server is OK with this and ready
+ * to receive the data.
+ * However, we'll get more headers now so we must get
+ * back into the header-parsing state!
+ */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
+
+ /* "A user agent MAY ignore unexpected 1xx status responses." */
+ switch(k->httpcode) {
+ case 100:
+ /* if we did wait for this do enable write now! */
+ if(k->exp100) {
+ k->exp100 = EXP100_SEND_DATA;
+ k->keepon |= KEEP_SEND;
+ }
+ break;
+ case 101:
+ /* Switching Protocols */
+ if(k->upgr101 == UPGR101_REQUESTED) {
+ infof(data, "Received 101\n");
+ k->upgr101 = UPGR101_RECEIVED;
+
+ /* switch to http2 now */
+ result = Curl_http2_switched(conn);
+ if(result)
+ return result;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ k->header = FALSE; /* no more header to parse! */
+
+ if((k->size == -1) && !k->chunk && !conn->bits.close &&
+ (conn->httpversion == 11) &&
+ !(conn->handler->protocol & CURLPROTO_RTSP) &&
+ data->set.httpreq != HTTPREQ_HEAD) {
+ /* On HTTP 1.1, when connection is not to get closed, but no
+ Content-Length nor Content-Encoding chunked have been
+ received, according to RFC2616 section 4.4 point 5, we
+ assume that the server will close the connection to
+ signal the end of the document. */
+ infof(data, "no chunk, no close, no size. Assume close to "
+ "signal end\n");
+ connclose(conn, "HTTP: No end-of-message indicator");
+ }
+ }
+
+ /*
+ * When all the headers have been parsed, see if we should give
+ * up and return an error.
+ */
+ if(http_should_fail(conn)) {
+ failf (data, "The requested URL returned error: %d",
+ k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+
+ /* now, only output this if the header AND body are requested:
+ */
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+
+ headerlen = k->p - data->state.headerbuff;
+
+ result = Curl_client_write(conn, writetype,
+ data->state.headerbuff,
+ headerlen);
+ if(result)
+ return result;
+
+ data->info.header_size += (long)headerlen;
+ data->req.headerbytecount += (long)headerlen;
+
+ data->req.deductheadercount =
+ (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
+
+ if(!*stop_reading) {
+ /* Curl_http_auth_act() checks what authentication methods
+ * that are available and decides which one (if any) to
+ * use. It will set 'newurl' if an auth method was picked. */
+ result = Curl_http_auth_act(conn);
+
+ if(result)
+ return result;
+
+ if(k->httpcode >= 300) {
+ if((!conn->bits.authneg) && !conn->bits.close &&
+ !conn->bits.rewindaftersend) {
+ /*
+ * General treatment of errors when about to send data. Including :
+ * "417 Expectation Failed", while waiting for 100-continue.
+ *
+ * The check for close above is done simply because of something
+ * else has already deemed the connection to get closed then
+ * something else should've considered the big picture and we
+ * avoid this check.
+ *
+ * rewindaftersend indicates that something has told libcurl to
+ * continue sending even if it gets discarded
+ */
+
+ switch(data->set.httpreq) {
+ case HTTPREQ_PUT:
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ /* We got an error response. If this happened before the whole
+ * request body has been sent we stop sending and mark the
+ * connection for closure after we've read the entire response.
+ */
+ if(!k->upload_done) {
+ infof(data, "HTTP error before end of send, stop sending\n");
+ connclose(conn, "Stop sending data before everything sent");
+ k->upload_done = TRUE;
+ k->keepon &= ~KEEP_SEND; /* don't send */
+ if(data->state.expect100header)
+ k->exp100 = EXP100_FAILED;
+ }
+ break;
+
+ default: /* default label present to avoid compiler warnings */
+ break;
+ }
+ }
+ }
+
+ if(conn->bits.rewindaftersend) {
+ /* We rewind after a complete send, so thus we continue
+ sending now */
+ infof(data, "Keep sending data to get tossed away!\n");
+ k->keepon |= KEEP_SEND;
+ }
+ }
+
+ if(!k->header) {
+ /*
+ * really end-of-headers.
+ *
+ * If we requested a "no body", this is a good time to get
+ * out and return home.
+ */
+ if(data->set.opt_no_body)
+ *stop_reading = TRUE;
+ else {
+ /* If we know the expected size of this document, we set the
+ maximum download size to the size of the expected
+ document or else, we won't know when to stop reading!
+
+ Note that we set the download maximum even if we read a
+ "Connection: close" header, to make sure that
+ "Content-Length: 0" still prevents us from attempting to
+ read the (missing) response-body.
+ */
+ /* According to RFC2616 section 4.4, we MUST ignore
+ Content-Length: headers if we are now receiving data
+ using chunked Transfer-Encoding.
+ */
+ if(k->chunk)
+ k->maxdownload = k->size = -1;
+ }
+ if(-1 != k->size) {
+ /* We do this operation even if no_body is true, since this
+ data might be retrieved later with curl_easy_getinfo()
+ and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */
+
+ Curl_pgrsSetDownloadSize(data, k->size);
+ k->maxdownload = k->size;
+ }
+
+ /* If max download size is *zero* (nothing) we already
+ have nothing and can safely return ok now! */
+ if(0 == k->maxdownload)
+ *stop_reading = TRUE;
+
+ if(*stop_reading) {
+ /* we make sure that this socket isn't read more now */
+ k->keepon &= ~KEEP_RECV;
+ }
+
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ k->str_start, headerlen, conn);
+ break; /* exit header line loop */
+ }
+
+ /* We continue reading headers, so reset the line-based
+ header parsing variables hbufp && hbuflen */
+ k->hbufp = data->state.headerbuff;
+ k->hbuflen = 0;
+ continue;
+ }
+
+ /*
+ * Checks for special headers coming up.
+ */
+
+ if(!k->headerline++) {
+ /* This is the first header, it MUST be the error code line
+ or else we consider this to be the body right away! */
+ int httpversion_major;
+ int rtspversion_major;
+ int nc = 0;
+#ifdef CURL_DOES_CONVERSIONS
+#define HEADER1 scratch
+#define SCRATCHSIZE 21
+ CURLcode res;
+ char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
+ /* We can't really convert this yet because we
+ don't know if it's the 1st header line or the body.
+ So we do a partial conversion into a scratch area,
+ leaving the data at k->p as-is.
+ */
+ strncpy(&scratch[0], k->p, SCRATCHSIZE);
+ scratch[SCRATCHSIZE] = 0; /* null terminate */
+ res = Curl_convert_from_network(data,
+ &scratch[0],
+ SCRATCHSIZE);
+ if(res)
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ return res;
+#else
+#define HEADER1 k->p /* no conversion needed, just use k->p */
+#endif /* CURL_DOES_CONVERSIONS */
+
+ if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ nc = sscanf(HEADER1,
+ " HTTP/%d.%d %3d",
+ &httpversion_major,
+ &conn->httpversion,
+ &k->httpcode);
+ if(nc==3) {
+ conn->httpversion += 10 * httpversion_major;
+ }
+ else {
+ /* this is the real world, not a Nirvana
+ NCSA 1.5.x returns this crap when asked for HTTP/1.1
+ */
+ nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
+ conn->httpversion = 10;
+
+ /* If user has set option HTTP200ALIASES,
+ compare header line against list of aliases
+ */
+ if(!nc) {
+ if(checkhttpprefix(data, k->p)) {
+ nc = 1;
+ k->httpcode = 200;
+ conn->httpversion = 10;
+ }
+ }
+ }
+ }
+ else if(conn->handler->protocol & CURLPROTO_RTSP) {
+ nc = sscanf(HEADER1,
+ " RTSP/%d.%d %3d",
+ &rtspversion_major,
+ &conn->rtspversion,
+ &k->httpcode);
+ if(nc==3) {
+ conn->rtspversion += 10 * rtspversion_major;
+ conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
+ }
+ else {
+ /* TODO: do we care about the other cases here? */
+ nc = 0;
+ }
+ }
+
+ if(nc) {
+ data->info.httpcode = k->httpcode;
+
+ data->info.httpversion = conn->httpversion;
+ if(!data->state.httpversion ||
+ data->state.httpversion > conn->httpversion)
+ /* store the lowest server version we encounter */
+ data->state.httpversion = conn->httpversion;
+
+ /*
+ * This code executes as part of processing the header. As a
+ * result, it's not totally clear how to interpret the
+ * response code yet as that depends on what other headers may
+ * be present. 401 and 407 may be errors, but may be OK
+ * depending on how authentication is working. Other codes
+ * are definitely errors, so give up here.
+ */
+ if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
+ ((k->httpcode != 401) || !conn->bits.user_passwd) &&
+ ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
+
+ if(data->state.resume_from &&
+ (data->set.httpreq==HTTPREQ_GET) &&
+ (k->httpcode == 416)) {
+ /* "Requested Range Not Satisfiable", just proceed and
+ pretend this is no error */
+ }
+ else {
+ /* serious error, go home! */
+ print_http_error(data);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+ }
+
+ if(conn->httpversion == 10) {
+ /* Default action for HTTP/1.0 must be to close, unless
+ we get one of those fancy headers that tell us the
+ server keeps it open for us! */
+ infof(data, "HTTP 1.0, assume close after body\n");
+ connclose(conn, "HTTP/1.0 close after body");
+ }
+ else if(conn->httpversion >= 11 &&
+ !conn->bits.close) {
+ struct connectbundle *cb_ptr;
+
+ /* If HTTP version is >= 1.1 and connection is persistent
+ server supports pipelining. */
+ DEBUGF(infof(data,
+ "HTTP 1.1 or later with persistent connection, "
+ "pipelining supported\n"));
+ /* Activate pipelining if needed */
+ cb_ptr = conn->bundle;
+ if(cb_ptr) {
+ if(!Curl_pipeline_site_blacklisted(data, conn))
+ cb_ptr->server_supports_pipelining = TRUE;
+ }
+ }
+
+ switch(k->httpcode) {
+ case 204:
+ /* (quote from RFC2616, section 10.2.5): The server has
+ * fulfilled the request but does not need to return an
+ * entity-body ... The 204 response MUST NOT include a
+ * message-body, and thus is always terminated by the first
+ * empty line after the header fields. */
+ /* FALLTHROUGH */
+ case 304:
+ /* (quote from RFC2616, section 10.3.5): The 304 response
+ * MUST NOT contain a message-body, and thus is always
+ * terminated by the first empty line after the header
+ * fields. */
+ if(data->set.timecondition)
+ data->info.timecond = TRUE;
+ k->size=0;
+ k->maxdownload=0;
+ k->ignorecl = TRUE; /* ignore Content-Length headers */
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+ }
+ else {
+ k->header = FALSE; /* this is not a header line */
+ break;
+ }
+ }
+
+ result = Curl_convert_from_network(data, k->p, strlen(k->p));
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+ /* Check for Content-Length: header lines to get size */
+ if(!k->ignorecl && !data->set.ignorecl &&
+ checkprefix("Content-Length:", k->p)) {
+ curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
+ if(data->set.max_filesize &&
+ contentlength > data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+ if(contentlength >= 0) {
+ k->size = contentlength;
+ k->maxdownload = k->size;
+ /* we set the progress download size already at this point
+ just to make it easier for apps/callbacks to extract this
+ info as soon as possible */
+ Curl_pgrsSetDownloadSize(data, k->size);
+ }
+ else {
+ /* Negative Content-Length is really odd, and we know it
+ happens for example when older Apache servers send large
+ files */
+ connclose(conn, "negative content-length");
+ infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
+ ", closing after transfer\n", contentlength);
+ }
+ }
+ /* check for Content-Type: header lines to get the MIME-type */
+ else if(checkprefix("Content-Type:", k->p)) {
+ char *contenttype = Curl_copy_header_value(k->p);
+ if(!contenttype)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*contenttype)
+ /* ignore empty data */
+ free(contenttype);
+ else {
+ Curl_safefree(data->info.contenttype);
+ data->info.contenttype = contenttype;
+ }
+ }
+ else if(checkprefix("Server:", k->p)) {
+ char *server_name = Curl_copy_header_value(k->p);
+
+ /* Turn off pipelining if the server version is blacklisted */
+ if(conn->bundle && conn->bundle->server_supports_pipelining) {
+ if(Curl_pipeline_server_blacklisted(data, server_name))
+ conn->bundle->server_supports_pipelining = FALSE;
+ }
+ Curl_safefree(server_name);
+ }
+ else if((conn->httpversion == 10) &&
+ conn->bits.httpproxy &&
+ Curl_compareheader(k->p,
+ "Proxy-Connection:", "keep-alive")) {
+ /*
+ * When a HTTP/1.0 reply comes when using a proxy, the
+ * 'Proxy-Connection: keep-alive' line tells us the
+ * connection will be kept alive for our pleasure.
+ * Default action for 1.0 is to close.
+ */
+ connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
+ infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
+ }
+ else if((conn->httpversion == 11) &&
+ conn->bits.httpproxy &&
+ Curl_compareheader(k->p,
+ "Proxy-Connection:", "close")) {
+ /*
+ * We get a HTTP/1.1 response from a proxy and it says it'll
+ * close down after this transfer.
+ */
+ connclose(conn, "Proxy-Connection: asked to close after done");
+ infof(data, "HTTP/1.1 proxy connection set close!\n");
+ }
+ else if((conn->httpversion == 10) &&
+ Curl_compareheader(k->p, "Connection:", "keep-alive")) {
+ /*
+ * A HTTP/1.0 reply with the 'Connection: keep-alive' line
+ * tells us the connection will be kept alive for our
+ * pleasure. Default action for 1.0 is to close.
+ *
+ * [RFC2068, section 19.7.1] */
+ connkeep(conn, "Connection keep-alive");
+ infof(data, "HTTP/1.0 connection set to keep alive!\n");
+ }
+ else if(Curl_compareheader(k->p, "Connection:", "close")) {
+ /*
+ * [RFC 2616, section 8.1.2.1]
+ * "Connection: close" is HTTP/1.1 language and means that
+ * the connection will close when this request has been
+ * served.
+ */
+ connclose(conn, "Connection: close used");
+ }
+ else if(checkprefix("Transfer-Encoding:", k->p)) {
+ /* One or more encodings. We check for chunked and/or a compression
+ algorithm. */
+ /*
+ * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
+ * means that the server will send a series of "chunks". Each
+ * chunk starts with line with info (including size of the
+ * coming block) (terminated with CRLF), then a block of data
+ * with the previously mentioned size. There can be any amount
+ * of chunks, and a chunk-data set to zero signals the
+ * end-of-chunks. */
+
+ char *start;
+
+ /* Find the first non-space letter */
+ start = k->p + 18;
+
+ for(;;) {
+ /* skip whitespaces and commas */
+ while(*start && (ISSPACE(*start) || (*start == ',')))
+ start++;
+
+ if(checkprefix("chunked", start)) {
+ k->chunk = TRUE; /* chunks coming our way */
+
+ /* init our chunky engine */
+ Curl_httpchunk_init(conn);
+
+ start += 7;
+ }
+
+ if(k->auto_decoding)
+ /* TODO: we only support the first mentioned compression for now */
+ break;
+
+ if(checkprefix("identity", start)) {
+ k->auto_decoding = IDENTITY;
+ start += 8;
+ }
+ else if(checkprefix("deflate", start)) {
+ k->auto_decoding = DEFLATE;
+ start += 7;
+ }
+ else if(checkprefix("gzip", start)) {
+ k->auto_decoding = GZIP;
+ start += 4;
+ }
+ else if(checkprefix("x-gzip", start)) {
+ k->auto_decoding = GZIP;
+ start += 6;
+ }
+ else if(checkprefix("compress", start)) {
+ k->auto_decoding = COMPRESS;
+ start += 8;
+ }
+ else if(checkprefix("x-compress", start)) {
+ k->auto_decoding = COMPRESS;
+ start += 10;
+ }
+ else
+ /* unknown! */
+ break;
+
+ }
+
+ }
+ else if(checkprefix("Content-Encoding:", k->p) &&
+ (data->set.str[STRING_ENCODING] ||
+ conn->httpversion == 20)) {
+ /*
+ * Process Content-Encoding. Look for the values: identity,
+ * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
+ * x-compress are the same as gzip and compress. (Sec 3.5 RFC
+ * 2616). zlib cannot handle compress. However, errors are
+ * handled further down when the response body is processed
+ */
+ char *start;
+
+ /* Find the first non-space letter */
+ start = k->p + 17;
+ while(*start && ISSPACE(*start))
+ start++;
+
+ /* Record the content-encoding for later use */
+ if(checkprefix("identity", start))
+ k->auto_decoding = IDENTITY;
+ else if(checkprefix("deflate", start))
+ k->auto_decoding = DEFLATE;
+ else if(checkprefix("gzip", start)
+ || checkprefix("x-gzip", start))
+ k->auto_decoding = GZIP;
+ else if(checkprefix("compress", start)
+ || checkprefix("x-compress", start))
+ k->auto_decoding = COMPRESS;
+ }
+ else if(checkprefix("Content-Range:", k->p)) {
+ /* Content-Range: bytes [num]-
+ Content-Range: bytes: [num]-
+ Content-Range: [num]-
+ Content-Range: [asterisk]/[total]
+
+ The second format was added since Sun's webserver
+ JavaWebServer/1.1.1 obviously sends the header this way!
+ The third added since some servers use that!
+ The forth means the requested range was unsatisfied.
+ */
+
+ char *ptr = k->p + 14;
+
+ /* Move forward until first digit or asterisk */
+ while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
+ ptr++;
+
+ /* if it truly stopped on a digit */
+ if(ISDIGIT(*ptr)) {
+ k->offset = curlx_strtoofft(ptr, NULL, 10);
+
+ if(data->state.resume_from == k->offset)
+ /* we asked for a resume and we got it */
+ k->content_range = TRUE;
+ }
+ else
+ data->state.resume_from = 0; /* get everything */
+ }
+#if !defined(CURL_DISABLE_COOKIES)
+ else if(data->cookies &&
+ checkprefix("Set-Cookie:", k->p)) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_add(data,
+ data->cookies, TRUE, k->p+11,
+ /* If there is a custom-set Host: name, use it
+ here, or else use real peer host name. */
+ conn->allocptr.cookiehost?
+ conn->allocptr.cookiehost:conn->host.name,
+ data->state.path);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+#endif
+ else if(checkprefix("Last-Modified:", k->p) &&
+ (data->set.timecondition || data->set.get_filetime) ) {
+ time_t secs=time(NULL);
+ k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
+ &secs);
+ if(data->set.get_filetime)
+ data->info.filetime = (long)k->timeofdoc;
+ }
+ else if((checkprefix("WWW-Authenticate:", k->p) &&
+ (401 == k->httpcode)) ||
+ (checkprefix("Proxy-authenticate:", k->p) &&
+ (407 == k->httpcode))) {
+
+ bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+ char *auth = Curl_copy_header_value(k->p);
+ if(!auth)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_http_input_auth(conn, proxy, auth);
+
+ Curl_safefree(auth);
+
+ if(result)
+ return result;
+ }
+ else if((k->httpcode >= 300 && k->httpcode < 400) &&
+ checkprefix("Location:", k->p) &&
+ !data->req.location) {
+ /* this is the URL that the server advises us to use instead */
+ char *location = Curl_copy_header_value(k->p);
+ if(!location)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*location)
+ /* ignore empty data */
+ free(location);
+ else {
+ data->req.location = location;
+
+ if(data->set.http_follow_location) {
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(data->req.location); /* clone */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* some cases of POST and PUT etc needs to rewind the data
+ stream at this point */
+ result = http_perhapsrewind(conn);
+ if(result)
+ return result;
+ }
+ }
+ }
+ else if(conn->handler->protocol & CURLPROTO_RTSP) {
+ result = Curl_rtsp_parseheader(conn, k->p);
+ if(result)
+ return result;
+ }
+
+ /*
+ * End of header-checks. Write them to the client.
+ */
+
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ k->p, (size_t)k->hbuflen, conn);
+
+ result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
+ if(result)
+ return result;
+
+ data->info.header_size += (long)k->hbuflen;
+ data->req.headerbytecount += (long)k->hbuflen;
+
+ /* reset hbufp pointer && hbuflen */
+ k->hbufp = data->state.headerbuff;
+ k->hbuflen = 0;
+ }
+ while(!*stop_reading && *k->str); /* header line within buffer */
+
+ /* We might have reached the end of the header part here, but
+ there might be a non-header part left in the end of the read
+ buffer. */
+
+ return CURLE_OK;
+}
+
+#endif /* CURL_DISABLE_HTTP */
diff --git a/external/libcurl_android/jni/libcurl/lib/http.h b/external/libcurl_android/jni/libcurl/lib/http.h
new file mode 100755
index 00000000..907755a8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http.h
@@ -0,0 +1,223 @@
+#ifndef HEADER_CURL_HTTP_H
+#define HEADER_CURL_HTTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_HTTP
+
+#ifdef USE_NGHTTP2
+#include <nghttp2/nghttp2.h>
+#endif
+
+extern const struct Curl_handler Curl_handler_http;
+
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_https;
+#endif
+
+/* Header specific functions */
+bool Curl_compareheader(const char *headerline, /* line to check */
+ const char *header, /* header keyword _with_ colon */
+ const char *content); /* content string to find */
+
+char *Curl_checkheaders(const struct connectdata *conn,
+ const char *thisheader);
+char *Curl_copy_header_value(const char *header);
+
+char *Curl_checkProxyheaders(const struct connectdata *conn,
+ const char *thisheader);
+/* ------------------------------------------------------------------------- */
+/*
+ * The add_buffer series of functions are used to build one large memory chunk
+ * from repeated function invokes. Used so that the entire HTTP request can
+ * be sent in one go.
+ */
+struct Curl_send_buffer {
+ char *buffer;
+ size_t size_max;
+ size_t size_used;
+};
+typedef struct Curl_send_buffer Curl_send_buffer;
+
+Curl_send_buffer *Curl_add_buffer_init(void);
+CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...);
+CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size);
+CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
+ struct connectdata *conn,
+ long *bytes_written,
+ size_t included_body_bytes,
+ int socketindex);
+
+CURLcode Curl_add_timecondition(struct SessionHandle *data,
+ Curl_send_buffer *buf);
+CURLcode Curl_add_custom_headers(struct connectdata *conn,
+ bool is_connect,
+ Curl_send_buffer *req_buffer);
+
+/* protocol-specific functions set up to be called by the main engine */
+CURLcode Curl_http(struct connectdata *conn, bool *done);
+CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
+CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
+CURLcode Curl_http_setup_conn(struct connectdata *conn);
+
+/* The following functions are defined in http_chunks.c */
+void Curl_httpchunk_init(struct connectdata *conn);
+CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
+ ssize_t length, ssize_t *wrote);
+
+/* These functions are in http.c */
+void Curl_http_auth_stage(struct SessionHandle *data, int stage);
+CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
+ const char *auth);
+CURLcode Curl_http_auth_act(struct connectdata *conn);
+CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
+
+/* If only the PICKNONE bit is set, there has been a round-trip and we
+ selected to use no auth at all. Ie, we actively select no auth, as opposed
+ to not having one selected. The other CURLAUTH_* defines are present in the
+ public curl/curl.h header. */
+#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */
+
+/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST
+ data get included in the initial data chunk sent to the server. If the
+ data is larger than this, it will automatically get split up in multiple
+ system calls.
+
+ This value used to be fairly big (100K), but we must take into account that
+ if the server rejects the POST due for authentication reasons, this data
+ will always be uncondtionally sent and thus it may not be larger than can
+ always be afforded to send twice.
+
+ It must not be greater than 64K to work on VMS.
+*/
+#ifndef MAX_INITIAL_POST_SIZE
+#define MAX_INITIAL_POST_SIZE (64*1024)
+#endif
+
+#ifndef TINY_INITIAL_POST_SIZE
+#define TINY_INITIAL_POST_SIZE 1024
+#endif
+
+#endif /* CURL_DISABLE_HTTP */
+
+/****************************************************************************
+ * HTTP unique setup
+ ***************************************************************************/
+struct HTTP {
+ struct FormData *sendit;
+ curl_off_t postsize; /* off_t to handle large file sizes */
+ const char *postdata;
+
+ const char *p_pragma; /* Pragma: string */
+ const char *p_accept; /* Accept: string */
+ curl_off_t readbytecount;
+ curl_off_t writebytecount;
+
+ /* For FORM posting */
+ struct Form form;
+
+ struct back {
+ curl_read_callback fread_func; /* backup storage for fread pointer */
+ void *fread_in; /* backup storage for fread_in pointer */
+ const char *postdata;
+ curl_off_t postsize;
+ } backup;
+
+ enum {
+ HTTPSEND_NADA, /* init */
+ HTTPSEND_REQUEST, /* sending a request */
+ HTTPSEND_BODY, /* sending body */
+ HTTPSEND_LAST /* never use this */
+ } sending;
+
+ void *send_buffer; /* used if the request couldn't be sent in one chunk,
+ points to an allocated send_buffer struct */
+};
+
+typedef int (*sending)(void); /* Curl_send */
+typedef int (*recving)(void); /* Curl_recv */
+
+struct http_conn {
+#ifdef USE_NGHTTP2
+#define H2_BINSETTINGS_LEN 80
+ nghttp2_session *h2;
+ uint8_t binsettings[H2_BINSETTINGS_LEN];
+ size_t binlen; /* length of the binsettings data */
+ char *mem; /* points to a buffer in memory to store */
+ size_t len; /* size of the buffer 'mem' points to */
+ bool bodystarted;
+ sending send_underlying; /* underlying send Curl_send callback */
+ recving recv_underlying; /* underlying recv Curl_recv callback */
+ bool closed; /* TRUE on HTTP2 stream close */
+ Curl_send_buffer *header_recvbuf; /* store response headers. We
+ store non-final and final
+ response headers into it. */
+ size_t nread_header_recvbuf; /* number of bytes in header_recvbuf
+ fed into upper layer */
+ int32_t stream_id; /* stream we are interested in */
+ const uint8_t *data; /* pointer to data chunk, received in
+ on_data_chunk */
+ size_t datalen; /* the number of bytes left in data */
+ char *inbuf; /* buffer to receive data from underlying socket */
+ /* We need separate buffer for transmission and reception because we
+ may call nghttp2_session_send() after the
+ nghttp2_session_mem_recv() but mem buffer is still not full. In
+ this case, we wrongly sends the content of mem buffer if we share
+ them for both cases. */
+ const uint8_t *upload_mem; /* points to a buffer to read from */
+ size_t upload_len; /* size of the buffer 'upload_mem' points to */
+ size_t upload_left; /* number of bytes left to upload */
+ int status_code; /* HTTP status code */
+#else
+ int unused; /* prevent a compiler warning */
+#endif
+};
+
+CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *stop_reading);
+
+/**
+ * Curl_http_output_auth() setups the authentication headers for the
+ * host/proxy and the correct authentication
+ * method. conn->data->state.authdone is set to TRUE when authentication is
+ * done.
+ *
+ * @param conn all information about the current connection
+ * @param request pointer to the request keyword
+ * @param path pointer to the requested path
+ * @param proxytunnel boolean if this is the request setting up a "proxy
+ * tunnel"
+ *
+ * @returns CURLcode
+ */
+CURLcode
+Curl_http_output_auth(struct connectdata *conn,
+ const char *request,
+ const char *path,
+ bool proxytunnel); /* TRUE if this is the request setting
+ up the proxy tunnel */
+
+#endif /* HEADER_CURL_HTTP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/http2.c b/external/libcurl_android/jni/libcurl/lib/http2.c
new file mode 100755
index 00000000..604514d7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http2.c
@@ -0,0 +1,1036 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NGHTTP2
+#define _MPRINTF_REPLACE
+#include <curl/mprintf.h>
+
+#include <nghttp2/nghttp2.h>
+#include "urldata.h"
+#include "http2.h"
+#include "http.h"
+#include "sendf.h"
+#include "curl_base64.h"
+#include "curl_memory.h"
+#include "rawstr.h"
+#include "multiif.h"
+
+/* include memdebug.h last */
+#include "memdebug.h"
+
+#if (NGHTTP2_VERSION_NUM < 0x000600)
+#error too old nghttp2 version, upgrade!
+#endif
+
+static int http2_perform_getsock(const struct connectdata *conn,
+ curl_socket_t *sock, /* points to
+ numsocks
+ number of
+ sockets */
+ int numsocks)
+{
+ const struct http_conn *httpc = &conn->proto.httpc;
+ int bitmap = GETSOCK_BLANK;
+ (void)numsocks;
+
+ /* TODO We should check underlying socket state if it is SSL socket
+ because of renegotiation. */
+ sock[0] = conn->sock[FIRSTSOCKET];
+
+ if(nghttp2_session_want_read(httpc->h2))
+ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+
+ if(nghttp2_session_want_write(httpc->h2))
+ bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
+
+ return bitmap;
+}
+
+static int http2_getsock(struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks
+ number of sockets */
+ int numsocks)
+{
+ return http2_perform_getsock(conn, sock, numsocks);
+}
+
+static CURLcode http2_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ struct http_conn *httpc = &conn->proto.httpc;
+ (void)dead_connection;
+
+ infof(conn->data, "HTTP/2 DISCONNECT starts now\n");
+
+ nghttp2_session_del(httpc->h2);
+
+ Curl_safefree(httpc->header_recvbuf->buffer);
+ Curl_safefree(httpc->header_recvbuf);
+
+ Curl_safefree(httpc->inbuf);
+
+ infof(conn->data, "HTTP/2 DISCONNECT done\n");
+
+ return CURLE_OK;
+}
+
+/*
+ * HTTP2 handler interface. This isn't added to the general list of protocols
+ * but will be used at run-time when the protocol is dynamically switched from
+ * HTTP to HTTP2.
+ */
+const struct Curl_handler Curl_handler_http2 = {
+ "HTTP2", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ Curl_http, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ http2_getsock, /* proto_getsock */
+ http2_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ http2_perform_getsock, /* perform_getsock */
+ http2_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+const struct Curl_handler Curl_handler_http2_ssl = {
+ "HTTP2", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ Curl_http, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ http2_getsock, /* proto_getsock */
+ http2_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ http2_perform_getsock, /* perform_getsock */
+ http2_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_HTTP, /* defport */
+ CURLPROTO_HTTPS, /* protocol */
+ PROTOPT_SSL /* flags */
+};
+
+/*
+ * Store nghttp2 version info in this buffer, Prefix with a space. Return
+ * total length written.
+ */
+int Curl_http2_ver(char *p, size_t len)
+{
+ nghttp2_info *h2 = nghttp2_version(0);
+ return snprintf(p, len, " nghttp2/%s", h2->version_str);
+}
+
+/*
+ * The implementation of nghttp2_send_callback type. Here we write |data| with
+ * size |length| to the network and return the number of bytes actually
+ * written. See the documentation of nghttp2_send_callback for the details.
+ */
+static ssize_t send_callback(nghttp2_session *h2,
+ const uint8_t *data, size_t length, int flags,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *httpc = &conn->proto.httpc;
+ ssize_t written;
+ CURLcode rc;
+ (void)h2;
+ (void)flags;
+
+ rc = 0;
+ written = ((Curl_send*)httpc->send_underlying)(conn, FIRSTSOCKET,
+ data, length, &rc);
+
+ if(rc == CURLE_AGAIN) {
+ return NGHTTP2_ERR_WOULDBLOCK;
+ }
+
+ if(written == -1) {
+ failf(conn->data, "Failed sending HTTP2 data");
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ if(!written)
+ return NGHTTP2_ERR_WOULDBLOCK;
+
+ return written;
+}
+
+static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ int rv;
+ size_t left, ncopy;
+
+ (void)session;
+ (void)frame;
+ infof(conn->data, "on_frame_recv() was called with header %x\n",
+ frame->hd.type);
+ switch(frame->hd.type) {
+ case NGHTTP2_DATA:
+ /* If body started, then receiving DATA is illegal. */
+ if(!c->bodystarted) {
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ break;
+ case NGHTTP2_HEADERS:
+ if(frame->headers.cat == NGHTTP2_HCAT_REQUEST)
+ break;
+
+ if(c->bodystarted) {
+ /* Only valid HEADERS after body started is trailer header,
+ which is not fully supported in this code. If HEADERS is not
+ trailer, then it is a PROTOCOL_ERROR. */
+ if((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ break;
+ }
+
+ if(c->status_code == -1) {
+ /* No :status header field means PROTOCOL_ERROR. */
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ break;
+ }
+
+ /* Only final status code signals the end of header */
+ if(c->status_code / 100 != 1) {
+ c->bodystarted = TRUE;
+ }
+
+ c->status_code = -1;
+
+ Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
+
+ left = c->header_recvbuf->size_used - c->nread_header_recvbuf;
+ ncopy = c->len < left ? c->len : left;
+
+ memcpy(c->mem, c->header_recvbuf->buffer + c->nread_header_recvbuf, ncopy);
+ c->nread_header_recvbuf += ncopy;
+
+ c->mem += ncopy;
+ c->len -= ncopy;
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->push_promise.promised_stream_id,
+ NGHTTP2_CANCEL);
+ if(nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ break;
+ }
+ return 0;
+}
+
+static int on_invalid_frame_recv(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ uint32_t error_code, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ infof(conn->data, "on_invalid_frame_recv() was called, error_code = %d\n",
+ error_code);
+ return 0;
+}
+
+static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const uint8_t *data, size_t len, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ size_t nread;
+ (void)session;
+ (void)flags;
+ (void)data;
+ infof(conn->data, "on_data_chunk_recv() "
+ "len = %u, stream = %x\n", len, stream_id);
+
+ if(stream_id != c->stream_id) {
+ return 0;
+ }
+
+ nread = c->len < len ? c->len : len;
+ memcpy(c->mem, data, nread);
+
+ c->mem += nread;
+ c->len -= nread;
+
+ infof(conn->data, "%zu data written\n", nread);
+
+ if(nread < len) {
+ c->data = data + nread;
+ c->datalen = len - nread;
+ return NGHTTP2_ERR_PAUSE;
+ }
+ return 0;
+}
+
+static int before_frame_send(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ infof(conn->data, "before_frame_send() was called\n");
+ return 0;
+}
+static int on_frame_send(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ infof(conn->data, "on_frame_send() was called\n");
+ return 0;
+}
+static int on_frame_not_send(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ int lib_error_code, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ infof(conn->data, "on_frame_not_send() was called, lib_error_code = %d\n",
+ lib_error_code);
+ return 0;
+}
+static int on_stream_close(nghttp2_session *session, int32_t stream_id,
+ uint32_t error_code, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ (void)session;
+ (void)stream_id;
+ infof(conn->data, "on_stream_close() was called, error_code = %d\n",
+ error_code);
+
+ if(stream_id != c->stream_id) {
+ return 0;
+ }
+
+ c->closed = TRUE;
+
+ return 0;
+}
+
+static int on_begin_headers(nghttp2_session *session,
+ const nghttp2_frame *frame, void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ (void)session;
+ (void)frame;
+ infof(conn->data, "on_begin_headers() was called\n");
+ return 0;
+}
+
+/* Decode HTTP status code. Returns -1 if no valid status code was
+ decoded. */
+static int decode_status_code(const uint8_t *value, size_t len)
+{
+ int i;
+ int res;
+
+ if(len != 3) {
+ return -1;
+ }
+
+ res = 0;
+
+ for(i = 0; i < 3; ++i) {
+ char c = value[i];
+
+ if(c < '0' || c > '9') {
+ return -1;
+ }
+
+ res *= 10;
+ res += c - '0';
+ }
+
+ return res;
+}
+
+static const char STATUS[] = ":status";
+
+/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
+static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ int rv;
+ int goodname;
+ int goodheader;
+
+ (void)session;
+ (void)frame;
+ (void)flags;
+
+ if(frame->hd.stream_id != c->stream_id) {
+ return 0;
+ }
+
+ if(c->bodystarted) {
+ /* Ignore trailer or HEADERS not mapped to HTTP semantics. The
+ consequence is handled in on_frame_recv(). */
+ return 0;
+ }
+
+ goodname = nghttp2_check_header_name(name, namelen);
+ goodheader = nghttp2_check_header_value(value, valuelen);
+
+ if(!goodname || !goodheader) {
+
+ infof(conn->data, "Detected bad incoming header %s%s, reset stream!\n",
+ goodname?"":"name",
+ goodheader?"":"value");
+
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+
+ if(namelen == sizeof(":status") - 1 &&
+ memcmp(STATUS, name, namelen) == 0) {
+
+ /* :status must appear exactly once. */
+ if(c->status_code != -1 ||
+ (c->status_code = decode_status_code(value, valuelen)) == -1) {
+
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+
+ Curl_add_buffer(c->header_recvbuf, "HTTP/2.0 ", 9);
+ Curl_add_buffer(c->header_recvbuf, value, valuelen);
+ Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
+
+ return 0;
+ }
+ else {
+ /* Here we are sure that namelen > 0 because of
+ nghttp2_check_header_name(). Pseudo header other than :status
+ is illegal. */
+ if(c->status_code == -1 || name[0] == ':') {
+ rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+ frame->hd.stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+ if(nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+
+ /* convert to a HTTP1-style header */
+ Curl_add_buffer(c->header_recvbuf, name, namelen);
+ Curl_add_buffer(c->header_recvbuf, ":", 1);
+ Curl_add_buffer(c->header_recvbuf, value, valuelen);
+ Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
+
+ infof(conn->data, "got http2 header: %.*s: %.*s\n",
+ namelen, name, valuelen, value);
+ }
+
+ return 0; /* 0 is successful */
+}
+
+static ssize_t data_source_read_callback(nghttp2_session *session,
+ int32_t stream_id,
+ uint8_t *buf, size_t length,
+ uint32_t *data_flags,
+ nghttp2_data_source *source,
+ void *userp)
+{
+ struct connectdata *conn = (struct connectdata *)userp;
+ struct http_conn *c = &conn->proto.httpc;
+ size_t nread;
+ (void)session;
+ (void)stream_id;
+ (void)source;
+
+ nread = c->upload_len < length ? c->upload_len : length;
+ if(nread > 0) {
+ memcpy(buf, c->upload_mem, nread);
+ c->upload_mem += nread;
+ c->upload_len -= nread;
+ c->upload_left -= nread;
+ }
+
+ if(c->upload_left == 0)
+ *data_flags = 1;
+ else if(nread == 0)
+ return NGHTTP2_ERR_DEFERRED;
+
+ return nread;
+}
+
+/*
+ * The HTTP2 settings we send in the Upgrade request
+ */
+static nghttp2_settings_entry settings[] = {
+ { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
+ { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
+};
+
+#define H2_BUFSIZE 4096
+
+/*
+ * Initialize nghttp2 for a Curl connection
+ */
+CURLcode Curl_http2_init(struct connectdata *conn)
+{
+ if(!conn->proto.httpc.h2) {
+ int rc;
+ nghttp2_session_callbacks *callbacks;
+
+ conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
+ if(conn->proto.httpc.inbuf == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ rc = nghttp2_session_callbacks_new(&callbacks);
+
+ if(rc) {
+ failf(conn->data, "Couldn't initialize nghttp2 callbacks!");
+ return CURLE_OUT_OF_MEMORY; /* most likely at least */
+ }
+
+ /* nghttp2_send_callback */
+ nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
+ /* nghttp2_on_frame_recv_callback */
+ nghttp2_session_callbacks_set_on_frame_recv_callback
+ (callbacks, on_frame_recv);
+ /* nghttp2_on_invalid_frame_recv_callback */
+ nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
+ (callbacks, on_invalid_frame_recv);
+ /* nghttp2_on_data_chunk_recv_callback */
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback
+ (callbacks, on_data_chunk_recv);
+ /* nghttp2_before_frame_send_callback */
+ nghttp2_session_callbacks_set_before_frame_send_callback
+ (callbacks, before_frame_send);
+ /* nghttp2_on_frame_send_callback */
+ nghttp2_session_callbacks_set_on_frame_send_callback
+ (callbacks, on_frame_send);
+ /* nghttp2_on_frame_not_send_callback */
+ nghttp2_session_callbacks_set_on_frame_not_send_callback
+ (callbacks, on_frame_not_send);
+ /* nghttp2_on_stream_close_callback */
+ nghttp2_session_callbacks_set_on_stream_close_callback
+ (callbacks, on_stream_close);
+ /* nghttp2_on_begin_headers_callback */
+ nghttp2_session_callbacks_set_on_begin_headers_callback
+ (callbacks, on_begin_headers);
+ /* nghttp2_on_header_callback */
+ nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
+
+ /* The nghttp2 session is not yet setup, do it */
+ rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
+ callbacks, conn);
+
+ nghttp2_session_callbacks_del(callbacks);
+
+ if(rc) {
+ failf(conn->data, "Couldn't initialize nghttp2!");
+ return CURLE_OUT_OF_MEMORY; /* most likely at least */
+ }
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Send a request using http2
+ */
+CURLcode Curl_http2_send_request(struct connectdata *conn)
+{
+ (void)conn;
+ return CURLE_OK;
+}
+
+/*
+ * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
+ */
+CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ ssize_t binlen;
+ char *base64;
+ size_t blen;
+ struct SingleRequest *k = &conn->data->req;
+ uint8_t *binsettings = conn->proto.httpc.binsettings;
+
+ result = Curl_http2_init(conn);
+ if(result)
+ return result;
+
+ result = Curl_http2_setup(conn);
+ if(result)
+ return result;
+
+ /* As long as we have a fixed set of settings, we don't have to dynamically
+ * figure out the base64 strings since it'll always be the same. However,
+ * the settings will likely not be fixed every time in the future.
+ */
+
+ /* this returns number of bytes it wrote */
+ binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
+ settings,
+ sizeof(settings)/sizeof(settings[0]));
+ if(!binlen) {
+ failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
+ return CURLE_FAILED_INIT;
+ }
+ conn->proto.httpc.binlen = binlen;
+
+ result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
+ &base64, &blen);
+ if(result)
+ return result;
+
+ result = Curl_add_bufferf(req,
+ "Connection: Upgrade, HTTP2-Settings\r\n"
+ "Upgrade: %s\r\n"
+ "HTTP2-Settings: %s\r\n",
+ NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
+ Curl_safefree(base64);
+
+ k->upgr101 = UPGR101_REQUESTED;
+
+ return result;
+}
+
+/*
+ * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
+ * a regular CURLcode value.
+ */
+static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err)
+{
+ CURLcode rc;
+ ssize_t rv;
+ ssize_t nread;
+ struct http_conn *httpc = &conn->proto.httpc;
+
+ (void)sockindex; /* we always do HTTP2 on sockindex 0 */
+
+ if(httpc->closed) {
+ /* Reset to FALSE to prevent infinite loop in readwrite_data
+ function. */
+ httpc->closed = FALSE;
+ return 0;
+ }
+
+ /* Nullify here because we call nghttp2_session_send() and they
+ might refer to the old buffer. */
+ httpc->upload_mem = NULL;
+ httpc->upload_len = 0;
+
+ if(httpc->bodystarted &&
+ httpc->nread_header_recvbuf < httpc->header_recvbuf->size_used) {
+ size_t left =
+ httpc->header_recvbuf->size_used - httpc->nread_header_recvbuf;
+ size_t ncopy = len < left ? len : left;
+ memcpy(mem, httpc->header_recvbuf->buffer + httpc->nread_header_recvbuf,
+ ncopy);
+ httpc->nread_header_recvbuf += ncopy;
+ return ncopy;
+ }
+
+ if(httpc->data) {
+ nread = len < httpc->datalen ? len : httpc->datalen;
+ memcpy(mem, httpc->data, nread);
+
+ httpc->data += nread;
+ httpc->datalen -= nread;
+
+ infof(conn->data, "%zu data written\n", nread);
+ if(httpc->datalen == 0) {
+ httpc->data = NULL;
+ httpc->datalen = 0;
+ }
+ return nread;
+ }
+
+ conn->proto.httpc.mem = mem;
+ conn->proto.httpc.len = len;
+
+ infof(conn->data, "http2_recv: %d bytes buffer\n",
+ conn->proto.httpc.len);
+
+ rc = 0;
+ nread = ((Curl_recv*)httpc->recv_underlying)(conn, FIRSTSOCKET,
+ httpc->inbuf, H2_BUFSIZE, &rc);
+
+ if(rc == CURLE_AGAIN) {
+ *err = rc;
+ return -1;
+ }
+
+ if(nread == -1) {
+ failf(conn->data, "Failed receiving HTTP2 data");
+ *err = rc;
+ return 0;
+ }
+
+ infof(conn->data, "nread=%zd\n", nread);
+ rv = nghttp2_session_mem_recv(httpc->h2,
+ (const uint8_t *)httpc->inbuf, nread);
+
+ if(nghttp2_is_fatal((int)rv)) {
+ failf(conn->data, "nghttp2_session_mem_recv() returned %d:%s\n",
+ rv, nghttp2_strerror((int)rv));
+ *err = CURLE_RECV_ERROR;
+ return 0;
+ }
+ infof(conn->data, "nghttp2_session_mem_recv() returns %zd\n", rv);
+ /* Always send pending frames in nghttp2 session, because
+ nghttp2_session_mem_recv() may queue new frame */
+ rv = nghttp2_session_send(httpc->h2);
+ if(rv != 0) {
+ *err = CURLE_SEND_ERROR;
+ return 0;
+ }
+ if(len != httpc->len) {
+ return len - conn->proto.httpc.len;
+ }
+ /* If stream is closed, return 0 to signal the http routine to close
+ the connection */
+ if(httpc->closed) {
+ /* Reset to FALSE to prevent infinite loop in readwrite_data
+ function. */
+ httpc->closed = FALSE;
+ return 0;
+ }
+ *err = CURLE_AGAIN;
+ return -1;
+}
+
+/* Index where :authority header field will appear in request header
+ field list. */
+#define AUTHORITY_DST_IDX 3
+
+/* return number of received (decrypted) bytes */
+static ssize_t http2_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, CURLcode *err)
+{
+ /*
+ * BIG TODO: Currently, we send request in this function, but this
+ * function is also used to send request body. It would be nice to
+ * add dedicated function for request.
+ */
+ int rv;
+ struct http_conn *httpc = &conn->proto.httpc;
+ nghttp2_nv *nva;
+ size_t nheader;
+ size_t i;
+ size_t authority_idx;
+ char *hdbuf = (char*)mem;
+ char *end;
+ nghttp2_data_provider data_prd;
+ int32_t stream_id;
+
+ (void)sockindex;
+
+ infof(conn->data, "http2_send len=%zu\n", len);
+
+ if(httpc->stream_id != -1) {
+ /* If stream_id != -1, we have dispatched request HEADERS, and now
+ are going to send or sending request body in DATA frame */
+ httpc->upload_mem = mem;
+ httpc->upload_len = len;
+ nghttp2_session_resume_data(httpc->h2, httpc->stream_id);
+ rv = nghttp2_session_send(httpc->h2);
+ if(nghttp2_is_fatal(rv)) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ return len - httpc->upload_len;
+ }
+
+ /* Calculate number of headers contained in [mem, mem + len) */
+ /* Here, we assume the curl http code generate *correct* HTTP header
+ field block */
+ nheader = 0;
+ for(i = 0; i < len; ++i) {
+ if(hdbuf[i] == 0x0a) {
+ ++nheader;
+ }
+ }
+ /* We counted additional 2 \n in the first and last line. We need 3
+ new headers: :method, :path and :scheme. Therefore we need one
+ more space. */
+ nheader += 1;
+ nva = malloc(sizeof(nghttp2_nv) * nheader);
+ if(nva == NULL) {
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ /* Extract :method, :path from request line */
+ end = strchr(hdbuf, ' ');
+ nva[0].name = (unsigned char *)":method";
+ nva[0].namelen = (uint16_t)strlen((char *)nva[0].name);
+ nva[0].value = (unsigned char *)hdbuf;
+ nva[0].valuelen = (uint16_t)(end - hdbuf);
+ nva[0].flags = NGHTTP2_NV_FLAG_NONE;
+
+ hdbuf = end + 1;
+
+ end = strchr(hdbuf, ' ');
+ nva[1].name = (unsigned char *)":path";
+ nva[1].namelen = (uint16_t)strlen((char *)nva[1].name);
+ nva[1].value = (unsigned char *)hdbuf;
+ nva[1].valuelen = (uint16_t)(end - hdbuf);
+ nva[1].flags = NGHTTP2_NV_FLAG_NONE;
+
+ nva[2].name = (unsigned char *)":scheme";
+ nva[2].namelen = (uint16_t)strlen((char *)nva[2].name);
+ if(conn->handler->flags & PROTOPT_SSL)
+ nva[2].value = (unsigned char *)"https";
+ else
+ nva[2].value = (unsigned char *)"http";
+ nva[2].valuelen = (uint16_t)strlen((char *)nva[2].value);
+ nva[2].flags = NGHTTP2_NV_FLAG_NONE;
+
+ hdbuf = strchr(hdbuf, 0x0a);
+ ++hdbuf;
+
+ authority_idx = 0;
+
+ for(i = 3; i < nheader; ++i) {
+ end = strchr(hdbuf, ':');
+ assert(end);
+ if(end - hdbuf == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
+ authority_idx = i;
+ nva[i].name = (unsigned char *)":authority";
+ nva[i].namelen = (uint16_t)strlen((char *)nva[i].name);
+ }
+ else {
+ nva[i].name = (unsigned char *)hdbuf;
+ nva[i].namelen = (uint16_t)(end - hdbuf);
+ }
+ hdbuf = end + 1;
+ for(; *hdbuf == ' '; ++hdbuf);
+ end = strchr(hdbuf, 0x0d);
+ assert(end);
+ nva[i].value = (unsigned char *)hdbuf;
+ nva[i].valuelen = (uint16_t)(end - hdbuf);
+ nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+
+ hdbuf = end + 2;
+ /* Inspect Content-Length header field and retrieve the request
+ entity length so that we can set END_STREAM to the last DATA
+ frame. */
+ if(nva[i].namelen == 14 &&
+ Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) {
+ size_t j;
+ for(j = 0; j < nva[i].valuelen; ++j) {
+ httpc->upload_left *= 10;
+ httpc->upload_left += nva[i].value[j] - '0';
+ }
+ infof(conn->data, "request content-length=%zu\n", httpc->upload_left);
+ }
+ }
+
+ /* :authority must come before non-pseudo header fields */
+ if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
+ nghttp2_nv authority = nva[authority_idx];
+ for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
+ nva[i] = nva[i - 1];
+ }
+ nva[i] = authority;
+ }
+
+ switch(conn->data->set.httpreq) {
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_PUT:
+ data_prd.read_callback = data_source_read_callback;
+ data_prd.source.ptr = NULL;
+ stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader,
+ &data_prd, NULL);
+ break;
+ default:
+ stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader,
+ NULL, NULL);
+ }
+
+ Curl_safefree(nva);
+
+ if(stream_id < 0) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ httpc->stream_id = stream_id;
+
+ rv = nghttp2_session_send(httpc->h2);
+
+ if(rv != 0) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ if(httpc->stream_id != -1) {
+ /* If whole HEADERS frame was sent off to the underlying socket,
+ the nghttp2 library calls data_source_read_callback. But only
+ it found that no data available, so it deferred the DATA
+ transmission. Which means that nghttp2_session_want_write()
+ returns 0 on http2_perform_getsock(), which results that no
+ writable socket check is performed. To workaround this, we
+ issue nghttp2_session_resume_data() here to bring back DATA
+ transmission from deferred state. */
+ nghttp2_session_resume_data(httpc->h2, httpc->stream_id);
+ }
+
+ return len;
+}
+
+CURLcode Curl_http2_setup(struct connectdata *conn)
+{
+ struct http_conn *httpc = &conn->proto.httpc;
+ if(conn->handler->flags & PROTOPT_SSL)
+ conn->handler = &Curl_handler_http2_ssl;
+ else
+ conn->handler = &Curl_handler_http2;
+
+ infof(conn->data, "Using HTTP2\n");
+ httpc->bodystarted = FALSE;
+ httpc->closed = FALSE;
+ httpc->header_recvbuf = Curl_add_buffer_init();
+ httpc->nread_header_recvbuf = 0;
+ httpc->data = NULL;
+ httpc->datalen = 0;
+ httpc->upload_left = 0;
+ httpc->upload_mem = NULL;
+ httpc->upload_len = 0;
+ httpc->stream_id = -1;
+ httpc->status_code = -1;
+
+ conn->httpversion = 20;
+
+ return 0;
+}
+
+CURLcode Curl_http2_switched(struct connectdata *conn)
+{
+ CURLcode rc;
+ struct http_conn *httpc = &conn->proto.httpc;
+ int rv;
+ struct SessionHandle *data = conn->data;
+
+ httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
+ httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
+ conn->recv[FIRSTSOCKET] = http2_recv;
+ conn->send[FIRSTSOCKET] = http2_send;
+
+ rv = (int) ((Curl_send*)httpc->send_underlying)
+ (conn, FIRSTSOCKET,
+ NGHTTP2_CLIENT_CONNECTION_PREFACE,
+ NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN,
+ &rc);
+ if(rc)
+ /* TODO: This may get CURLE_AGAIN */
+ return rc;
+
+ if(rv != 24) {
+ failf(data, "Only sent partial HTTP2 packet");
+ return CURLE_SEND_ERROR;
+ }
+
+ if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
+ /* stream 1 is opened implicitly on upgrade */
+ httpc->stream_id = 1;
+ /* queue SETTINGS frame (again) */
+ rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
+ httpc->binlen, NULL);
+ if(rv != 0) {
+ failf(data, "nghttp2_session_upgrade() failed: %s(%d)",
+ nghttp2_strerror(rv), rv);
+ return CURLE_HTTP2;
+ }
+ }
+ else {
+ /* stream ID is unknown at this point */
+ httpc->stream_id = -1;
+ rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
+ if(rv != 0) {
+ failf(data, "nghttp2_submit_settings() failed: %s(%d)",
+ nghttp2_strerror(rv), rv);
+ return CURLE_HTTP2;
+ }
+ }
+ return CURLE_OK;
+}
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/http2.h b/external/libcurl_android/jni/libcurl/lib/http2.h
new file mode 100755
index 00000000..66aa6fd5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http2.h
@@ -0,0 +1,50 @@
+#ifndef HEADER_CURL_HTTP2_H
+#define HEADER_CURL_HTTP2_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_NGHTTP2
+#include "http.h"
+/*
+ * Store nghttp2 version info in this buffer, Prefix with a space. Return
+ * total length written.
+ */
+int Curl_http2_ver(char *p, size_t len);
+
+CURLcode Curl_http2_init(struct connectdata *conn);
+CURLcode Curl_http2_send_request(struct connectdata *conn);
+CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+ struct connectdata *conn);
+CURLcode Curl_http2_setup(struct connectdata *conn);
+CURLcode Curl_http2_switched(struct connectdata *conn);
+#else /* USE_NGHTTP2 */
+#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_switched(x) CURLE_UNSUPPORTED_PROTOCOL
+#endif
+
+#endif /* HEADER_CURL_HTTP2_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/http_chunks.c b/external/libcurl_android/jni/libcurl/lib/http_chunks.c
new file mode 100755
index 00000000..61a6098a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_chunks.c
@@ -0,0 +1,385 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_HTTP
+
+#include "urldata.h" /* it includes http_chunks.h */
+#include "sendf.h" /* for the client write stuff */
+
+#include "content_encoding.h"
+#include "http.h"
+#include "curl_memory.h"
+#include "non-ascii.h" /* for Curl_convert_to_network prototype */
+#include "strtoofft.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Chunk format (simplified):
+ *
+ * <HEX SIZE>[ chunk extension ] CRLF
+ * <DATA> CRLF
+ *
+ * Highlights from RFC2616 section 3.6 say:
+
+ The chunked encoding modifies the body of a message in order to
+ transfer it as a series of chunks, each with its own size indicator,
+ followed by an OPTIONAL trailer containing entity-header fields. This
+ allows dynamically produced content to be transferred along with the
+ information necessary for the recipient to verify that it has
+ received the full message.
+
+ Chunked-Body = *chunk
+ last-chunk
+ trailer
+ CRLF
+
+ chunk = chunk-size [ chunk-extension ] CRLF
+ chunk-data CRLF
+ chunk-size = 1*HEX
+ last-chunk = 1*("0") [ chunk-extension ] CRLF
+
+ chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+ chunk-ext-name = token
+ chunk-ext-val = token | quoted-string
+ chunk-data = chunk-size(OCTET)
+ trailer = *(entity-header CRLF)
+
+ The chunk-size field is a string of hex digits indicating the size of
+ the chunk. The chunked encoding is ended by any chunk whose size is
+ zero, followed by the trailer, which is terminated by an empty line.
+
+ */
+
+/* Check for an ASCII hex digit.
+ We avoid the use of isxdigit to accommodate non-ASCII hosts. */
+static bool Curl_isxdigit(char digit)
+{
+ return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */
+ || (digit >= 0x41 && digit <= 0x46) /* A-F */
+ || (digit >= 0x61 && digit <= 0x66) /* a-f */ ) ? TRUE : FALSE;
+}
+
+void Curl_httpchunk_init(struct connectdata *conn)
+{
+ struct Curl_chunker *chunk = &conn->chunk;
+ chunk->hexindex=0; /* start at 0 */
+ chunk->dataleft=0; /* no data left yet! */
+ chunk->state = CHUNK_HEX; /* we get hex first! */
+}
+
+/*
+ * chunk_read() returns a OK for normal operations, or a positive return code
+ * for errors. STOP means this sequence of chunks is complete. The 'wrote'
+ * argument is set to tell the caller how many bytes we actually passed to the
+ * client (for byte-counting and whatever).
+ *
+ * The states and the state-machine is further explained in the header file.
+ *
+ * This function always uses ASCII hex values to accommodate non-ASCII hosts.
+ * For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
+ */
+CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
+ char *datap,
+ ssize_t datalen,
+ ssize_t *wrotep)
+{
+ CURLcode result=CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct Curl_chunker *ch = &conn->chunk;
+ struct SingleRequest *k = &data->req;
+ size_t piece;
+ curl_off_t length = (curl_off_t)datalen;
+ size_t *wrote = (size_t *)wrotep;
+
+ *wrote = 0; /* nothing's written yet */
+
+ /* the original data is written to the client, but we go on with the
+ chunk read process, to properly calculate the content length*/
+ if(data->set.http_te_skip && !k->ignorebody) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen);
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+ }
+
+ while(length) {
+ switch(ch->state) {
+ case CHUNK_HEX:
+ if(Curl_isxdigit(*datap)) {
+ if(ch->hexindex < MAXNUM_SIZE) {
+ ch->hexbuffer[ch->hexindex] = *datap;
+ datap++;
+ length--;
+ ch->hexindex++;
+ }
+ else {
+ return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */
+ }
+ }
+ else {
+ char *endptr;
+ if(0 == ch->hexindex)
+ /* This is illegal data, we received junk where we expected
+ a hexadecimal digit. */
+ return CHUNKE_ILLEGAL_HEX;
+
+ /* length and datap are unmodified */
+ ch->hexbuffer[ch->hexindex]=0;
+
+ /* convert to host encoding before calling strtoul */
+ result = Curl_convert_from_network(conn->data, ch->hexbuffer,
+ ch->hexindex);
+ if(result) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* Treat it as a bad hex character */
+ return CHUNKE_ILLEGAL_HEX ;
+ }
+
+ ch->datasize=curlx_strtoofft(ch->hexbuffer, &endptr, 16);
+ if((ch->datasize == CURL_OFF_T_MAX) && (errno == ERANGE))
+ /* overflow is an error */
+ return CHUNKE_ILLEGAL_HEX;
+ ch->state = CHUNK_LF; /* now wait for the CRLF */
+ }
+ break;
+
+ case CHUNK_LF:
+ /* waiting for the LF after a chunk size */
+ if(*datap == 0x0a) {
+ /* we're now expecting data to come, unless size was zero! */
+ if(0 == ch->datasize) {
+ ch->state = CHUNK_TRAILER; /* now check for trailers */
+ conn->trlPos=0;
+ }
+ else
+ ch->state = CHUNK_DATA;
+ }
+
+ datap++;
+ length--;
+ break;
+
+ case CHUNK_DATA:
+ /* We expect 'datasize' of data. We have 'length' right now, it can be
+ more or less than 'datasize'. Get the smallest piece.
+ */
+ piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
+
+ /* Write the data portion available */
+#ifdef HAVE_LIBZ
+ switch (conn->data->set.http_ce_skip?
+ IDENTITY : data->req.auto_decoding) {
+ case IDENTITY:
+#endif
+ if(!k->ignorebody) {
+ if(!data->set.http_te_skip)
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, datap,
+ piece);
+ else
+ result = CURLE_OK;
+ }
+#ifdef HAVE_LIBZ
+ break;
+
+ case DEFLATE:
+ /* update data->req.keep.str to point to the chunk data. */
+ data->req.str = datap;
+ result = Curl_unencode_deflate_write(conn, &data->req,
+ (ssize_t)piece);
+ break;
+
+ case GZIP:
+ /* update data->req.keep.str to point to the chunk data. */
+ data->req.str = datap;
+ result = Curl_unencode_gzip_write(conn, &data->req,
+ (ssize_t)piece);
+ break;
+
+ case COMPRESS:
+ default:
+ failf (conn->data,
+ "Unrecognized content encoding type. "
+ "libcurl understands `identity', `deflate' and `gzip' "
+ "content encodings.");
+ return CHUNKE_BAD_ENCODING;
+ }
+#endif
+
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+
+ *wrote += piece;
+
+ ch->datasize -= piece; /* decrease amount left to expect */
+ datap += piece; /* move read pointer forward */
+ length -= piece; /* decrease space left in this round */
+
+ if(0 == ch->datasize)
+ /* end of data this round, we now expect a trailing CRLF */
+ ch->state = CHUNK_POSTLF;
+ break;
+
+ case CHUNK_POSTLF:
+ if(*datap == 0x0a) {
+ /* The last one before we go back to hex state and start all over. */
+ Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */
+ }
+ else if(*datap != 0x0d)
+ return CHUNKE_BAD_CHUNK;
+ datap++;
+ length--;
+ break;
+
+ case CHUNK_TRAILER:
+ if((*datap == 0x0d) || (*datap == 0x0a)) {
+ /* this is the end of a trailer, but if the trailer was zero bytes
+ there was no trailer and we move on */
+
+ if(conn->trlPos) {
+ /* we allocate trailer with 3 bytes extra room to fit this */
+ conn->trailer[conn->trlPos++]=0x0d;
+ conn->trailer[conn->trlPos++]=0x0a;
+ conn->trailer[conn->trlPos]=0;
+
+ /* Convert to host encoding before calling Curl_client_write */
+ result = Curl_convert_from_network(conn->data, conn->trailer,
+ conn->trlPos);
+ if(result)
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* Treat it as a bad chunk */
+ return CHUNKE_BAD_CHUNK;
+
+ if(!data->set.http_te_skip) {
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ conn->trailer, conn->trlPos);
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+ }
+ conn->trlPos=0;
+ ch->state = CHUNK_TRAILER_CR;
+ if(*datap == 0x0a)
+ /* already on the LF */
+ break;
+ }
+ else {
+ /* no trailer, we're on the final CRLF pair */
+ ch->state = CHUNK_TRAILER_POSTCR;
+ break; /* don't advance the pointer */
+ }
+ }
+ else {
+ /* conn->trailer is assumed to be freed in url.c on a
+ connection basis */
+ if(conn->trlPos >= conn->trlMax) {
+ /* we always allocate three extra bytes, just because when the full
+ header has been received we append CRLF\0 */
+ char *ptr;
+ if(conn->trlMax) {
+ conn->trlMax *= 2;
+ ptr = realloc(conn->trailer, conn->trlMax + 3);
+ }
+ else {
+ conn->trlMax=128;
+ ptr = malloc(conn->trlMax + 3);
+ }
+ if(!ptr)
+ return CHUNKE_OUT_OF_MEMORY;
+ conn->trailer = ptr;
+ }
+ conn->trailer[conn->trlPos++]=*datap;
+ }
+ datap++;
+ length--;
+ break;
+
+ case CHUNK_TRAILER_CR:
+ if(*datap == 0x0a) {
+ ch->state = CHUNK_TRAILER_POSTCR;
+ datap++;
+ length--;
+ }
+ else
+ return CHUNKE_BAD_CHUNK;
+ break;
+
+ case CHUNK_TRAILER_POSTCR:
+ /* We enter this state when a CR should arrive so we expect to
+ have to first pass a CR before we wait for LF */
+ if((*datap != 0x0d) && (*datap != 0x0a)) {
+ /* not a CR then it must be another header in the trailer */
+ ch->state = CHUNK_TRAILER;
+ break;
+ }
+ if(*datap == 0x0d) {
+ /* skip if CR */
+ datap++;
+ length--;
+ }
+ /* now wait for the final LF */
+ ch->state = CHUNK_STOP;
+ break;
+
+ case CHUNK_STOP:
+ if(*datap == 0x0a) {
+ length--;
+
+ /* Record the length of any data left in the end of the buffer
+ even if there's no more chunks to read */
+ ch->dataleft = curlx_sotouz(length);
+
+ return CHUNKE_STOP; /* return stop */
+ }
+ else
+ return CHUNKE_BAD_CHUNK;
+ }
+ }
+ return CHUNKE_OK;
+}
+
+const char *Curl_chunked_strerror(CHUNKcode code)
+{
+ switch (code) {
+ default:
+ return "OK";
+ case CHUNKE_TOO_LONG_HEX:
+ return "Too long hexadecimal number";
+ case CHUNKE_ILLEGAL_HEX:
+ return "Illegal or missing hexadecimal sequence";
+ case CHUNKE_BAD_CHUNK:
+ return "Malformed encoding found";
+ case CHUNKE_WRITE_ERROR:
+ return "Write error";
+ case CHUNKE_BAD_ENCODING:
+ return "Bad content-encoding found";
+ case CHUNKE_OUT_OF_MEMORY:
+ return "Out of memory";
+ }
+}
+
+#endif /* CURL_DISABLE_HTTP */
diff --git a/external/libcurl_android/jni/libcurl/lib/http_chunks.h b/external/libcurl_android/jni/libcurl/lib/http_chunks.h
new file mode 100755
index 00000000..0489eb85
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_chunks.h
@@ -0,0 +1,91 @@
+#ifndef HEADER_CURL_HTTP_CHUNKS_H
+#define HEADER_CURL_HTTP_CHUNKS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ * The longest possible hexadecimal number we support in a chunked transfer.
+ * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul()
+ * to convert it, we "only" support 2^32 bytes chunk data.
+ */
+#define MAXNUM_SIZE 16
+
+typedef enum {
+ /* await and buffer all hexadecimal digits until we get one that isn't a
+ hexadecimal digit. When done, we go CHUNK_LF */
+ CHUNK_HEX,
+
+ /* wait for LF, ignore all else */
+ CHUNK_LF,
+
+ /* We eat the amount of data specified. When done, we move on to the
+ POST_CR state. */
+ CHUNK_DATA,
+
+ /* POSTLF should get a CR and then a LF and nothing else, then move back to
+ HEX as the CRLF combination marks the end of a chunk. A missing CR is no
+ big deal. */
+ CHUNK_POSTLF,
+
+ /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft'
+ field in the struct that will tell how many bytes that were not passed to
+ the client in the end of the last buffer! */
+ CHUNK_STOP,
+
+ /* At this point optional trailer headers can be found, unless the next line
+ is CRLF */
+ CHUNK_TRAILER,
+
+ /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR.
+ Next char must be a LF */
+ CHUNK_TRAILER_CR,
+
+ /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be
+ signalled If this is an empty trailer CHUNKE_STOP will be signalled.
+ Otherwise the trailer will be broadcasted via Curl_client_write() and the
+ next state will be CHUNK_TRAILER */
+ CHUNK_TRAILER_POSTCR
+} ChunkyState;
+
+typedef enum {
+ CHUNKE_STOP = -1,
+ CHUNKE_OK = 0,
+ CHUNKE_TOO_LONG_HEX = 1,
+ CHUNKE_ILLEGAL_HEX,
+ CHUNKE_BAD_CHUNK,
+ CHUNKE_WRITE_ERROR,
+ CHUNKE_BAD_ENCODING,
+ CHUNKE_OUT_OF_MEMORY,
+ CHUNKE_LAST
+} CHUNKcode;
+
+const char *Curl_chunked_strerror(CHUNKcode code);
+
+struct Curl_chunker {
+ char hexbuffer[ MAXNUM_SIZE + 1];
+ int hexindex;
+ ChunkyState state;
+ curl_off_t datasize;
+ size_t dataleft; /* untouched data amount at the end of the last buffer */
+};
+
+#endif /* HEADER_CURL_HTTP_CHUNKS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/http_digest.c b/external/libcurl_android/jni/libcurl/lib/http_digest.c
new file mode 100755
index 00000000..55f5108c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_digest.c
@@ -0,0 +1,598 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+
+#include "urldata.h"
+#include "rawstr.h"
+#include "curl_base64.h"
+#include "curl_md5.h"
+#include "http_digest.h"
+#include "strtok.h"
+#include "curl_memory.h"
+#include "vtls/vtls.h" /* for Curl_rand() */
+#include "non-ascii.h" /* included for Curl_convert_... prototypes */
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#define MAX_VALUE_LENGTH 256
+#define MAX_CONTENT_LENGTH 1024
+
+static void digest_cleanup_one(struct digestdata *dig);
+
+/*
+ * Return 0 on success and then the buffers are filled in fine.
+ *
+ * Non-zero means failure to parse.
+ */
+static int get_pair(const char *str, char *value, char *content,
+ const char **endptr)
+{
+ int c;
+ bool starts_with_quote = FALSE;
+ bool escape = FALSE;
+
+ for(c=MAX_VALUE_LENGTH-1; (*str && (*str != '=') && c--); )
+ *value++ = *str++;
+ *value=0;
+
+ if('=' != *str++)
+ /* eek, no match */
+ return 1;
+
+ if('\"' == *str) {
+ /* this starts with a quote so it must end with one as well! */
+ str++;
+ starts_with_quote = TRUE;
+ }
+
+ for(c=MAX_CONTENT_LENGTH-1; *str && c--; str++) {
+ switch(*str) {
+ case '\\':
+ if(!escape) {
+ /* possibly the start of an escaped quote */
+ escape = TRUE;
+ *content++ = '\\'; /* even though this is an escape character, we still
+ store it as-is in the target buffer */
+ continue;
+ }
+ break;
+ case ',':
+ if(!starts_with_quote) {
+ /* this signals the end of the content if we didn't get a starting
+ quote and then we do "sloppy" parsing */
+ c=0; /* the end */
+ continue;
+ }
+ break;
+ case '\r':
+ case '\n':
+ /* end of string */
+ c=0;
+ continue;
+ case '\"':
+ if(!escape && starts_with_quote) {
+ /* end of string */
+ c=0;
+ continue;
+ }
+ break;
+ }
+ escape = FALSE;
+ *content++ = *str;
+ }
+ *content=0;
+
+ *endptr = str;
+
+ return 0; /* all is fine! */
+}
+
+/* Test example headers:
+
+WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
+Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"
+
+*/
+
+CURLdigest Curl_input_digest(struct connectdata *conn,
+ bool proxy,
+ const char *header) /* rest of the *-authenticate:
+ header */
+{
+ char *token = NULL;
+ char *tmp = NULL;
+ bool foundAuth = FALSE;
+ bool foundAuthInt = FALSE;
+ struct SessionHandle *data=conn->data;
+ bool before = FALSE; /* got a nonce before */
+ struct digestdata *d;
+
+ if(proxy) {
+ d = &data->state.proxydigest;
+ }
+ else {
+ d = &data->state.digest;
+ }
+
+ if(checkprefix("Digest", header)) {
+ header += strlen("Digest");
+
+ /* If we already have received a nonce, keep that in mind */
+ if(d->nonce)
+ before = TRUE;
+
+ /* clear off any former leftovers and init to defaults */
+ digest_cleanup_one(d);
+
+ for(;;) {
+ char value[MAX_VALUE_LENGTH];
+ char content[MAX_CONTENT_LENGTH];
+
+ while(*header && ISSPACE(*header))
+ header++;
+
+ /* extract a value=content pair */
+ if(!get_pair(header, value, content, &header)) {
+ if(Curl_raw_equal(value, "nonce")) {
+ d->nonce = strdup(content);
+ if(!d->nonce)
+ return CURLDIGEST_NOMEM;
+ }
+ else if(Curl_raw_equal(value, "stale")) {
+ if(Curl_raw_equal(content, "true")) {
+ d->stale = TRUE;
+ d->nc = 1; /* we make a new nonce now */
+ }
+ }
+ else if(Curl_raw_equal(value, "realm")) {
+ d->realm = strdup(content);
+ if(!d->realm)
+ return CURLDIGEST_NOMEM;
+ }
+ else if(Curl_raw_equal(value, "opaque")) {
+ d->opaque = strdup(content);
+ if(!d->opaque)
+ return CURLDIGEST_NOMEM;
+ }
+ else if(Curl_raw_equal(value, "qop")) {
+ char *tok_buf;
+ /* tokenize the list and choose auth if possible, use a temporary
+ clone of the buffer since strtok_r() ruins it */
+ tmp = strdup(content);
+ if(!tmp)
+ return CURLDIGEST_NOMEM;
+ token = strtok_r(tmp, ",", &tok_buf);
+ while(token != NULL) {
+ if(Curl_raw_equal(token, "auth")) {
+ foundAuth = TRUE;
+ }
+ else if(Curl_raw_equal(token, "auth-int")) {
+ foundAuthInt = TRUE;
+ }
+ token = strtok_r(NULL, ",", &tok_buf);
+ }
+ free(tmp);
+ /*select only auth o auth-int. Otherwise, ignore*/
+ if(foundAuth) {
+ d->qop = strdup("auth");
+ if(!d->qop)
+ return CURLDIGEST_NOMEM;
+ }
+ else if(foundAuthInt) {
+ d->qop = strdup("auth-int");
+ if(!d->qop)
+ return CURLDIGEST_NOMEM;
+ }
+ }
+ else if(Curl_raw_equal(value, "algorithm")) {
+ d->algorithm = strdup(content);
+ if(!d->algorithm)
+ return CURLDIGEST_NOMEM;
+ if(Curl_raw_equal(content, "MD5-sess"))
+ d->algo = CURLDIGESTALGO_MD5SESS;
+ else if(Curl_raw_equal(content, "MD5"))
+ d->algo = CURLDIGESTALGO_MD5;
+ else
+ return CURLDIGEST_BADALGO;
+ }
+ else {
+ /* unknown specifier, ignore it! */
+ }
+ }
+ else
+ break; /* we're done here */
+
+ /* pass all additional spaces here */
+ while(*header && ISSPACE(*header))
+ header++;
+ if(',' == *header)
+ /* allow the list to be comma-separated */
+ header++;
+ }
+ /* We had a nonce since before, and we got another one now without
+ 'stale=true'. This means we provided bad credentials in the previous
+ request */
+ if(before && !d->stale)
+ return CURLDIGEST_BAD;
+
+ /* We got this header without a nonce, that's a bad Digest line! */
+ if(!d->nonce)
+ return CURLDIGEST_BAD;
+ }
+ else
+ /* else not a digest, get out */
+ return CURLDIGEST_NONE;
+
+ return CURLDIGEST_FINE;
+}
+
+/* convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
+static void md5_to_ascii(unsigned char *source, /* 16 bytes */
+ unsigned char *dest) /* 33 bytes */
+{
+ int i;
+ for(i=0; i<16; i++)
+ snprintf((char *)&dest[i*2], 3, "%02x", source[i]);
+}
+
+/* Perform quoted-string escaping as described in RFC2616 and its errata */
+static char *string_quoted(const char *source)
+{
+ char *dest, *d;
+ const char *s = source;
+ size_t n = 1; /* null terminator */
+
+ /* Calculate size needed */
+ while(*s) {
+ ++n;
+ if(*s == '"' || *s == '\\') {
+ ++n;
+ }
+ ++s;
+ }
+
+ dest = malloc(n);
+ if(dest) {
+ s = source;
+ d = dest;
+ while(*s) {
+ if(*s == '"' || *s == '\\') {
+ *d++ = '\\';
+ }
+ *d++ = *s++;
+ }
+ *d = 0;
+ }
+
+ return dest;
+}
+
+CURLcode Curl_output_digest(struct connectdata *conn,
+ bool proxy,
+ const unsigned char *request,
+ const unsigned char *uripath)
+{
+ /* We have a Digest setup for this, use it! Now, to get all the details for
+ this sorted out, I must urge you dear friend to read up on the RFC2617
+ section 3.2.2, */
+ size_t urilen;
+ unsigned char md5buf[16]; /* 16 bytes/128 bits */
+ unsigned char request_digest[33];
+ unsigned char *md5this;
+ unsigned char ha1[33];/* 32 digits and 1 zero byte */
+ unsigned char ha2[33];/* 32 digits and 1 zero byte */
+ char cnoncebuf[33];
+ char *cnonce = NULL;
+ size_t cnonce_sz = 0;
+ char *tmp = NULL;
+ char **allocuserpwd;
+ size_t userlen;
+ const char *userp;
+ char *userp_quoted;
+ const char *passwdp;
+ struct auth *authp;
+
+ struct SessionHandle *data = conn->data;
+ struct digestdata *d;
+ CURLcode rc;
+/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines.
+ It converts digest text to ASCII so the MD5 will be correct for
+ what ultimately goes over the network.
+*/
+#define CURL_OUTPUT_DIGEST_CONV(a, b) \
+ rc = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
+ if(rc != CURLE_OK) { \
+ free(b); \
+ return rc; \
+ }
+
+ if(proxy) {
+ d = &data->state.proxydigest;
+ allocuserpwd = &conn->allocptr.proxyuserpwd;
+ userp = conn->proxyuser;
+ passwdp = conn->proxypasswd;
+ authp = &data->state.authproxy;
+ }
+ else {
+ d = &data->state.digest;
+ allocuserpwd = &conn->allocptr.userpwd;
+ userp = conn->user;
+ passwdp = conn->passwd;
+ authp = &data->state.authhost;
+ }
+
+ Curl_safefree(*allocuserpwd);
+
+ /* not set means empty */
+ if(!userp)
+ userp="";
+
+ if(!passwdp)
+ passwdp="";
+
+ if(!d->nonce) {
+ authp->done = FALSE;
+ return CURLE_OK;
+ }
+ authp->done = TRUE;
+
+ if(!d->nc)
+ d->nc = 1;
+
+ if(!d->cnonce) {
+ snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
+ Curl_rand(data), Curl_rand(data),
+ Curl_rand(data), Curl_rand(data));
+ rc = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
+ &cnonce, &cnonce_sz);
+ if(rc)
+ return rc;
+ d->cnonce = cnonce;
+ }
+
+ /*
+ if the algorithm is "MD5" or unspecified (which then defaults to MD5):
+
+ A1 = unq(username-value) ":" unq(realm-value) ":" passwd
+
+ if the algorithm is "MD5-sess" then:
+
+ A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd )
+ ":" unq(nonce-value) ":" unq(cnonce-value)
+ */
+
+ md5this = (unsigned char *)
+ aprintf("%s:%s:%s", userp, d->realm, passwdp);
+ if(!md5this)
+ return CURLE_OUT_OF_MEMORY;
+
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
+ Curl_md5it(md5buf, md5this);
+ Curl_safefree(md5this);
+ md5_to_ascii(md5buf, ha1);
+
+ if(d->algo == CURLDIGESTALGO_MD5SESS) {
+ /* nonce and cnonce are OUTSIDE the hash */
+ tmp = aprintf("%s:%s:%s", ha1, d->nonce, d->cnonce);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+ CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */
+ Curl_md5it(md5buf, (unsigned char *)tmp);
+ Curl_safefree(tmp);
+ md5_to_ascii(md5buf, ha1);
+ }
+
+ /*
+ If the "qop" directive's value is "auth" or is unspecified, then A2 is:
+
+ A2 = Method ":" digest-uri-value
+
+ If the "qop" value is "auth-int", then A2 is:
+
+ A2 = Method ":" digest-uri-value ":" H(entity-body)
+
+ (The "Method" value is the HTTP request method as specified in section
+ 5.1.1 of RFC 2616)
+ */
+
+ /* So IE browsers < v7 cut off the URI part at the query part when they
+ evaluate the MD5 and some (IIS?) servers work with them so we may need to
+ do the Digest IE-style. Note that the different ways cause different MD5
+ sums to get sent.
+
+ Apache servers can be set to do the Digest IE-style automatically using
+ the BrowserMatch feature:
+ http://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html#msie
+
+ Further details on Digest implementation differences:
+ http://www.fngtps.com/2006/09/http-authentication
+ */
+
+ if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL))
+ urilen = tmp - (char *)uripath;
+ else
+ urilen = strlen((char *)uripath);
+
+ md5this = (unsigned char *)aprintf("%s:%.*s", request, urilen, uripath);
+
+ if(d->qop && Curl_raw_equal(d->qop, "auth-int")) {
+ /* We don't support auth-int for PUT or POST at the moment.
+ TODO: replace md5 of empty string with entity-body for PUT/POST */
+ unsigned char *md5this2 = (unsigned char *)
+ aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e");
+ Curl_safefree(md5this);
+ md5this = md5this2;
+ }
+
+ if(!md5this)
+ return CURLE_OUT_OF_MEMORY;
+
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
+ Curl_md5it(md5buf, md5this);
+ Curl_safefree(md5this);
+ md5_to_ascii(md5buf, ha2);
+
+ if(d->qop) {
+ md5this = (unsigned char *)aprintf("%s:%s:%08x:%s:%s:%s",
+ ha1,
+ d->nonce,
+ d->nc,
+ d->cnonce,
+ d->qop,
+ ha2);
+ }
+ else {
+ md5this = (unsigned char *)aprintf("%s:%s:%s",
+ ha1,
+ d->nonce,
+ ha2);
+ }
+ if(!md5this)
+ return CURLE_OUT_OF_MEMORY;
+
+ CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
+ Curl_md5it(md5buf, md5this);
+ Curl_safefree(md5this);
+ md5_to_ascii(md5buf, request_digest);
+
+ /* for test case 64 (snooped from a Mozilla 1.3a request)
+
+ Authorization: Digest username="testuser", realm="testrealm", \
+ nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
+
+ Digest parameters are all quoted strings. Username which is provided by
+ the user will need double quotes and backslashes within it escaped. For
+ the other fields, this shouldn't be an issue. realm, nonce, and opaque
+ are copied as is from the server, escapes and all. cnonce is generated
+ with web-safe characters. uri is already percent encoded. nc is 8 hex
+ characters. algorithm and qop with standard values only contain web-safe
+ chracters.
+ */
+ userp_quoted = string_quoted(userp);
+ if(!userp_quoted)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(d->qop) {
+ *allocuserpwd =
+ aprintf( "%sAuthorization: Digest "
+ "username=\"%s\", "
+ "realm=\"%s\", "
+ "nonce=\"%s\", "
+ "uri=\"%.*s\", "
+ "cnonce=\"%s\", "
+ "nc=%08x, "
+ "qop=%s, "
+ "response=\"%s\"",
+ proxy?"Proxy-":"",
+ userp_quoted,
+ d->realm,
+ d->nonce,
+ urilen, uripath, /* this is the PATH part of the URL */
+ d->cnonce,
+ d->nc,
+ d->qop,
+ request_digest);
+
+ if(Curl_raw_equal(d->qop, "auth"))
+ d->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0 padded
+ which tells to the server how many times you are using the
+ same nonce in the qop=auth mode. */
+ }
+ else {
+ *allocuserpwd =
+ aprintf( "%sAuthorization: Digest "
+ "username=\"%s\", "
+ "realm=\"%s\", "
+ "nonce=\"%s\", "
+ "uri=\"%.*s\", "
+ "response=\"%s\"",
+ proxy?"Proxy-":"",
+ userp_quoted,
+ d->realm,
+ d->nonce,
+ urilen, uripath, /* this is the PATH part of the URL */
+ request_digest);
+ }
+ Curl_safefree(userp_quoted);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Add optional fields */
+ if(d->opaque) {
+ /* append opaque */
+ tmp = aprintf("%s, opaque=\"%s\"", *allocuserpwd, d->opaque);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+ free(*allocuserpwd);
+ *allocuserpwd = tmp;
+ }
+
+ if(d->algorithm) {
+ /* append algorithm */
+ tmp = aprintf("%s, algorithm=\"%s\"", *allocuserpwd, d->algorithm);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+ free(*allocuserpwd);
+ *allocuserpwd = tmp;
+ }
+
+ /* append CRLF + zero (3 bytes) to the userpwd header */
+ userlen = strlen(*allocuserpwd);
+ tmp = realloc(*allocuserpwd, userlen + 3);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+ strcpy(&tmp[userlen], "\r\n"); /* append the data */
+ *allocuserpwd = tmp;
+
+ return CURLE_OK;
+}
+
+static void digest_cleanup_one(struct digestdata *d)
+{
+ Curl_safefree(d->nonce);
+ Curl_safefree(d->cnonce);
+ Curl_safefree(d->realm);
+ Curl_safefree(d->opaque);
+ Curl_safefree(d->qop);
+ Curl_safefree(d->algorithm);
+
+ d->nc = 0;
+ d->algo = CURLDIGESTALGO_MD5; /* default algorithm */
+ d->stale = FALSE; /* default means normal, not stale */
+}
+
+
+void Curl_digest_cleanup(struct SessionHandle *data)
+{
+ digest_cleanup_one(&data->state.digest);
+ digest_cleanup_one(&data->state.proxydigest);
+}
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/http_digest.h b/external/libcurl_android/jni/libcurl/lib/http_digest.h
new file mode 100755
index 00000000..c6a4e916
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_digest.h
@@ -0,0 +1,57 @@
+#ifndef HEADER_CURL_HTTP_DIGEST_H
+#define HEADER_CURL_HTTP_DIGEST_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+typedef enum {
+ CURLDIGEST_NONE, /* not a digest */
+ CURLDIGEST_BAD, /* a digest, but one we don't like */
+ CURLDIGEST_BADALGO, /* unsupported algorithm requested */
+ CURLDIGEST_NOMEM,
+ CURLDIGEST_FINE, /* a digest we act on */
+
+ CURLDIGEST_LAST /* last entry in this enum, don't use */
+} CURLdigest;
+
+enum {
+ CURLDIGESTALGO_MD5,
+ CURLDIGESTALGO_MD5SESS
+};
+
+/* this is for digest header input */
+CURLdigest Curl_input_digest(struct connectdata *conn,
+ bool proxy, const char *header);
+
+/* this is for creating digest header output */
+CURLcode Curl_output_digest(struct connectdata *conn,
+ bool proxy,
+ const unsigned char *request,
+ const unsigned char *uripath);
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+void Curl_digest_cleanup(struct SessionHandle *data);
+#else
+#define Curl_digest_cleanup(x) Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_HTTP_DIGEST_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/http_negotiate.c b/external/libcurl_android/jni/libcurl/lib/http_negotiate.c
new file mode 100755
index 00000000..c8bfa29b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_negotiate.c
@@ -0,0 +1,243 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_GSSAPI
+#ifdef HAVE_OLD_GSSMIT
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#define NCOMPAT 1
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+
+#include "urldata.h"
+#include "sendf.h"
+#include "curl_gssapi.h"
+#include "rawstr.h"
+#include "curl_base64.h"
+#include "http_negotiate.h"
+#include "curl_memory.h"
+#include "url.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static int
+get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server)
+{
+ OM_uint32 major_status, minor_status;
+ gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+ char name[2048];
+ const char* service = "HTTP";
+
+ token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name :
+ conn->host.name) + 1;
+ if(token.length + 1 > sizeof(name))
+ return EMSGSIZE;
+
+ snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name :
+ conn->host.name);
+
+ token.value = (void *) name;
+ major_status = gss_import_name(&minor_status,
+ &token,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ server);
+
+ return GSS_ERROR(major_status) ? -1 : 0;
+}
+
+static void
+log_gss_error(struct connectdata *conn, OM_uint32 error_status,
+ const char *prefix)
+{
+ OM_uint32 maj_stat, min_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+ char buf[1024];
+ size_t len;
+
+ snprintf(buf, sizeof(buf), "%s", prefix);
+ len = strlen(buf);
+ do {
+ maj_stat = gss_display_status(&min_stat,
+ error_status,
+ GSS_C_MECH_CODE,
+ GSS_C_NO_OID,
+ &msg_ctx,
+ &status_string);
+ if(sizeof(buf) > len + status_string.length + 1) {
+ snprintf(buf + len, sizeof(buf) - len,
+ ": %s", (char*) status_string.value);
+ len += status_string.length;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
+
+ infof(conn->data, "%s\n", buf);
+}
+
+/* returning zero (0) means success, everything else is treated as "failure"
+ with no care exactly what the failure was */
+int Curl_input_negotiate(struct connectdata *conn, bool proxy,
+ const char *header)
+{
+ struct SessionHandle *data = conn->data;
+ struct negotiatedata *neg_ctx = proxy?&data->state.proxyneg:
+ &data->state.negotiate;
+ OM_uint32 major_status, minor_status, discard_st;
+ gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
+ int ret;
+ size_t len;
+ size_t rawlen = 0;
+ CURLcode error;
+
+ if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
+ /* We finished successfully our part of authentication, but server
+ * rejected it (since we're again here). Exit with an error since we
+ * can't invent anything better */
+ Curl_cleanup_negotiate(data);
+ return -1;
+ }
+
+ if(neg_ctx->server_name == NULL &&
+ (ret = get_gss_name(conn, proxy, &neg_ctx->server_name)))
+ return ret;
+
+ header += strlen("Negotiate");
+ while(*header && ISSPACE(*header))
+ header++;
+
+ len = strlen(header);
+ if(len > 0) {
+ error = Curl_base64_decode(header,
+ (unsigned char **)&input_token.value, &rawlen);
+ if(error || rawlen == 0)
+ return -1;
+ input_token.length = rawlen;
+
+ DEBUGASSERT(input_token.value != NULL);
+ }
+
+ major_status = Curl_gss_init_sec_context(data,
+ &minor_status,
+ &neg_ctx->context,
+ neg_ctx->server_name,
+ &Curl_spnego_mech_oid,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &input_token,
+ &output_token,
+ NULL);
+ Curl_safefree(input_token.value);
+
+ neg_ctx->status = major_status;
+ if(GSS_ERROR(major_status)) {
+ if(output_token.value)
+ gss_release_buffer(&discard_st, &output_token);
+ log_gss_error(conn, minor_status, "gss_init_sec_context() failed: ");
+ return -1;
+ }
+
+ if(!output_token.value || !output_token.length) {
+ if(output_token.value)
+ gss_release_buffer(&discard_st, &output_token);
+ return -1;
+ }
+
+ neg_ctx->output_token = output_token;
+ return 0;
+}
+
+
+CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
+{
+ struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
+ &conn->data->state.negotiate;
+ char *encoded = NULL;
+ size_t len = 0;
+ char *userp;
+ CURLcode error;
+ OM_uint32 discard_st;
+
+ error = Curl_base64_encode(conn->data,
+ neg_ctx->output_token.value,
+ neg_ctx->output_token.length,
+ &encoded, &len);
+ if(error) {
+ gss_release_buffer(&discard_st, &neg_ctx->output_token);
+ neg_ctx->output_token.value = NULL;
+ neg_ctx->output_token.length = 0;
+ return error;
+ }
+
+ if(!encoded || !len) {
+ gss_release_buffer(&discard_st, &neg_ctx->output_token);
+ neg_ctx->output_token.value = NULL;
+ neg_ctx->output_token.length = 0;
+ return CURLE_REMOTE_ACCESS_DENIED;
+ }
+
+ userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
+ encoded);
+ if(proxy) {
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ conn->allocptr.proxyuserpwd = userp;
+ }
+ else {
+ Curl_safefree(conn->allocptr.userpwd);
+ conn->allocptr.userpwd = userp;
+ }
+
+ Curl_safefree(encoded);
+
+ return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
+}
+
+static void cleanup(struct negotiatedata *neg_ctx)
+{
+ OM_uint32 minor_status;
+ if(neg_ctx->context != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER);
+
+ if(neg_ctx->output_token.value)
+ gss_release_buffer(&minor_status, &neg_ctx->output_token);
+
+ if(neg_ctx->server_name != GSS_C_NO_NAME)
+ gss_release_name(&minor_status, &neg_ctx->server_name);
+
+ memset(neg_ctx, 0, sizeof(*neg_ctx));
+}
+
+void Curl_cleanup_negotiate(struct SessionHandle *data)
+{
+ cleanup(&data->state.negotiate);
+ cleanup(&data->state.proxyneg);
+}
+
+
+#endif
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/http_negotiate.h b/external/libcurl_android/jni/libcurl/lib/http_negotiate.h
new file mode 100755
index 00000000..f7efe8cd
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_negotiate.h
@@ -0,0 +1,42 @@
+#ifndef HEADER_CURL_HTTP_NEGOTIATE_H
+#define HEADER_CURL_HTTP_NEGOTIATE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifdef USE_SPNEGO
+
+/* this is for Negotiate header input */
+int Curl_input_negotiate(struct connectdata *conn, bool proxy,
+ const char *header);
+
+/* this is for creating Negotiate header output */
+CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
+
+void Curl_cleanup_negotiate(struct SessionHandle *data);
+
+#ifdef USE_WINDOWS_SSPI
+#define GSS_ERROR(status) (status & 0x80000000)
+#endif
+
+#endif /* USE_SPNEGO */
+
+#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/http_negotiate_sspi.c b/external/libcurl_android/jni/libcurl/lib/http_negotiate_sspi.c
new file mode 100755
index 00000000..61581f1f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_negotiate_sspi.c
@@ -0,0 +1,290 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_WINDOWS_SSPI
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
+
+#include "urldata.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "warnless.h"
+#include "curl_base64.h"
+#include "curl_sasl.h"
+#include "http_negotiate.h"
+#include "curl_memory.h"
+#include "curl_multibyte.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* returning zero (0) means success, everything else is treated as "failure"
+ with no care exactly what the failure was */
+int Curl_input_negotiate(struct connectdata *conn, bool proxy,
+ const char *header)
+{
+ BYTE *input_token = NULL;
+ SecBufferDesc out_buff_desc;
+ SecBuffer out_sec_buff;
+ SecBufferDesc in_buff_desc;
+ SecBuffer in_sec_buff;
+ unsigned long context_attributes;
+ TimeStamp lifetime;
+ int ret;
+ size_t len = 0, input_token_len = 0;
+ CURLcode error;
+
+ /* Point to the username and password */
+ const char *userp;
+ const char *passwdp;
+
+ /* Point to the correct struct with this */
+ struct negotiatedata *neg_ctx;
+
+ if(proxy) {
+ userp = conn->proxyuser;
+ passwdp = conn->proxypasswd;
+ neg_ctx = &conn->data->state.proxyneg;
+ }
+ else {
+ userp = conn->user;
+ passwdp = conn->passwd;
+ neg_ctx = &conn->data->state.negotiate;
+ }
+
+ /* Not set means empty */
+ if(!userp)
+ userp = "";
+
+ if(!passwdp)
+ passwdp = "";
+
+ if(neg_ctx->context && neg_ctx->status == SEC_E_OK) {
+ /* We finished successfully our part of authentication, but server
+ * rejected it (since we're again here). Exit with an error since we
+ * can't invent anything better */
+ Curl_cleanup_negotiate(conn->data);
+ return -1;
+ }
+
+ if(!neg_ctx->server_name) {
+ /* Check proxy auth requested but no given proxy name */
+ if(proxy && !conn->proxy.name)
+ return -1;
+
+ /* Generate our SPN */
+ neg_ctx->server_name = Curl_sasl_build_spn("HTTP",
+ proxy ? conn->proxy.name :
+ conn->host.name);
+ if(!neg_ctx->server_name)
+ return -1;
+ }
+
+ if(!neg_ctx->output_token) {
+ PSecPkgInfo SecurityPackage;
+ ret = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT("Negotiate"),
+ &SecurityPackage);
+ if(ret != SEC_E_OK)
+ return -1;
+
+ /* Allocate input and output buffers according to the max token size
+ as indicated by the security package */
+ neg_ctx->max_token_length = SecurityPackage->cbMaxToken;
+ neg_ctx->output_token = malloc(neg_ctx->max_token_length);
+ s_pSecFn->FreeContextBuffer(SecurityPackage);
+ }
+
+ /* Obtain the input token, if any */
+ header += strlen("Negotiate");
+ while(*header && ISSPACE(*header))
+ header++;
+
+ len = strlen(header);
+ if(!len) {
+ /* Is this the first call in a new negotiation? */
+ if(neg_ctx->context) {
+ /* The server rejected our authentication and hasn't suppled any more
+ negotiation mechanisms */
+ return -1;
+ }
+
+ /* We have to acquire credentials and allocate memory for the context */
+ neg_ctx->credentials = malloc(sizeof(CredHandle));
+ neg_ctx->context = malloc(sizeof(CtxtHandle));
+
+ if(!neg_ctx->credentials || !neg_ctx->context)
+ return -1;
+
+ if(userp && *userp) {
+ /* Populate our identity structure */
+ error = Curl_create_sspi_identity(userp, passwdp, &neg_ctx->identity);
+ if(error)
+ return -1;
+
+ /* Allow proper cleanup of the identity structure */
+ neg_ctx->p_identity = &neg_ctx->identity;
+ }
+ else
+ /* Use the current Windows user */
+ neg_ctx->p_identity = NULL;
+
+ /* Acquire our credientials handle */
+ neg_ctx->status =
+ s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT("Negotiate"),
+ SECPKG_CRED_OUTBOUND, NULL,
+ neg_ctx->p_identity, NULL, NULL,
+ neg_ctx->credentials, &lifetime);
+ if(neg_ctx->status != SEC_E_OK)
+ return -1;
+ }
+ else {
+ error = Curl_base64_decode(header,
+ (unsigned char **)&input_token,
+ &input_token_len);
+ if(error || !input_token_len)
+ return -1;
+ }
+
+ /* Setup the "output" security buffer */
+ out_buff_desc.ulVersion = SECBUFFER_VERSION;
+ out_buff_desc.cBuffers = 1;
+ out_buff_desc.pBuffers = &out_sec_buff;
+ out_sec_buff.BufferType = SECBUFFER_TOKEN;
+ out_sec_buff.pvBuffer = neg_ctx->output_token;
+ out_sec_buff.cbBuffer = curlx_uztoul(neg_ctx->max_token_length);
+
+ /* Setup the "input" security buffer if present */
+ if(input_token) {
+ in_buff_desc.ulVersion = SECBUFFER_VERSION;
+ in_buff_desc.cBuffers = 1;
+ in_buff_desc.pBuffers = &in_sec_buff;
+ in_sec_buff.BufferType = SECBUFFER_TOKEN;
+ in_sec_buff.pvBuffer = input_token;
+ in_sec_buff.cbBuffer = curlx_uztoul(input_token_len);
+ }
+
+ /* Generate our message */
+ neg_ctx->status = s_pSecFn->InitializeSecurityContext(
+ neg_ctx->credentials,
+ input_token ? neg_ctx->context : NULL,
+ neg_ctx->server_name,
+ ISC_REQ_CONFIDENTIALITY,
+ 0,
+ SECURITY_NATIVE_DREP,
+ input_token ? &in_buff_desc : NULL,
+ 0,
+ neg_ctx->context,
+ &out_buff_desc,
+ &context_attributes,
+ &lifetime);
+
+ Curl_safefree(input_token);
+
+ if(GSS_ERROR(neg_ctx->status))
+ return -1;
+
+ if(neg_ctx->status == SEC_I_COMPLETE_NEEDED ||
+ neg_ctx->status == SEC_I_COMPLETE_AND_CONTINUE) {
+ neg_ctx->status = s_pSecFn->CompleteAuthToken(neg_ctx->context,
+ &out_buff_desc);
+ if(GSS_ERROR(neg_ctx->status))
+ return -1;
+ }
+
+ neg_ctx->output_token_length = out_sec_buff.cbBuffer;
+
+ return 0;
+}
+
+
+CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
+{
+ struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
+ &conn->data->state.negotiate;
+ char *encoded = NULL;
+ size_t len = 0;
+ char *userp;
+ CURLcode error;
+
+ error = Curl_base64_encode(conn->data,
+ (const char*)neg_ctx->output_token,
+ neg_ctx->output_token_length,
+ &encoded, &len);
+ if(error)
+ return error;
+
+ if(!len)
+ return CURLE_REMOTE_ACCESS_DENIED;
+
+ userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
+ encoded);
+
+ if(proxy) {
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ conn->allocptr.proxyuserpwd = userp;
+ }
+ else {
+ Curl_safefree(conn->allocptr.userpwd);
+ conn->allocptr.userpwd = userp;
+ }
+ free(encoded);
+ return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
+}
+
+static void cleanup(struct negotiatedata *neg_ctx)
+{
+ if(neg_ctx->context) {
+ s_pSecFn->DeleteSecurityContext(neg_ctx->context);
+ free(neg_ctx->context);
+ neg_ctx->context = NULL;
+ }
+
+ if(neg_ctx->credentials) {
+ s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials);
+ free(neg_ctx->credentials);
+ neg_ctx->credentials = NULL;
+ }
+
+ neg_ctx->max_token_length = 0;
+ Curl_safefree(neg_ctx->output_token);
+
+ Curl_safefree(neg_ctx->server_name);
+
+ Curl_sspi_free_identity(neg_ctx->p_identity);
+ neg_ctx->p_identity = NULL;
+}
+
+void Curl_cleanup_negotiate(struct SessionHandle *data)
+{
+ cleanup(&data->state.negotiate);
+ cleanup(&data->state.proxyneg);
+}
+
+#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
+
+#endif /* USE_WINDOWS_SSPI */
diff --git a/external/libcurl_android/jni/libcurl/lib/http_proxy.c b/external/libcurl_android/jni/libcurl/lib/http_proxy.c
new file mode 100755
index 00000000..5343eb71
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_proxy.c
@@ -0,0 +1,598 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "http_proxy.h"
+#include "sendf.h"
+#include "http.h"
+#include "url.h"
+#include "select.h"
+#include "rawstr.h"
+#include "progress.h"
+#include "non-ascii.h"
+#include "connect.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curlx.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+CURLcode Curl_proxy_connect(struct connectdata *conn)
+{
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
+#ifndef CURL_DISABLE_PROXY
+ /* for [protocol] tunneled through HTTP proxy */
+ struct HTTP http_proxy;
+ void *prot_save;
+ CURLcode result;
+
+ /* BLOCKING */
+ /* We want "seamless" operations through HTTP proxy tunnel */
+
+ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
+ * member conn->proto.http; we want [protocol] through HTTP and we have
+ * to change the member temporarily for connecting to the HTTP
+ * proxy. After Curl_proxyCONNECT we have to set back the member to the
+ * original pointer
+ *
+ * This function might be called several times in the multi interface case
+ * if the proxy's CONNTECT response is not instant.
+ */
+ prot_save = conn->data->req.protop;
+ memset(&http_proxy, 0, sizeof(http_proxy));
+ conn->data->req.protop = &http_proxy;
+ connkeep(conn, "HTTP proxy CONNECT");
+ result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
+ conn->host.name, conn->remote_port);
+ conn->data->req.protop = prot_save;
+ if(CURLE_OK != result)
+ return result;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
+ }
+ /* no HTTP tunnel proxy, just return */
+ return CURLE_OK;
+}
+
+/*
+ * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
+ * function will issue the necessary commands to get a seamless tunnel through
+ * this proxy. After that, the socket can be used just as a normal socket.
+ */
+
+CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+ int sockindex,
+ const char *hostname,
+ int remote_port)
+{
+ int subversion=0;
+ struct SessionHandle *data=conn->data;
+ struct SingleRequest *k = &data->req;
+ CURLcode result;
+ curl_socket_t tunnelsocket = conn->sock[sockindex];
+ curl_off_t cl=0;
+ bool closeConnection = FALSE;
+ bool chunked_encoding = FALSE;
+ long check;
+
+#define SELECT_OK 0
+#define SELECT_ERROR 1
+#define SELECT_TIMEOUT 2
+ int error = SELECT_OK;
+
+ if(conn->tunnel_state[sockindex] == TUNNEL_COMPLETE)
+ return CURLE_OK; /* CONNECT is already completed */
+
+ conn->bits.proxy_connect_closed = FALSE;
+
+ do {
+ if(TUNNEL_INIT == conn->tunnel_state[sockindex]) {
+ /* BEGIN CONNECT PHASE */
+ char *host_port;
+ Curl_send_buffer *req_buffer;
+
+ infof(data, "Establish HTTP proxy tunnel to %s:%hu\n",
+ hostname, remote_port);
+
+ if(data->req.newurl) {
+ /* This only happens if we've looped here due to authentication
+ reasons, and we don't really use the newly cloned URL here
+ then. Just free() it. */
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+ }
+
+ /* initialize a dynamic send-buffer */
+ req_buffer = Curl_add_buffer_init();
+
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ host_port = aprintf("%s:%hu", hostname, remote_port);
+ if(!host_port) {
+ free(req_buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE);
+
+ free(host_port);
+
+ if(CURLE_OK == result) {
+ char *host=(char *)"";
+ const char *proxyconn="";
+ const char *useragent="";
+ const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
+ "1.0" : "1.1";
+ char *hostheader= /* host:port with IPv6 support */
+ aprintf("%s%s%s:%hu", conn->bits.ipv6_ip?"[":"",
+ hostname, conn->bits.ipv6_ip?"]":"",
+ remote_port);
+ if(!hostheader) {
+ free(req_buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!Curl_checkProxyheaders(conn, "Host:")) {
+ host = aprintf("Host: %s\r\n", hostheader);
+ if(!host) {
+ free(hostheader);
+ free(req_buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
+ proxyconn = "Proxy-Connection: Keep-Alive\r\n";
+
+ if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
+ data->set.str[STRING_USERAGENT])
+ useragent = conn->allocptr.uagent;
+
+ result =
+ Curl_add_bufferf(req_buffer,
+ "CONNECT %s HTTP/%s\r\n"
+ "%s" /* Host: */
+ "%s" /* Proxy-Authorization */
+ "%s" /* User-Agent */
+ "%s", /* Proxy-Connection */
+ hostheader,
+ http,
+ host,
+ conn->allocptr.proxyuserpwd?
+ conn->allocptr.proxyuserpwd:"",
+ useragent,
+ proxyconn);
+
+ if(host && *host)
+ free(host);
+ free(hostheader);
+
+ if(CURLE_OK == result)
+ result = Curl_add_custom_headers(conn, TRUE, req_buffer);
+
+ if(CURLE_OK == result)
+ /* CRLF terminate the request */
+ result = Curl_add_bufferf(req_buffer, "\r\n");
+
+ if(CURLE_OK == result) {
+ /* Send the connect request to the proxy */
+ /* BLOCKING */
+ result =
+ Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, sockindex);
+ }
+ req_buffer = NULL;
+ if(result)
+ failf(data, "Failed sending CONNECT to proxy");
+ }
+
+ Curl_safefree(req_buffer);
+ if(result)
+ return result;
+
+ conn->tunnel_state[sockindex] = TUNNEL_CONNECT;
+ } /* END CONNECT PHASE */
+
+ check = Curl_timeleft(data, NULL, TRUE);
+ if(check <= 0) {
+ failf(data, "Proxy CONNECT aborted due to timeout");
+ return CURLE_RECV_ERROR;
+ }
+
+ if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
+ /* return so we'll be called again polling-style */
+ return CURLE_OK;
+ else {
+ DEBUGF(infof(data,
+ "Read response immediately from proxy CONNECT\n"));
+ }
+
+ /* at this point, the tunnel_connecting phase is over. */
+
+ { /* READING RESPONSE PHASE */
+ size_t nread; /* total size read */
+ int perline; /* count bytes per line */
+ int keepon=TRUE;
+ ssize_t gotbytes;
+ char *ptr;
+ char *line_start;
+
+ ptr=data->state.buffer;
+ line_start = ptr;
+
+ nread=0;
+ perline=0;
+ keepon=TRUE;
+
+ while((nread<BUFSIZE) && (keepon && !error)) {
+
+ check = Curl_timeleft(data, NULL, TRUE);
+ if(check <= 0) {
+ failf(data, "Proxy CONNECT aborted due to timeout");
+ error = SELECT_TIMEOUT; /* already too little time */
+ break;
+ }
+
+ /* loop every second at least, less if the timeout is near */
+ switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD,
+ check<1000L?check:1000)) {
+ case -1: /* select() error, stop reading */
+ error = SELECT_ERROR;
+ failf(data, "Proxy CONNECT aborted due to select/poll error");
+ break;
+ case 0: /* timeout */
+ break;
+ default:
+ DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
+ result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
+ &gotbytes);
+ if(result==CURLE_AGAIN)
+ continue; /* go loop yourself */
+ else if(result)
+ keepon = FALSE;
+ else if(gotbytes <= 0) {
+ keepon = FALSE;
+ if(data->set.proxyauth && data->state.authproxy.avail) {
+ /* proxy auth was requested and there was proxy auth available,
+ then deem this as "mere" proxy disconnect */
+ conn->bits.proxy_connect_closed = TRUE;
+ infof(data, "Proxy CONNECT connection closed");
+ }
+ else {
+ error = SELECT_ERROR;
+ failf(data, "Proxy CONNECT aborted");
+ }
+ }
+ else {
+ /*
+ * We got a whole chunk of data, which can be anything from one
+ * byte to a set of lines and possibly just a piece of the last
+ * line.
+ */
+ int i;
+
+ nread += gotbytes;
+
+ if(keepon > TRUE) {
+ /* This means we are currently ignoring a response-body */
+
+ nread = 0; /* make next read start over in the read buffer */
+ ptr=data->state.buffer;
+ if(cl) {
+ /* A Content-Length based body: simply count down the counter
+ and make sure to break out of the loop when we're done! */
+ cl -= gotbytes;
+ if(cl<=0) {
+ keepon = FALSE;
+ break;
+ }
+ }
+ else {
+ /* chunked-encoded body, so we need to do the chunked dance
+ properly to know when the end of the body is reached */
+ CHUNKcode r;
+ ssize_t tookcareof=0;
+
+ /* now parse the chunked piece of data so that we can
+ properly tell when the stream ends */
+ r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE\n");
+ keepon = FALSE;
+ /* we did the full CONNECT treatment, go COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+ }
+ else
+ infof(data, "Read %zd bytes of chunk, continue\n",
+ tookcareof);
+ }
+ }
+ else
+ for(i = 0; i < gotbytes; ptr++, i++) {
+ perline++; /* amount of bytes in this line so far */
+ if(*ptr == 0x0a) {
+ char letter;
+ int writetype;
+
+ /* convert from the network encoding */
+ result = Curl_convert_from_network(data, line_start,
+ perline);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+ /* output debug if that is requested */
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ line_start, (size_t)perline, conn);
+
+ /* send the header to the callback */
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+
+ result = Curl_client_write(conn, writetype, line_start,
+ perline);
+
+ data->info.header_size += (long)perline;
+ data->req.headerbytecount += (long)perline;
+
+ if(result)
+ return result;
+
+ /* Newlines are CRLF, so the CR is ignored as the line isn't
+ really terminated until the LF comes. Treat a following CR
+ as end-of-headers as well.*/
+
+ if(('\r' == line_start[0]) ||
+ ('\n' == line_start[0])) {
+ /* end of response-headers from the proxy */
+ nread = 0; /* make next read start over in the read
+ buffer */
+ ptr=data->state.buffer;
+ if((407 == k->httpcode) && !data->state.authproblem) {
+ /* If we get a 407 response code with content length
+ when we have no auth problem, we must ignore the
+ whole response-body */
+ keepon = 2;
+
+ if(cl) {
+ infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
+ " bytes of response-body\n", cl);
+
+ /* remove the remaining chunk of what we already
+ read */
+ cl -= (gotbytes - i);
+
+ if(cl<=0)
+ /* if the whole thing was already read, we are done!
+ */
+ keepon=FALSE;
+ }
+ else if(chunked_encoding) {
+ CHUNKcode r;
+ /* We set ignorebody true here since the chunked
+ decoder function will acknowledge that. Pay
+ attention so that this is cleared again when this
+ function returns! */
+ k->ignorebody = TRUE;
+ infof(data, "%zd bytes of chunk left\n", gotbytes-i);
+
+ if(line_start[1] == '\n') {
+ /* this can only be a LF if the letter at index 0
+ was a CR */
+ line_start++;
+ i++;
+ }
+
+ /* now parse the chunked piece of data so that we can
+ properly tell when the stream ends */
+ r = Curl_httpchunk_read(conn, line_start+1,
+ gotbytes -i, &gotbytes);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE\n");
+ keepon = FALSE;
+ /* we did the full CONNECT treatment, go to
+ COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+ }
+ else
+ infof(data, "Read %zd bytes of chunk, continue\n",
+ gotbytes);
+ }
+ else {
+ /* without content-length or chunked encoding, we
+ can't keep the connection alive since the close is
+ the end signal so we bail out at once instead */
+ keepon=FALSE;
+ }
+ }
+ else {
+ keepon = FALSE;
+ if(200 == data->info.httpproxycode) {
+ if(gotbytes - (i+1))
+ failf(data, "Proxy CONNECT followed by %zd bytes "
+ "of opaque data. Data ignored (known bug #39)",
+ gotbytes - (i+1));
+ }
+ }
+ /* we did the full CONNECT treatment, go to COMPLETE */
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+ break; /* breaks out of for-loop, not switch() */
+ }
+
+ /* keep a backup of the position we are about to blank */
+ letter = line_start[perline];
+ line_start[perline]=0; /* zero terminate the buffer */
+ if((checkprefix("WWW-Authenticate:", line_start) &&
+ (401 == k->httpcode)) ||
+ (checkprefix("Proxy-authenticate:", line_start) &&
+ (407 == k->httpcode))) {
+
+ bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+ char *auth = Curl_copy_header_value(line_start);
+ if(!auth)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_http_input_auth(conn, proxy, auth);
+
+ Curl_safefree(auth);
+
+ if(result)
+ return result;
+ }
+ else if(checkprefix("Content-Length:", line_start)) {
+ cl = curlx_strtoofft(line_start +
+ strlen("Content-Length:"), NULL, 10);
+ }
+ else if(Curl_compareheader(line_start,
+ "Connection:", "close"))
+ closeConnection = TRUE;
+ else if(Curl_compareheader(line_start,
+ "Transfer-Encoding:",
+ "chunked")) {
+ infof(data, "CONNECT responded chunked\n");
+ chunked_encoding = TRUE;
+ /* init our chunky engine */
+ Curl_httpchunk_init(conn);
+ }
+ else if(Curl_compareheader(line_start,
+ "Proxy-Connection:", "close"))
+ closeConnection = TRUE;
+ else if(2 == sscanf(line_start, "HTTP/1.%d %d",
+ &subversion,
+ &k->httpcode)) {
+ /* store the HTTP code from the proxy */
+ data->info.httpproxycode = k->httpcode;
+ }
+ /* put back the letter we blanked out before */
+ line_start[perline]= letter;
+
+ perline=0; /* line starts over here */
+ line_start = ptr+1; /* this skips the zero byte we wrote */
+ }
+ }
+ }
+ break;
+ } /* switch */
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ } /* while there's buffer left and loop is requested */
+
+ if(error)
+ return CURLE_RECV_ERROR;
+
+ if(data->info.httpproxycode != 200) {
+ /* Deal with the possibly already received authenticate
+ headers. 'newurl' is set to a new URL if we must loop. */
+ result = Curl_http_auth_act(conn);
+ if(result)
+ return result;
+
+ if(conn->bits.close)
+ /* the connection has been marked for closure, most likely in the
+ Curl_http_auth_act() function and thus we can kill it at once
+ below
+ */
+ closeConnection = TRUE;
+ }
+
+ if(closeConnection && data->req.newurl) {
+ /* Connection closed by server. Don't use it anymore */
+ Curl_closesocket(conn, conn->sock[sockindex]);
+ conn->sock[sockindex] = CURL_SOCKET_BAD;
+ break;
+ }
+ } /* END READING RESPONSE PHASE */
+
+ /* If we are supposed to continue and request a new URL, which basically
+ * means the HTTP authentication is still going on so if the tunnel
+ * is complete we start over in INIT state */
+ if(data->req.newurl &&
+ (TUNNEL_COMPLETE == conn->tunnel_state[sockindex])) {
+ conn->tunnel_state[sockindex] = TUNNEL_INIT;
+ infof(data, "TUNNEL_STATE switched to: %d\n",
+ conn->tunnel_state[sockindex]);
+ }
+
+ } while(data->req.newurl);
+
+ if(200 != data->req.httpcode) {
+ if(closeConnection && data->req.newurl) {
+ conn->bits.proxy_connect_closed = TRUE;
+ infof(data, "Connect me again please\n");
+ }
+ else {
+ if(data->req.newurl) {
+ /* this won't be used anymore for the CONNECT so free it now */
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+ }
+ /* failure, close this connection to avoid re-use */
+ connclose(conn, "proxy CONNECT failure");
+ Curl_closesocket(conn, conn->sock[sockindex]);
+ conn->sock[sockindex] = CURL_SOCKET_BAD;
+ }
+
+ /* to back to init state */
+ conn->tunnel_state[sockindex] = TUNNEL_INIT;
+
+ if(conn->bits.proxy_connect_closed)
+ /* this is not an error, just part of the connection negotiation */
+ return CURLE_OK;
+ else {
+ failf(data, "Received HTTP code %d from proxy after CONNECT",
+ data->req.httpcode);
+ return CURLE_RECV_ERROR;
+ }
+ }
+
+ conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+
+ /* If a proxy-authorization header was used for the proxy, then we should
+ make sure that it isn't accidentally used for the document request
+ after we've connected. So let's free and clear it here. */
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ conn->allocptr.proxyuserpwd = NULL;
+
+ data->state.authproxy.done = TRUE;
+
+ infof (data, "Proxy replied OK to CONNECT request\n");
+ data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
+ conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
+ document request */
+ return CURLE_OK;
+}
+#endif /* CURL_DISABLE_PROXY */
diff --git a/external/libcurl_android/jni/libcurl/lib/http_proxy.h b/external/libcurl_android/jni/libcurl/lib/http_proxy.h
new file mode 100755
index 00000000..2b5e9c9b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/http_proxy.h
@@ -0,0 +1,41 @@
+#ifndef HEADER_CURL_HTTP_PROXY_H
+#define HEADER_CURL_HTTP_PROXY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
+/* ftp can use this as well */
+CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+ int tunnelsocket,
+ const char *hostname, int remote_port);
+
+/* Default proxy timeout in milliseconds */
+#define PROXY_TIMEOUT (3600*1000)
+
+CURLcode Curl_proxy_connect(struct connectdata *conn);
+
+#else
+#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
+#define Curl_proxy_connect(x) CURLE_OK
+#endif
+
+#endif /* HEADER_CURL_HTTP_PROXY_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/idn_win32.c b/external/libcurl_android/jni/libcurl/lib/idn_win32.c
new file mode 100755
index 00000000..464964bc
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/idn_win32.c
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+ /*
+ * IDN conversions using Windows kernel32 and normaliz libraries.
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_WIN32_IDN
+
+#include "curl_multibyte.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef WANT_IDN_PROTOTYPES
+WINBASEAPI int WINAPI IdnToAscii(DWORD, const WCHAR *, int, WCHAR *, int);
+WINBASEAPI int WINAPI IdnToUnicode(DWORD, const WCHAR *, int, WCHAR *, int);
+#endif
+
+#define IDN_MAX_LENGTH 255
+
+int curl_win32_idn_to_ascii(const char *in, char **out);
+int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8);
+
+int curl_win32_idn_to_ascii(const char *in, char **out)
+{
+ wchar_t *in_w = Curl_convert_UTF8_to_wchar(in);
+ if(in_w) {
+ wchar_t punycode[IDN_MAX_LENGTH];
+ if(IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH) == 0) {
+ wprintf(L"ERROR %d converting to Punycode\n", GetLastError());
+ free(in_w);
+ return 0;
+ }
+ free(in_w);
+
+ *out = Curl_convert_wchar_to_UTF8(punycode);
+ if(!*out)
+ return 0;
+ }
+ return 1;
+}
+
+int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8)
+{
+ (void)in_len; /* unused */
+ if(in) {
+ WCHAR unicode[IDN_MAX_LENGTH];
+
+ if(IdnToUnicode(0, (wchar_t *)in, -1, unicode, IDN_MAX_LENGTH) == 0) {
+ wprintf(L"ERROR %d converting to Punycode\n", GetLastError());
+ return 0;
+ }
+ else {
+ *out_utf8 = Curl_convert_wchar_to_UTF8(unicode);
+ if(!*out_utf8)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#endif /* USE_WIN32_IDN */
diff --git a/external/libcurl_android/jni/libcurl/lib/if2ip.c b/external/libcurl_android/jni/libcurl/lib/if2ip.c
new file mode 100755
index 00000000..05ae7d6f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/if2ip.c
@@ -0,0 +1,218 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+#ifdef HAVE_IFADDRS_H
+# include <ifaddrs.h>
+#endif
+#ifdef HAVE_STROPTS_H
+# include <stropts.h>
+#endif
+#ifdef __VMS
+# include <inet.h>
+#endif
+
+#include "inet_ntop.h"
+#include "strequal.h"
+#include "if2ip.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* ------------------------------------------------------------------ */
+
+#if defined(HAVE_GETIFADDRS)
+
+bool Curl_if_is_interface_name(const char *interf)
+{
+ bool result = FALSE;
+
+ struct ifaddrs *iface, *head;
+
+ if(getifaddrs(&head) >= 0) {
+ for(iface=head; iface != NULL; iface=iface->ifa_next) {
+ if(curl_strequal(iface->ifa_name, interf)) {
+ result = TRUE;
+ break;
+ }
+ }
+ freeifaddrs(head);
+ }
+ return result;
+}
+
+if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
+ const char *interf, char *buf, int buf_size)
+{
+ struct ifaddrs *iface, *head;
+ if2ip_result_t res = IF2IP_NOT_FOUND;
+
+#ifndef ENABLE_IPV6
+ (void) remote_scope;
+#endif
+
+ if(getifaddrs(&head) >= 0) {
+ for(iface=head; iface != NULL; iface=iface->ifa_next) {
+ if(iface->ifa_addr != NULL) {
+ if(iface->ifa_addr->sa_family == af) {
+ if(curl_strequal(iface->ifa_name, interf)) {
+ void *addr;
+ char *ip;
+ char scope[12]="";
+ char ipstr[64];
+#ifdef ENABLE_IPV6
+ if(af == AF_INET6) {
+ unsigned int scopeid = 0;
+ addr = &((struct sockaddr_in6 *)iface->ifa_addr)->sin6_addr;
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
+ /* Include the scope of this interface as part of the address */
+ scopeid =
+ ((struct sockaddr_in6 *)iface->ifa_addr)->sin6_scope_id;
+#endif
+ if(scopeid != remote_scope) {
+ /* We are interested only in interface addresses whose
+ scope ID matches the remote address we want to
+ connect to: global (0) for global, link-local for
+ link-local, etc... */
+ if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED;
+ continue;
+ }
+ if(scopeid)
+ snprintf(scope, sizeof(scope), "%%%u", scopeid);
+ }
+ else
+#endif
+ addr = &((struct sockaddr_in *)iface->ifa_addr)->sin_addr;
+ res = IF2IP_FOUND;
+ ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
+ snprintf(buf, buf_size, "%s%s", ip, scope);
+ break;
+ }
+ }
+ else if((res == IF2IP_NOT_FOUND) &&
+ curl_strequal(iface->ifa_name, interf)) {
+ res = IF2IP_AF_NOT_SUPPORTED;
+ }
+ }
+ }
+ freeifaddrs(head);
+ }
+ return res;
+}
+
+#elif defined(HAVE_IOCTL_SIOCGIFADDR)
+
+bool Curl_if_is_interface_name(const char *interf)
+{
+ /* This is here just to support the old interfaces */
+ char buf[256];
+
+ return (Curl_if2ip(AF_INET, 0, interf, buf, sizeof(buf)) ==
+ IF2IP_NOT_FOUND) ? FALSE : TRUE;
+}
+
+if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
+ const char *interf, char *buf, int buf_size)
+{
+ struct ifreq req;
+ struct in_addr in;
+ struct sockaddr_in *s;
+ curl_socket_t dummy;
+ size_t len;
+
+ (void)remote_scope;
+
+ if(!interf || (af != AF_INET))
+ return IF2IP_NOT_FOUND;
+
+ len = strlen(interf);
+ if(len >= sizeof(req.ifr_name))
+ return IF2IP_NOT_FOUND;
+
+ dummy = socket(AF_INET, SOCK_STREAM, 0);
+ if(CURL_SOCKET_BAD == dummy)
+ return IF2IP_NOT_FOUND;
+
+ memset(&req, 0, sizeof(req));
+ memcpy(req.ifr_name, interf, len+1);
+ req.ifr_addr.sa_family = AF_INET;
+
+ if(ioctl(dummy, SIOCGIFADDR, &req) < 0) {
+ sclose(dummy);
+ /* With SIOCGIFADDR, we cannot tell the difference between an interface
+ that does not exist and an interface that has no address of the
+ correct family. Assume the interface does not exist */
+ return IF2IP_NOT_FOUND;
+ }
+
+ s = (struct sockaddr_in *)&req.ifr_addr;
+ memcpy(&in, &s->sin_addr, sizeof(in));
+ Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
+
+ sclose(dummy);
+ return IF2IP_FOUND;
+}
+
+#else
+
+bool Curl_if_is_interface_name(const char *interf)
+{
+ (void) interf;
+
+ return FALSE;
+}
+
+if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
+ const char *interf, char *buf, int buf_size)
+{
+ (void) af;
+ (void) remote_scope;
+ (void) interf;
+ (void) buf;
+ (void) buf_size;
+ return IF2IP_NOT_FOUND;
+}
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/if2ip.h b/external/libcurl_android/jni/libcurl/lib/if2ip.h
new file mode 100755
index 00000000..ac587523
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/if2ip.h
@@ -0,0 +1,74 @@
+#ifndef HEADER_CURL_IF2IP_H
+#define HEADER_CURL_IF2IP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+bool Curl_if_is_interface_name(const char *interf);
+
+typedef enum {
+ IF2IP_NOT_FOUND = 0, /* Interface not found */
+ IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */
+ IF2IP_FOUND = 2 /* The address has been stored in "buf" */
+} if2ip_result_t;
+
+if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
+ const char *interf, char *buf, int buf_size);
+
+#ifdef __INTERIX
+
+/* Nedelcho Stanev's work-around for SFU 3.0 */
+struct ifreq {
+#define IFNAMSIZ 16
+#define IFHWADDRLEN 6
+ union {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ } ifr_ifrn;
+
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ short ifru_flags;
+ int ifru_metric;
+ int ifru_mtu;
+ } ifr_ifru;
+};
+
+/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the
+ C code. */
+
+#define ifr_name ifr_ifrn.ifrn_name /* interface name */
+#define ifr_addr ifr_ifru.ifru_addr /* address */
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
+#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
+#define ifr_metric ifr_ifru.ifru_metric /* metric */
+#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+
+#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */
+
+#endif /* __INTERIX */
+
+#endif /* HEADER_CURL_IF2IP_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/imap.c b/external/libcurl_android/jni/libcurl/lib/imap.c
new file mode 100755
index 00000000..9fc47286
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/imap.c
@@ -0,0 +1,2893 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC2195 CRAM-MD5 authentication
+ * RFC2595 Using TLS with IMAP, POP3 and ACAP
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC3501 IMAPv4 protocol
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4616 PLAIN authentication
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ * RFC4959 IMAP Extension for SASL Initial Client Response
+ * RFC5092 IMAP URL Scheme
+ * RFC6749 OAuth 2.0 Authorization Framework
+ * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_IMAP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "if2ip.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "socks.h"
+#include "imap.h"
+
+#include "strtoofft.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "select.h"
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "curl_sasl.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Local API functions */
+static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
+static CURLcode imap_do(struct connectdata *conn, bool *done);
+static CURLcode imap_done(struct connectdata *conn, CURLcode status,
+ bool premature);
+static CURLcode imap_connect(struct connectdata *conn, bool *done);
+static CURLcode imap_disconnect(struct connectdata *conn, bool dead);
+static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done);
+static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done);
+static CURLcode imap_setup_connection(struct connectdata *conn);
+static char *imap_atom(const char *str);
+static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...);
+static CURLcode imap_parse_url_options(struct connectdata *conn);
+static CURLcode imap_parse_url_path(struct connectdata *conn);
+static CURLcode imap_parse_custom_request(struct connectdata *conn);
+static CURLcode imap_calc_sasl_details(struct connectdata *conn,
+ const char **mech,
+ char **initresp, size_t *len,
+ imapstate *state1, imapstate *state2);
+
+/*
+ * IMAP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_imap = {
+ "IMAP", /* scheme */
+ imap_setup_connection, /* setup_connection */
+ imap_do, /* do_it */
+ imap_done, /* done */
+ ZERO_NULL, /* do_more */
+ imap_connect, /* connect_it */
+ imap_multi_statemach, /* connecting */
+ imap_doing, /* doing */
+ imap_getsock, /* proto_getsock */
+ imap_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ imap_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_IMAP, /* defport */
+ CURLPROTO_IMAP, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * IMAPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_imaps = {
+ "IMAPS", /* scheme */
+ imap_setup_connection, /* setup_connection */
+ imap_do, /* do_it */
+ imap_done, /* done */
+ ZERO_NULL, /* do_more */
+ imap_connect, /* connect_it */
+ imap_multi_statemach, /* connecting */
+ imap_doing, /* doing */
+ imap_getsock, /* proto_getsock */
+ imap_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ imap_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_IMAPS, /* defport */
+ CURLPROTO_IMAPS, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_SSL |
+ PROTOPT_NEEDSPWD /* flags */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed IMAP protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_imap_proxy = {
+ "IMAP", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_IMAP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTP-proxyed IMAPS protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_imaps_proxy = {
+ "IMAPS", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_IMAPS, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+#endif
+#endif
+
+#ifdef USE_SSL
+static void imap_to_imaps(struct connectdata *conn)
+{
+ conn->handler = &Curl_handler_imaps;
+}
+#else
+#define imap_to_imaps(x) Curl_nop_stmt
+#endif
+
+/***********************************************************************
+ *
+ * imap_matchresp()
+ *
+ * Determines whether the untagged response is related to the specified
+ * command by checking if it is in format "* <command-name> ..." or
+ * "* <number> <command-name> ...".
+ *
+ * The "* " marker is assumed to have already been checked by the caller.
+ */
+static bool imap_matchresp(const char *line, size_t len, const char *cmd)
+{
+ const char *end = line + len;
+ size_t cmd_len = strlen(cmd);
+
+ /* Skip the untagged response marker */
+ line += 2;
+
+ /* Do we have a number after the marker? */
+ if(line < end && ISDIGIT(*line)) {
+ /* Skip the number */
+ do
+ line++;
+ while(line < end && ISDIGIT(*line));
+
+ /* Do we have the space character? */
+ if(line == end || *line != ' ')
+ return FALSE;
+
+ line++;
+ }
+
+ /* Does the command name match and is it followed by a space character or at
+ the end of line? */
+ if(line + cmd_len <= end && Curl_raw_nequal(line, cmd, cmd_len) &&
+ (line[cmd_len] == ' ' || line + cmd_len + 2 == end))
+ return TRUE;
+
+ return FALSE;
+}
+
+/***********************************************************************
+ *
+ * imap_endofresp()
+ *
+ * Checks whether the given string is a valid tagged, untagged or continuation
+ * response which can be processed by the response handler.
+ */
+static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
+ int *resp)
+{
+ struct IMAP *imap = conn->data->req.protop;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *id = imapc->resptag;
+ size_t id_len = strlen(id);
+
+ /* Do we have a tagged command response? */
+ if(len >= id_len + 1 && !memcmp(id, line, id_len) && line[id_len] == ' ') {
+ line += id_len + 1;
+ len -= id_len + 1;
+
+ if(len >= 2 && !memcmp(line, "OK", 2))
+ *resp = 'O';
+ else if(len >= 2 && !memcmp(line, "NO", 2))
+ *resp = 'N';
+ else if(len >= 3 && !memcmp(line, "BAD", 3))
+ *resp = 'B';
+ else {
+ failf(conn->data, "Bad tagged response");
+ *resp = -1;
+ }
+
+ return TRUE;
+ }
+
+ /* Do we have an untagged command response? */
+ if(len >= 2 && !memcmp("* ", line, 2)) {
+ switch(imapc->state) {
+ /* States which are interested in untagged responses */
+ case IMAP_CAPABILITY:
+ if(!imap_matchresp(line, len, "CAPABILITY"))
+ return FALSE;
+ break;
+
+ case IMAP_LIST:
+ if((!imap->custom && !imap_matchresp(line, len, "LIST")) ||
+ (imap->custom && !imap_matchresp(line, len, imap->custom) &&
+ (strcmp(imap->custom, "STORE") ||
+ !imap_matchresp(line, len, "FETCH")) &&
+ strcmp(imap->custom, "SELECT") &&
+ strcmp(imap->custom, "EXAMINE") &&
+ strcmp(imap->custom, "SEARCH") &&
+ strcmp(imap->custom, "EXPUNGE") &&
+ strcmp(imap->custom, "LSUB") &&
+ strcmp(imap->custom, "UID") &&
+ strcmp(imap->custom, "NOOP")))
+ return FALSE;
+ break;
+
+ case IMAP_SELECT:
+ /* SELECT is special in that its untagged responses do not have a
+ common prefix so accept anything! */
+ break;
+
+ case IMAP_FETCH:
+ if(!imap_matchresp(line, len, "FETCH"))
+ return FALSE;
+ break;
+
+ case IMAP_SEARCH:
+ if(!imap_matchresp(line, len, "SEARCH"))
+ return FALSE;
+ break;
+
+ /* Ignore other untagged responses */
+ default:
+ return FALSE;
+ }
+
+ *resp = '*';
+ return TRUE;
+ }
+
+ /* Do we have a continuation response? This should be a + symbol followed by
+ a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
+ APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
+ some e-mail servers ignore this and only send a single + instead. */
+ if((len == 3 && !memcmp("+", line, 1)) ||
+ (len >= 2 && !memcmp("+ ", line, 2))) {
+ switch(imapc->state) {
+ /* States which are interested in continuation responses */
+ case IMAP_AUTHENTICATE_PLAIN:
+ case IMAP_AUTHENTICATE_LOGIN:
+ case IMAP_AUTHENTICATE_LOGIN_PASSWD:
+ case IMAP_AUTHENTICATE_CRAMMD5:
+ case IMAP_AUTHENTICATE_DIGESTMD5:
+ case IMAP_AUTHENTICATE_DIGESTMD5_RESP:
+ case IMAP_AUTHENTICATE_NTLM:
+ case IMAP_AUTHENTICATE_NTLM_TYPE2MSG:
+ case IMAP_AUTHENTICATE_XOAUTH2:
+ case IMAP_AUTHENTICATE_FINAL:
+ case IMAP_APPEND:
+ *resp = '+';
+ break;
+
+ default:
+ failf(conn->data, "Unexpected continuation response");
+ *resp = -1;
+ break;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE; /* Nothing for us */
+}
+
+/***********************************************************************
+ *
+ * imap_get_message()
+ *
+ * Gets the authentication message from the response buffer.
+ */
+static void imap_get_message(char *buffer, char** outptr)
+{
+ size_t len = 0;
+ char* message = NULL;
+
+ /* Find the start of the message */
+ for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
+ ;
+
+ /* Find the end of the message */
+ for(len = strlen(message); len--;)
+ if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+ message[len] != '\t')
+ break;
+
+ /* Terminate the message */
+ if(++len) {
+ message[len] = '\0';
+ }
+
+ *outptr = message;
+}
+
+/***********************************************************************
+ *
+ * state()
+ *
+ * This is the ONLY way to change IMAP state!
+ */
+static void state(struct connectdata *conn, imapstate newstate)
+{
+ struct imap_conn *imapc = &conn->proto.imapc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[]={
+ "STOP",
+ "SERVERGREET",
+ "CAPABILITY",
+ "STARTTLS",
+ "UPGRADETLS",
+ "AUTHENTICATE_PLAIN",
+ "AUTHENTICATE_LOGIN",
+ "AUTHENTICATE_LOGIN_PASSWD",
+ "AUTHENTICATE_CRAMMD5",
+ "AUTHENTICATE_DIGESTMD5",
+ "AUTHENTICATE_DIGESTMD5_RESP",
+ "AUTHENTICATE_NTLM",
+ "AUTHENTICATE_NTLM_TYPE2MSG",
+ "AUTHENTICATE_GSSAPI",
+ "AUTHENTICATE_GSSAPI_TOKEN",
+ "AUTHENTICATE_GSSAPI_NO_DATA",
+ "AUTHENTICATE_XOAUTH2",
+ "AUTHENTICATE_CANCEL",
+ "AUTHENTICATE_FINAL",
+ "LOGIN",
+ "LIST",
+ "SELECT",
+ "FETCH",
+ "FETCH_FINAL",
+ "APPEND",
+ "APPEND_FINAL",
+ "SEARCH",
+ "LOGOUT",
+ /* LAST */
+ };
+
+ if(imapc->state != newstate)
+ infof(conn->data, "IMAP %p state change from %s to %s\n",
+ (void *)imapc, names[imapc->state], names[newstate]);
+#endif
+
+ imapc->state = newstate;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_capability()
+ *
+ * Sends the CAPABILITY command in order to obtain a list of server side
+ * supported capabilities.
+ */
+static CURLcode imap_perform_capability(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ imapc->authmechs = 0; /* No known authentication mechanisms yet */
+ imapc->authused = 0; /* Clear the authentication mechanism used */
+ imapc->tls_supported = FALSE; /* Clear the TLS capability */
+
+ /* Send the CAPABILITY command */
+ result = imap_sendf(conn, "CAPABILITY");
+
+ if(!result)
+ state(conn, IMAP_CAPABILITY);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_starttls()
+ *
+ * Sends the STARTTLS command to start the upgrade to TLS.
+ */
+static CURLcode imap_perform_starttls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the STARTTLS command */
+ result = imap_sendf(conn, "STARTTLS");
+
+ if(!result)
+ state(conn, IMAP_STARTTLS);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_upgrade_tls()
+ *
+ * Performs the upgrade to TLS.
+ */
+static CURLcode imap_perform_upgrade_tls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ /* Start the SSL connection */
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
+
+ if(!result) {
+ if(imapc->state != IMAP_UPGRADETLS)
+ state(conn, IMAP_UPGRADETLS);
+
+ if(imapc->ssldone) {
+ imap_to_imaps(conn);
+ result = imap_perform_capability(conn);
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_login()
+ *
+ * Sends a clear text LOGIN command to authenticate with.
+ */
+static CURLcode imap_perform_login(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ char *user;
+ char *passwd;
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't */
+ if(!conn->bits.user_passwd) {
+ state(conn, IMAP_STOP);
+
+ return result;
+ }
+
+ /* Make sure the username and password are in the correct atom format */
+ user = imap_atom(conn->user);
+ passwd = imap_atom(conn->passwd);
+
+ /* Send the LOGIN command */
+ result = imap_sendf(conn, "LOGIN %s %s", user ? user : "",
+ passwd ? passwd : "");
+
+ Curl_safefree(user);
+ Curl_safefree(passwd);
+
+ if(!result)
+ state(conn, IMAP_LOGIN);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_authenticate()
+ *
+ * Sends an AUTHENTICATE command allowing the client to login with the given
+ * SASL authentication mechanism.
+ */
+static CURLcode imap_perform_authenticate(struct connectdata *conn,
+ const char *mech,
+ const char *initresp,
+ imapstate state1, imapstate state2)
+{
+ CURLcode result = CURLE_OK;
+
+ if(initresp) {
+ /* Send the AUTHENTICATE command with the initial response */
+ result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp);
+
+ if(!result)
+ state(conn, state2);
+ }
+ else {
+ /* Send the AUTHENTICATE command */
+ result = imap_sendf(conn, "AUTHENTICATE %s", mech);
+
+ if(!result)
+ state(conn, state1);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_authentication()
+ *
+ * Initiates the authentication sequence, with the appropriate SASL
+ * authentication mechanism, falling back to clear text should a common
+ * mechanism not be available between the client and server.
+ */
+static CURLcode imap_perform_authentication(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *mech = NULL;
+ char *initresp = NULL;
+ size_t len = 0;
+ imapstate state1 = IMAP_STOP;
+ imapstate state2 = IMAP_STOP;
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't */
+ if(!conn->bits.user_passwd) {
+ state(conn, IMAP_STOP);
+
+ return result;
+ }
+
+ /* Calculate the SASL login details */
+ result = imap_calc_sasl_details(conn, &mech, &initresp, &len, &state1,
+ &state2);
+
+ if(!result) {
+ if(mech && (imapc->preftype & IMAP_TYPE_SASL)) {
+ /* Perform SASL based authentication */
+ result = imap_perform_authenticate(conn, mech, initresp, state1, state2);
+
+ Curl_safefree(initresp);
+ }
+ else if((!imapc->login_disabled) &&
+ (imapc->preftype & IMAP_TYPE_CLEARTEXT))
+ /* Perform clear text authentication */
+ result = imap_perform_login(conn);
+ else {
+ /* Other mechanisms not supported */
+ infof(conn->data, "No known authentication mechanisms supported!\n");
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_list()
+ *
+ * Sends a LIST command or an alternative custom request.
+ */
+static CURLcode imap_perform_list(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ char *mailbox;
+
+ if(imap->custom)
+ /* Send the custom request */
+ result = imap_sendf(conn, "%s%s", imap->custom,
+ imap->custom_params ? imap->custom_params : "");
+ else {
+ /* Make sure the mailbox is in the correct atom format */
+ mailbox = imap_atom(imap->mailbox ? imap->mailbox : "");
+ if(!mailbox)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the LIST command */
+ result = imap_sendf(conn, "LIST \"%s\" *", mailbox);
+
+ Curl_safefree(mailbox);
+ }
+
+ if(!result)
+ state(conn, IMAP_LIST);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_select()
+ *
+ * Sends a SELECT command to ask the server to change the selected mailbox.
+ */
+static CURLcode imap_perform_select(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ char *mailbox;
+
+ /* Invalidate old information as we are switching mailboxes */
+ Curl_safefree(imapc->mailbox);
+ Curl_safefree(imapc->mailbox_uidvalidity);
+
+ /* Check we have a mailbox */
+ if(!imap->mailbox) {
+ failf(conn->data, "Cannot SELECT without a mailbox.");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Make sure the mailbox is in the correct atom format */
+ mailbox = imap_atom(imap->mailbox);
+ if(!mailbox)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the SELECT command */
+ result = imap_sendf(conn, "SELECT %s", mailbox);
+
+ Curl_safefree(mailbox);
+
+ if(!result)
+ state(conn, IMAP_SELECT);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_fetch()
+ *
+ * Sends a FETCH command to initiate the download of a message.
+ */
+static CURLcode imap_perform_fetch(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct IMAP *imap = conn->data->req.protop;
+
+ /* Check we have a UID */
+ if(!imap->uid) {
+ failf(conn->data, "Cannot FETCH without a UID.");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Send the FETCH command */
+ if(imap->partial)
+ result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
+ imap->uid,
+ imap->section ? imap->section : "",
+ imap->partial);
+ else
+ result = imap_sendf(conn, "FETCH %s BODY[%s]",
+ imap->uid,
+ imap->section ? imap->section : "");
+
+ if(!result)
+ state(conn, IMAP_FETCH);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_append()
+ *
+ * Sends an APPEND command to initiate the upload of a message.
+ */
+static CURLcode imap_perform_append(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct IMAP *imap = conn->data->req.protop;
+ char *mailbox;
+
+ /* Check we have a mailbox */
+ if(!imap->mailbox) {
+ failf(conn->data, "Cannot APPEND without a mailbox.");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Check we know the size of the upload */
+ if(conn->data->state.infilesize < 0) {
+ failf(conn->data, "Cannot APPEND with unknown input file size\n");
+ return CURLE_UPLOAD_FAILED;
+ }
+
+ /* Make sure the mailbox is in the correct atom format */
+ mailbox = imap_atom(imap->mailbox);
+ if(!mailbox)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the APPEND command */
+ result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
+ mailbox, conn->data->state.infilesize);
+
+ Curl_safefree(mailbox);
+
+ if(!result)
+ state(conn, IMAP_APPEND);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_search()
+ *
+ * Sends a SEARCH command.
+ */
+static CURLcode imap_perform_search(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct IMAP *imap = conn->data->req.protop;
+
+ /* Check we have a query string */
+ if(!imap->query) {
+ failf(conn->data, "Cannot SEARCH without a query string.");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Send the SEARCH command */
+ result = imap_sendf(conn, "SEARCH %s", imap->query);
+
+ if(!result)
+ state(conn, IMAP_SEARCH);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform_logout()
+ *
+ * Performs the logout action prior to sclose() being called.
+ */
+static CURLcode imap_perform_logout(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the LOGOUT command */
+ result = imap_sendf(conn, "LOGOUT");
+
+ if(!result)
+ state(conn, IMAP_LOGOUT);
+
+ return result;
+}
+
+/* For the initial server greeting */
+static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != 'O') {
+ failf(data, "Got unexpected imap-server response");
+ result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
+ }
+ else
+ result = imap_perform_capability(conn);
+
+ return result;
+}
+
+/* For CAPABILITY responses */
+static CURLcode imap_state_capability_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *line = data->state.buffer;
+ size_t wordlen;
+
+ (void)instate; /* no use for this yet */
+
+ /* Do we have a untagged response? */
+ if(imapcode == '*') {
+ line += 2;
+
+ /* Loop through the data line */
+ for(;;) {
+ while(*line &&
+ (*line == ' ' || *line == '\t' ||
+ *line == '\r' || *line == '\n')) {
+
+ line++;
+ }
+
+ if(!*line)
+ break;
+
+ /* Extract the word */
+ for(wordlen = 0; line[wordlen] && line[wordlen] != ' ' &&
+ line[wordlen] != '\t' && line[wordlen] != '\r' &&
+ line[wordlen] != '\n';)
+ wordlen++;
+
+ /* Does the server support the STARTTLS capability? */
+ if(wordlen == 8 && !memcmp(line, "STARTTLS", 8))
+ imapc->tls_supported = TRUE;
+
+ /* Has the server explicitly disabled clear text authentication? */
+ else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13))
+ imapc->login_disabled = TRUE;
+
+ /* Does the server support the SASL-IR capability? */
+ else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7))
+ imapc->ir_supported = TRUE;
+
+ /* Do we have a SASL based authentication mechanism? */
+ else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) {
+ line += 5;
+ wordlen -= 5;
+
+ /* Test the word for a matching authentication mechanism */
+ if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
+ imapc->authmechs |= SASL_MECH_LOGIN;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
+ imapc->authmechs |= SASL_MECH_PLAIN;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
+ imapc->authmechs |= SASL_MECH_CRAM_MD5;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
+ imapc->authmechs |= SASL_MECH_DIGEST_MD5;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
+ imapc->authmechs |= SASL_MECH_GSSAPI;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
+ imapc->authmechs |= SASL_MECH_EXTERNAL;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
+ imapc->authmechs |= SASL_MECH_NTLM;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
+ imapc->authmechs |= SASL_MECH_XOAUTH2;
+ }
+
+ line += wordlen;
+ }
+ }
+ else if(imapcode == 'O') {
+ if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* We don't have a SSL/TLS connection yet, but SSL is requested */
+ if(imapc->tls_supported)
+ /* Switch to TLS connection now */
+ result = imap_perform_starttls(conn);
+ else if(data->set.use_ssl == CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = imap_perform_authentication(conn);
+ else {
+ failf(data, "STARTTLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
+ }
+ else
+ result = imap_perform_authentication(conn);
+ }
+ else
+ result = imap_perform_authentication(conn);
+
+ return result;
+}
+
+/* For STARTTLS responses */
+static CURLcode imap_state_starttls_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != 'O') {
+ if(data->set.use_ssl != CURLUSESSL_TRY) {
+ failf(data, "STARTTLS denied. %c", imapcode);
+ result = CURLE_USE_SSL_FAILED;
+ }
+ else
+ result = imap_perform_authentication(conn);
+ }
+ else
+ result = imap_perform_upgrade_tls(conn);
+
+ return result;
+}
+
+/* For AUTHENTICATE PLAIN (without initial response) responses */
+static CURLcode imap_state_auth_plain_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *plainauth = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied. %c", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the authorisation message */
+ result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
+ &plainauth, &len);
+ if(!result && plainauth) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_FINAL);
+ }
+ }
+
+ Curl_safefree(plainauth);
+
+ return result;
+}
+
+/* For AUTHENTICATE LOGIN (without initial response) responses */
+static CURLcode imap_state_auth_login_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *authuser = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the user message */
+ result = Curl_sasl_create_login_message(data, conn->user,
+ &authuser, &len);
+ if(!result && authuser) {
+ /* Send the user */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authuser);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_LOGIN_PASSWD);
+ }
+ }
+
+ Curl_safefree(authuser);
+
+ return result;
+}
+
+/* For AUTHENTICATE LOGIN user entry responses */
+static CURLcode imap_state_auth_login_password_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *authpasswd = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the password message */
+ result = Curl_sasl_create_login_message(data, conn->passwd,
+ &authpasswd, &len);
+ if(!result && authpasswd) {
+ /* Send the password */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authpasswd);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_FINAL);
+ }
+ }
+
+ Curl_safefree(authpasswd);
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+/* For AUTHENTICATE CRAM-MD5 responses */
+static CURLcode imap_state_auth_cram_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlg = NULL;
+ char *chlg64 = NULL;
+ char *rplyb64 = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Get the challenge message */
+ imap_get_message(data->state.buffer, &chlg64);
+
+ /* Decode the challenge message */
+ result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
+ if(result) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_CANCEL);
+ }
+ else {
+ /* Create the response message */
+ result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user,
+ conn->passwd, &rplyb64, &len);
+ if(!result && rplyb64) {
+ /* Send the response */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_FINAL);
+ }
+ }
+
+ Curl_safefree(chlg);
+ Curl_safefree(rplyb64);
+
+ return result;
+}
+
+/* For AUTHENTICATE DIGEST-MD5 challenge responses */
+static CURLcode imap_state_auth_digest_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlg64 = NULL;
+ char *rplyb64 = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Get the challenge message */
+ imap_get_message(data->state.buffer, &chlg64);
+
+ /* Create the response message */
+ result = Curl_sasl_create_digest_md5_message(data, chlg64,
+ conn->user, conn->passwd,
+ "imap", &rplyb64, &len);
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_DIGESTMD5_RESP);
+ }
+
+ Curl_safefree(rplyb64);
+
+ return result;
+}
+
+/* For AUTHENTICATE DIGEST-MD5 challenge-response responses */
+static CURLcode imap_state_auth_digest_resp_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Authentication failed: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Send an empty response */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "");
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_FINAL);
+ }
+
+ return result;
+}
+#endif
+
+#ifdef USE_NTLM
+/* For AUTHENTICATE NTLM (without initial response) responses */
+static CURLcode imap_state_auth_ntlm_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *type1msg = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the type-1 message */
+ result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
+ &conn->ntlm,
+ &type1msg, &len);
+ if(!result && type1msg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type1msg);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_NTLM_TYPE2MSG);
+ }
+ }
+
+ Curl_safefree(type1msg);
+
+ return result;
+}
+
+/* For NTLM type-2 responses (sent in reponse to our type-1 message) */
+static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *type2msg = NULL;
+ char *type3msg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the challenge message */
+ imap_get_message(data->state.buffer, &type2msg);
+
+ /* Decode the type-2 message */
+ result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
+ if(result) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_CANCEL);
+ }
+ else {
+ /* Create the type-3 message */
+ result = Curl_sasl_create_ntlm_type3_message(data, conn->user,
+ conn->passwd, &conn->ntlm,
+ &type3msg, &len);
+ if(!result && type3msg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type3msg);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_FINAL);
+ }
+ }
+ }
+
+ Curl_safefree(type3msg);
+
+ return result;
+}
+#endif
+
+#if defined(USE_WINDOWS_SSPI)
+/* For AUTHENTICATE GSSAPI (without initial response) responses */
+static CURLcode imap_state_auth_gssapi_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ size_t len = 0;
+ char *respmsg = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the initial response message */
+ result = Curl_sasl_create_gssapi_user_message(data, conn->user,
+ conn->passwd, "imap",
+ imapc->mutual_auth,
+ NULL, &conn->krb5,
+ &respmsg, &len);
+ if(!result && respmsg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&imapc->pp, "%s", respmsg);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_GSSAPI_TOKEN);
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+
+/* For AUTHENTICATE GSSAPI user token responses */
+static CURLcode imap_state_auth_gssapi_token_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ char *chlgmsg = NULL;
+ char *respmsg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the challenge message */
+ imap_get_message(data->state.buffer, &chlgmsg);
+
+ if(imapc->mutual_auth)
+ /* Decode the user token challenge and create the optional response
+ message */
+ result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL,
+ imapc->mutual_auth,
+ chlgmsg, &conn->krb5,
+ &respmsg, &len);
+ else
+ /* Decode the security challenge and create the response message */
+ result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
+ &conn->krb5,
+ &respmsg, &len);
+
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&imapc->pp, "%s", "*");
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ if(respmsg)
+ result = Curl_pp_sendf(&imapc->pp, "%s", respmsg);
+ else
+ result = Curl_pp_sendf(&imapc->pp, "%s", "");
+
+ if(!result)
+ state(conn, (imapc->mutual_auth ? IMAP_AUTHENTICATE_GSSAPI_NO_DATA :
+ IMAP_AUTHENTICATE_FINAL));
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+
+/* For AUTHENTICATE GSSAPI no data responses */
+static CURLcode imap_state_auth_gssapi_no_data_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlgmsg = NULL;
+ char *respmsg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the challenge message */
+ imap_get_message(data->state.buffer, &chlgmsg);
+
+ /* Decode the security challenge and create the response message */
+ result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
+ &conn->krb5,
+ &respmsg, &len);
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ if(respmsg) {
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", respmsg);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_FINAL);
+ }
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+#endif
+
+/* For AUTHENTICATE XOAUTH2 (without initial response) responses */
+static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *xoauth = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '+') {
+ failf(data, "Access denied: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the authorisation message */
+ result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
+ conn->xoauth2_bearer,
+ &xoauth, &len);
+ if(!result && xoauth) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth);
+
+ if(!result)
+ state(conn, IMAP_AUTHENTICATE_FINAL);
+ }
+ }
+
+ Curl_safefree(xoauth);
+
+ return result;
+}
+
+/* For AUTHENTICATE cancellation responses */
+static CURLcode imap_state_auth_cancel_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *mech = NULL;
+ char *initresp = NULL;
+ size_t len = 0;
+ imapstate state1 = IMAP_STOP;
+ imapstate state2 = IMAP_STOP;
+
+ (void)imapcode;
+ (void)instate; /* no use for this yet */
+
+ /* Remove the offending mechanism from the supported list */
+ imapc->authmechs ^= imapc->authused;
+
+ /* Calculate alternative SASL login details */
+ result = imap_calc_sasl_details(conn, &mech, &initresp, &len, &state1,
+ &state2);
+
+ if(!result) {
+ /* Do we have any mechanisms left or can we fallback to clear text? */
+ if(mech) {
+ /* Retry SASL based authentication */
+ result = imap_perform_authenticate(conn, mech, initresp, state1, state2);
+
+ Curl_safefree(initresp);
+ }
+ else if((!imapc->login_disabled) &&
+ (imapc->preftype & IMAP_TYPE_CLEARTEXT))
+ /* Perform clear text authentication */
+ result = imap_perform_login(conn);
+ else {
+ failf(data, "Authentication cancelled");
+
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/* For final responses in the AUTHENTICATE sequence */
+static CURLcode imap_state_auth_final_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != 'O') {
+ failf(data, "Authentication failed: %d", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For LOGIN responses */
+static CURLcode imap_state_login_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != 'O') {
+ failf(data, "Access denied. %c", imapcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For LIST responses */
+static CURLcode imap_state_list_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ char *line = conn->data->state.buffer;
+ size_t len = strlen(line);
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode == '*') {
+ /* Temporarily add the LF character back and send as body to the client */
+ line[len] = '\n';
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ line[len] = '\0';
+ }
+ else if(imapcode != 'O')
+ result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
+ else
+ /* End of DO phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For SELECT responses */
+static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = conn->data->req.protop;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *line = data->state.buffer;
+ char tmp[20];
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode == '*') {
+ /* See if this is an UIDVALIDITY response */
+ if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
+ Curl_safefree(imapc->mailbox_uidvalidity);
+ imapc->mailbox_uidvalidity = strdup(tmp);
+ }
+ }
+ else if(imapcode == 'O') {
+ /* Check if the UIDVALIDITY has been specified and matches */
+ if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
+ strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
+ failf(conn->data, "Mailbox UIDVALIDITY has changed");
+ result = CURLE_REMOTE_FILE_NOT_FOUND;
+ }
+ else {
+ /* Note the currently opened mailbox on this connection */
+ imapc->mailbox = strdup(imap->mailbox);
+
+ if(imap->custom)
+ result = imap_perform_list(conn);
+ else if(imap->query)
+ result = imap_perform_search(conn);
+ else
+ result = imap_perform_fetch(conn);
+ }
+ }
+ else {
+ failf(data, "Select failed");
+ result = CURLE_LOGIN_DENIED;
+ }
+
+ return result;
+}
+
+/* For the (first line of the) FETCH responses */
+static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ struct pingpong *pp = &imapc->pp;
+ const char *ptr = data->state.buffer;
+ bool parsed = FALSE;
+ curl_off_t size;
+
+ (void)instate; /* no use for this yet */
+
+ if(imapcode != '*') {
+ Curl_pgrsSetDownloadSize(data, -1);
+ state(conn, IMAP_STOP);
+ return CURLE_REMOTE_FILE_NOT_FOUND; /* TODO: Fix error code */
+ }
+
+ /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
+ the continuation data contained within the curly brackets */
+ while(*ptr && (*ptr != '{'))
+ ptr++;
+
+ if(*ptr == '{') {
+ char *endptr;
+ size = curlx_strtoofft(ptr + 1, &endptr, 10);
+ if(endptr - ptr > 1 && endptr[0] == '}' &&
+ endptr[1] == '\r' && endptr[2] == '\0')
+ parsed = TRUE;
+ }
+
+ if(parsed) {
+ infof(data, "Found %" CURL_FORMAT_CURL_OFF_TU " bytes to download\n",
+ size);
+ Curl_pgrsSetDownloadSize(data, size);
+
+ if(pp->cache) {
+ /* At this point there is a bunch of data in the header "cache" that is
+ actually body content, send it as body and then skip it. Do note
+ that there may even be additional "headers" after the body. */
+ size_t chunk = pp->cache_size;
+
+ if(chunk > (size_t)size)
+ /* The conversion from curl_off_t to size_t is always fine here */
+ chunk = (size_t)size;
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk);
+ if(result)
+ return result;
+
+ data->req.bytecount += chunk;
+
+ infof(data, "Written %" CURL_FORMAT_CURL_OFF_TU
+ " bytes, %" CURL_FORMAT_CURL_OFF_TU
+ " bytes are left for transfer\n", (curl_off_t)chunk,
+ size - chunk);
+
+ /* Have we used the entire cache or just part of it?*/
+ if(pp->cache_size > chunk) {
+ /* Only part of it so shrink the cache to fit the trailing data */
+ memmove(pp->cache, pp->cache + chunk, pp->cache_size - chunk);
+ pp->cache_size -= chunk;
+ }
+ else {
+ /* Free the cache */
+ Curl_safefree(pp->cache);
+
+ /* Reset the cache size */
+ pp->cache_size = 0;
+ }
+ }
+
+ if(data->req.bytecount == size)
+ /* The entire data is already transferred! */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ else {
+ /* IMAP download */
+ data->req.maxdownload = size;
+ Curl_setup_transfer(conn, FIRSTSOCKET, size, FALSE, NULL, -1, NULL);
+ }
+ }
+ else {
+ /* We don't know how to parse this line */
+ failf(pp->conn->data, "Failed to parse FETCH response.");
+ result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
+ }
+
+ /* End of DO phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For final FETCH responses performed after the download */
+static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode != 'O')
+ result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: Fix error code */
+ else
+ /* End of DONE phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For APPEND responses */
+static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode != '+') {
+ result = CURLE_UPLOAD_FAILED;
+ }
+ else {
+ /* Set the progress upload size */
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+
+ /* IMAP upload */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+
+ /* End of DO phase */
+ state(conn, IMAP_STOP);
+ }
+
+ return result;
+}
+
+/* For final APPEND responses performed after the upload */
+static CURLcode imap_state_append_final_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode != 'O')
+ result = CURLE_UPLOAD_FAILED;
+ else
+ /* End of DONE phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+/* For SEARCH responses */
+static CURLcode imap_state_search_resp(struct connectdata *conn, int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ char *line = conn->data->state.buffer;
+ size_t len = strlen(line);
+
+ (void)instate; /* No use for this yet */
+
+ if(imapcode == '*') {
+ /* Temporarily add the LF character back and send as body to the client */
+ line[len] = '\n';
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ line[len] = '\0';
+ }
+ else if(imapcode != 'O')
+ result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
+ else
+ /* End of DO phase */
+ state(conn, IMAP_STOP);
+
+ return result;
+}
+
+static CURLcode imap_statemach_act(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ int imapcode;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ struct pingpong *pp = &imapc->pp;
+ size_t nread = 0;
+
+ /* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
+ if(imapc->state == IMAP_UPGRADETLS)
+ return imap_perform_upgrade_tls(conn);
+
+ /* Flush any data that needs to be sent */
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
+
+ do {
+ /* Read the response from the server */
+ result = Curl_pp_readresp(sock, pp, &imapcode, &nread);
+ if(result)
+ return result;
+
+ /* Was there an error parsing the response line? */
+ if(imapcode == -1)
+ return CURLE_FTP_WEIRD_SERVER_REPLY;
+
+ if(!imapcode)
+ break;
+
+ /* We have now received a full IMAP server response */
+ switch(imapc->state) {
+ case IMAP_SERVERGREET:
+ result = imap_state_servergreet_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_CAPABILITY:
+ result = imap_state_capability_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_STARTTLS:
+ result = imap_state_starttls_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_PLAIN:
+ result = imap_state_auth_plain_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_LOGIN:
+ result = imap_state_auth_login_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_LOGIN_PASSWD:
+ result = imap_state_auth_login_password_resp(conn, imapcode,
+ imapc->state);
+ break;
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ case IMAP_AUTHENTICATE_CRAMMD5:
+ result = imap_state_auth_cram_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_DIGESTMD5:
+ result = imap_state_auth_digest_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_DIGESTMD5_RESP:
+ result = imap_state_auth_digest_resp_resp(conn, imapcode, imapc->state);
+ break;
+#endif
+
+#ifdef USE_NTLM
+ case IMAP_AUTHENTICATE_NTLM:
+ result = imap_state_auth_ntlm_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_NTLM_TYPE2MSG:
+ result = imap_state_auth_ntlm_type2msg_resp(conn, imapcode,
+ imapc->state);
+ break;
+#endif
+
+#if defined(USE_WINDOWS_SSPI)
+ case IMAP_AUTHENTICATE_GSSAPI:
+ result = imap_state_auth_gssapi_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_GSSAPI_TOKEN:
+ result = imap_state_auth_gssapi_token_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_GSSAPI_NO_DATA:
+ result = imap_state_auth_gssapi_no_data_resp(conn, imapcode,
+ imapc->state);
+ break;
+#endif
+
+ case IMAP_AUTHENTICATE_XOAUTH2:
+ result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_CANCEL:
+ result = imap_state_auth_cancel_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_AUTHENTICATE_FINAL:
+ result = imap_state_auth_final_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_LOGIN:
+ result = imap_state_login_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_LIST:
+ result = imap_state_list_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_SELECT:
+ result = imap_state_select_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_FETCH:
+ result = imap_state_fetch_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_FETCH_FINAL:
+ result = imap_state_fetch_final_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_APPEND:
+ result = imap_state_append_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_APPEND_FINAL:
+ result = imap_state_append_final_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_SEARCH:
+ result = imap_state_search_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_LOGOUT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ state(conn, IMAP_STOP);
+ break;
+ }
+ } while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp));
+
+ return result;
+}
+
+/* Called repeatedly until done from multi.c */
+static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
+ if(result || !imapc->ssldone)
+ return result;
+ }
+
+ result = Curl_pp_statemach(&imapc->pp, FALSE);
+ *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
+
+ return result;
+}
+
+static CURLcode imap_block_statemach(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ while(imapc->state != IMAP_STOP && !result)
+ result = Curl_pp_statemach(&imapc->pp, TRUE);
+
+ return result;
+}
+
+/* Allocate and initialize the struct IMAP for the current SessionHandle if
+ required */
+static CURLcode imap_init(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap;
+
+ imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
+ if(!imap)
+ result = CURLE_OUT_OF_MEMORY;
+
+ return result;
+}
+
+/* For the IMAP "protocol connect" and "doing" phases only */
+static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks);
+}
+
+/***********************************************************************
+ *
+ * imap_connect()
+ *
+ * This function should do everything that is to be considered a part of the
+ * connection phase.
+ *
+ * The variable 'done' points to will be TRUE if the protocol-layer connect
+ * phase is done when this function returns, or FALSE if not.
+ */
+static CURLcode imap_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ struct pingpong *pp = &imapc->pp;
+
+ *done = FALSE; /* default to not done yet */
+
+ /* We always support persistent connections in IMAP */
+ connkeep(conn, "IMAP default");
+
+ /* Set the default response time-out */
+ pp->response_time = RESP_TIMEOUT;
+ pp->statemach_act = imap_statemach_act;
+ pp->endofresp = imap_endofresp;
+ pp->conn = conn;
+
+ /* Set the default preferred authentication type and mechanism */
+ imapc->preftype = IMAP_TYPE_ANY;
+ imapc->prefmech = SASL_AUTH_ANY;
+
+ /* Initialise the pingpong layer */
+ Curl_pp_init(pp);
+
+ /* Parse the URL options */
+ result = imap_parse_url_options(conn);
+ if(result)
+ return result;
+
+ /* Start off waiting for the server greeting response */
+ state(conn, IMAP_SERVERGREET);
+
+ /* Start off with an response id of '*' */
+ strcpy(imapc->resptag, "*");
+
+ result = imap_multi_statemach(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_done()
+ *
+ * The DONE function. This does what needs to be done after a single DO has
+ * performed.
+ *
+ * Input argument is already checked for validity.
+ */
+static CURLcode imap_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+
+ (void)premature;
+
+ if(!imap)
+ /* When the easy handle is removed from the multi interface while libcurl
+ is still trying to resolve the host name, the IMAP struct is not yet
+ initialized. However, the removal action calls Curl_done() which in
+ turn calls this function, so we simply return success. */
+ return CURLE_OK;
+
+ if(status) {
+ connclose(conn, "IMAP done with bad status"); /* marked for closure */
+ result = status; /* use the already set error code */
+ }
+ else if(!data->set.connect_only && !imap->custom &&
+ (imap->uid || data->set.upload)) {
+ /* Handle responses after FETCH or APPEND transfer has finished */
+ if(!data->set.upload)
+ state(conn, IMAP_FETCH_FINAL);
+ else {
+ /* End the APPEND command first by sending an empty line */
+ result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "");
+ if(!result)
+ state(conn, IMAP_APPEND_FINAL);
+ }
+
+ /* Run the state-machine
+
+ TODO: when the multi interface is used, this _really_ should be using
+ the imap_multi_statemach function but we have no general support for
+ non-blocking DONE operations, not in the multi state machine and with
+ Curl_done() invokes on several places in the code!
+ */
+ if(!result)
+ result = imap_block_statemach(conn);
+ }
+
+ /* Cleanup our per-request based variables */
+ Curl_safefree(imap->mailbox);
+ Curl_safefree(imap->uidvalidity);
+ Curl_safefree(imap->uid);
+ Curl_safefree(imap->section);
+ Curl_safefree(imap->partial);
+ Curl_safefree(imap->query);
+ Curl_safefree(imap->custom);
+ Curl_safefree(imap->custom_params);
+
+ /* Clear the transfer mode for the next request */
+ imap->transfer = FTPTRANSFER_BODY;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_perform()
+ *
+ * This is the actual DO function for IMAP. Fetch or append a message, or do
+ * other things according to the options previously setup.
+ */
+static CURLcode imap_perform(struct connectdata *conn, bool *connected,
+ bool *dophase_done)
+{
+ /* This is IMAP and no proxy */
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ bool selected = FALSE;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ if(conn->data->set.opt_no_body) {
+ /* Requested no body means no transfer */
+ imap->transfer = FTPTRANSFER_INFO;
+ }
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* Determine if the requested mailbox (with the same UIDVALIDITY if set)
+ has already been selected on this connection */
+ if(imap->mailbox && imapc->mailbox &&
+ !strcmp(imap->mailbox, imapc->mailbox) &&
+ (!imap->uidvalidity || !imapc->mailbox_uidvalidity ||
+ !strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)))
+ selected = TRUE;
+
+ /* Start the first command in the DO phase */
+ if(conn->data->set.upload)
+ /* APPEND can be executed directly */
+ result = imap_perform_append(conn);
+ else if(imap->custom && (selected || !imap->mailbox))
+ /* Custom command using the same mailbox or no mailbox */
+ result = imap_perform_list(conn);
+ else if(!imap->custom && selected && imap->uid)
+ /* FETCH from the same mailbox */
+ result = imap_perform_fetch(conn);
+ else if(!imap->custom && selected && imap->query)
+ /* SEARCH the current mailbox */
+ result = imap_perform_search(conn);
+ else if(imap->mailbox && !selected &&
+ (imap->custom || imap->uid || imap->query))
+ /* SELECT the mailbox */
+ result = imap_perform_select(conn);
+ else
+ /* LIST */
+ result = imap_perform_list(conn);
+
+ if(result)
+ return result;
+
+ /* Run the state-machine */
+ result = imap_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_do()
+ *
+ * This function is registered as 'curl_do' function. It decodes the path
+ * parts etc as a wrapper to the actual DO function (imap_perform).
+ *
+ * The input argument is already checked for validity.
+ */
+static CURLcode imap_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+
+ *done = FALSE; /* default to false */
+
+ /* Parse the URL path */
+ result = imap_parse_url_path(conn);
+ if(result)
+ return result;
+
+ /* Parse the custom request */
+ result = imap_parse_custom_request(conn);
+ if(result)
+ return result;
+
+ result = imap_regular_transfer(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_disconnect()
+ *
+ * Disconnect from an IMAP server. Cleanup protocol-specific per-connection
+ * resources. BLOCKING.
+ */
+static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ /* We cannot send quit unconditionally. If this connection is stale or
+ bad in any way, sending quit and waiting around here will make the
+ disconnect wait in vain and cause more problems than we need to. */
+
+ /* The IMAP session may or may not have been allocated/setup at this
+ point! */
+ if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
+ if(!imap_perform_logout(conn))
+ (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */
+
+ /* Disconnect from the server */
+ Curl_pp_disconnect(&imapc->pp);
+
+ /* Cleanup the SASL module */
+ Curl_sasl_cleanup(conn, imapc->authused);
+
+ /* Cleanup our connection based variables */
+ Curl_safefree(imapc->mailbox);
+ Curl_safefree(imapc->mailbox_uidvalidity);
+
+ return CURLE_OK;
+}
+
+/* Call this when the DO phase has completed */
+static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
+{
+ struct IMAP *imap = conn->data->req.protop;
+
+ (void)connected;
+
+ if(imap->transfer != FTPTRANSFER_BODY)
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ return CURLE_OK;
+}
+
+/* Called from multi.c while DOing */
+static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result = imap_multi_statemach(conn, dophase_done);
+
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
+ result = imap_dophase_done(conn, FALSE /* not connected */);
+
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_regular_transfer()
+ *
+ * The input argument is already checked for validity.
+ *
+ * Performs all commands done before a regular transfer between a local and a
+ * remote host.
+ */
+static CURLcode imap_regular_transfer(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
+ struct SessionHandle *data = conn->data;
+
+ /* Make sure size is unknown at this point */
+ data->req.size = -1;
+
+ /* Set the progress data */
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ /* Carry out the perform */
+ result = imap_perform(conn, &connected, dophase_done);
+
+ /* Perform post DO phase operations if necessary */
+ if(!result && *dophase_done)
+ result = imap_dophase_done(conn, connected);
+
+ return result;
+}
+
+static CURLcode imap_setup_connection(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+
+ /* Initialise the IMAP layer */
+ CURLcode result = imap_init(conn);
+ if(result)
+ return result;
+
+ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+ /* Unless we have asked to tunnel IMAP operations through the proxy, we
+ switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+ if(conn->handler == &Curl_handler_imap)
+ conn->handler = &Curl_handler_imap_proxy;
+ else {
+#ifdef USE_SSL
+ conn->handler = &Curl_handler_imaps_proxy;
+#else
+ failf(data, "IMAPS not supported!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ /* set it up as an HTTP connection instead */
+ return conn->handler->setup_connection(conn);
+#else
+ failf(data, "IMAP over http proxy requires HTTP support built-in!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ data->state.path++; /* don't include the initial slash */
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * imap_sendf()
+ *
+ * Sends the formated string as an IMAP command to the server.
+ *
+ * Designed to never block.
+ */
+static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ char *taggedfmt;
+ va_list ap;
+
+ DEBUGASSERT(fmt);
+
+ /* Calculate the next command ID wrapping at 3 digits */
+ imapc->cmdid = (imapc->cmdid + 1) % 1000;
+
+ /* Calculate the tag based on the connection ID and command ID */
+ snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
+ 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
+
+ /* Prefix the format with the tag */
+ taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
+ if(!taggedfmt)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Send the data with the tag */
+ va_start(ap, fmt);
+ result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
+ va_end(ap);
+
+ Curl_safefree(taggedfmt);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_atom()
+ *
+ * Checks the input string for characters that need escaping and returns an
+ * atom ready for sending to the server.
+ *
+ * The returned string needs to be freed.
+ *
+ */
+static char *imap_atom(const char *str)
+{
+ const char *p1;
+ char *p2;
+ size_t backsp_count = 0;
+ size_t quote_count = 0;
+ bool space_exists = FALSE;
+ size_t newlen = 0;
+ char *newstr = NULL;
+
+ if(!str)
+ return NULL;
+
+ /* Count any unescapped characters */
+ p1 = str;
+ while(*p1) {
+ if(*p1 == '\\')
+ backsp_count++;
+ else if(*p1 == '"')
+ quote_count++;
+ else if(*p1 == ' ')
+ space_exists = TRUE;
+
+ p1++;
+ }
+
+ /* Does the input contain any unescapped characters? */
+ if(!backsp_count && !quote_count && !space_exists)
+ return strdup(str);
+
+ /* Calculate the new string length */
+ newlen = strlen(str) + backsp_count + quote_count + (space_exists ? 2 : 0);
+
+ /* Allocate the new string */
+ newstr = (char *) malloc((newlen + 1) * sizeof(char));
+ if(!newstr)
+ return NULL;
+
+ /* Surround the string in quotes if necessary */
+ p2 = newstr;
+ if(space_exists) {
+ newstr[0] = '"';
+ newstr[newlen - 1] = '"';
+ p2++;
+ }
+
+ /* Copy the string, escaping backslash and quote characters along the way */
+ p1 = str;
+ while(*p1) {
+ if(*p1 == '\\' || *p1 == '"') {
+ *p2 = '\\';
+ p2++;
+ }
+
+ *p2 = *p1;
+
+ p1++;
+ p2++;
+ }
+
+ /* Terminate the string */
+ newstr[newlen] = '\0';
+
+ return newstr;
+}
+
+/***********************************************************************
+ *
+ * imap_is_bchar()
+ *
+ * Portable test of whether the specified char is a "bchar" as defined in the
+ * grammar of RFC-5092.
+ */
+static bool imap_is_bchar(char ch)
+{
+ switch(ch) {
+ /* bchar */
+ case ':': case '@': case '/':
+ /* bchar -> achar */
+ case '&': case '=':
+ /* bchar -> achar -> uchar -> unreserved */
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
+ case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
+ case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
+ case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
+ case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
+ case 'v': case 'w': case 'x': case 'y': case 'z':
+ case '-': case '.': case '_': case '~':
+ /* bchar -> achar -> uchar -> sub-delims-sh */
+ case '!': case '$': case '\'': case '(': case ')': case '*':
+ case '+': case ',':
+ /* bchar -> achar -> uchar -> pct-encoded */
+ case '%': /* HEXDIG chars are already included above */
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/***********************************************************************
+ *
+ * imap_parse_url_options()
+ *
+ * Parse the URL login options.
+ */
+static CURLcode imap_parse_url_options(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ const char *options = conn->options;
+ const char *ptr = options;
+ bool reset = TRUE;
+
+ while(ptr && *ptr) {
+ const char *key = ptr;
+
+ while(*ptr && *ptr != '=')
+ ptr++;
+
+ if(strnequal(key, "AUTH", 4)) {
+ size_t len = 0;
+ const char *value = ++ptr;
+
+ if(reset) {
+ reset = FALSE;
+ imapc->preftype = IMAP_TYPE_NONE;
+ imapc->prefmech = SASL_AUTH_NONE;
+ }
+
+ while(*ptr && *ptr != ';') {
+ ptr++;
+ len++;
+ }
+
+ if(strnequal(value, "*", len)) {
+ imapc->preftype = IMAP_TYPE_ANY;
+ imapc->prefmech = SASL_AUTH_ANY;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_LOGIN, len)) {
+ imapc->preftype = IMAP_TYPE_SASL;
+ imapc->prefmech |= SASL_MECH_LOGIN;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_PLAIN, len)) {
+ imapc->preftype = IMAP_TYPE_SASL;
+ imapc->prefmech |= SASL_MECH_PLAIN;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_CRAM_MD5, len)) {
+ imapc->preftype = IMAP_TYPE_SASL;
+ imapc->prefmech |= SASL_MECH_CRAM_MD5;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_DIGEST_MD5, len)) {
+ imapc->preftype = IMAP_TYPE_SASL;
+ imapc->prefmech |= SASL_MECH_DIGEST_MD5;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_GSSAPI, len)) {
+ imapc->preftype = IMAP_TYPE_SASL;
+ imapc->prefmech |= SASL_MECH_GSSAPI;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_NTLM, len)) {
+ imapc->preftype = IMAP_TYPE_SASL;
+ imapc->prefmech |= SASL_MECH_NTLM;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_XOAUTH2, len)) {
+ imapc->preftype = IMAP_TYPE_SASL;
+ imapc->prefmech |= SASL_MECH_XOAUTH2;
+ }
+
+ if(*ptr == ';')
+ ptr++;
+ }
+ else
+ result = CURLE_URL_MALFORMAT;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_parse_url_path()
+ *
+ * Parse the URL path into separate path components.
+ *
+ */
+static CURLcode imap_parse_url_path(struct connectdata *conn)
+{
+ /* The imap struct is already initialised in imap_connect() */
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ const char *begin = data->state.path;
+ const char *ptr = begin;
+
+ /* See how much of the URL is a valid path and decode it */
+ while(imap_is_bchar(*ptr))
+ ptr++;
+
+ if(ptr != begin) {
+ /* Remove the trailing slash if present */
+ const char *end = ptr;
+ if(end > begin && end[-1] == '/')
+ end--;
+
+ result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL,
+ TRUE);
+ if(result)
+ return result;
+ }
+ else
+ imap->mailbox = NULL;
+
+ /* There can be any number of parameters in the form ";NAME=VALUE" */
+ while(*ptr == ';') {
+ char *name;
+ char *value;
+ size_t valuelen;
+
+ /* Find the length of the name parameter */
+ begin = ++ptr;
+ while(*ptr && *ptr != '=')
+ ptr++;
+
+ if(!*ptr)
+ return CURLE_URL_MALFORMAT;
+
+ /* Decode the name parameter */
+ result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE);
+ if(result)
+ return result;
+
+ /* Find the length of the value parameter */
+ begin = ++ptr;
+ while(imap_is_bchar(*ptr))
+ ptr++;
+
+ /* Decode the value parameter */
+ result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE);
+ if(result) {
+ Curl_safefree(name);
+ return result;
+ }
+
+ DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value));
+
+ /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and
+ PARTIAL) stripping of the trailing slash character if it is present.
+
+ Note: Unknown parameters trigger a URL_MALFORMAT error. */
+ if(Curl_raw_equal(name, "UIDVALIDITY") && !imap->uidvalidity) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->uidvalidity = value;
+ value = NULL;
+ }
+ else if(Curl_raw_equal(name, "UID") && !imap->uid) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->uid = value;
+ value = NULL;
+ }
+ else if(Curl_raw_equal(name, "SECTION") && !imap->section) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->section = value;
+ value = NULL;
+ }
+ else if(Curl_raw_equal(name, "PARTIAL") && !imap->partial) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->partial = value;
+ value = NULL;
+ }
+ else {
+ Curl_safefree(name);
+ Curl_safefree(value);
+
+ return CURLE_URL_MALFORMAT;
+ }
+
+ Curl_safefree(name);
+ Curl_safefree(value);
+ }
+
+ /* Does the URL contain a query parameter? Only valid when we have a mailbox
+ and no UID as per RFC-5092 */
+ if(imap->mailbox && !imap->uid && *ptr == '?') {
+ /* Find the length of the query parameter */
+ begin = ++ptr;
+ while(imap_is_bchar(*ptr))
+ ptr++;
+
+ /* Decode the query parameter */
+ result = Curl_urldecode(data, begin, ptr - begin, &imap->query, NULL,
+ TRUE);
+ if(result)
+ return result;
+ }
+
+ /* Any extra stuff at the end of the URL is an error */
+ if(*ptr)
+ return CURLE_URL_MALFORMAT;
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * imap_parse_custom_request()
+ *
+ * Parse the custom request.
+ */
+static CURLcode imap_parse_custom_request(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct IMAP *imap = data->req.protop;
+ const char *custom = data->set.str[STRING_CUSTOMREQUEST];
+
+ if(custom) {
+ /* URL decode the custom request */
+ result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE);
+
+ /* Extract the parameters if specified */
+ if(!result) {
+ const char *params = imap->custom;
+
+ while(*params && *params != ' ')
+ params++;
+
+ if(*params) {
+ imap->custom_params = strdup(params);
+ imap->custom[params - imap->custom] = '\0';
+
+ if(!imap->custom_params)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * imap_calc_sasl_details()
+ *
+ * Calculate the required login details for SASL authentication.
+ */
+static CURLcode imap_calc_sasl_details(struct connectdata *conn,
+ const char **mech,
+ char **initresp, size_t *len,
+ imapstate *state1, imapstate *state2)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct imap_conn *imapc = &conn->proto.imapc;
+
+ /* Calculate the supported authentication mechanism, by decreasing order of
+ security, as well as the initial response where appropriate */
+#if defined(USE_WINDOWS_SSPI)
+ if((imapc->authmechs & SASL_MECH_GSSAPI) &&
+ (imapc->prefmech & SASL_MECH_GSSAPI)) {
+ imapc->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
+
+ *mech = SASL_MECH_STRING_GSSAPI;
+ *state1 = IMAP_AUTHENTICATE_GSSAPI;
+ *state2 = IMAP_AUTHENTICATE_GSSAPI_TOKEN;
+ imapc->authused = SASL_MECH_GSSAPI;
+
+ if(imapc->ir_supported || data->set.sasl_ir)
+ result = Curl_sasl_create_gssapi_user_message(data, conn->user,
+ conn->passwd, "imap",
+ imapc->mutual_auth,
+ NULL, &conn->krb5,
+ initresp, len);
+ }
+ else
+#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if((imapc->authmechs & SASL_MECH_DIGEST_MD5) &&
+ (imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
+ *mech = SASL_MECH_STRING_DIGEST_MD5;
+ *state1 = IMAP_AUTHENTICATE_DIGESTMD5;
+ imapc->authused = SASL_MECH_DIGEST_MD5;
+ }
+ else if((imapc->authmechs & SASL_MECH_CRAM_MD5) &&
+ (imapc->prefmech & SASL_MECH_CRAM_MD5)) {
+ *mech = SASL_MECH_STRING_CRAM_MD5;
+ *state1 = IMAP_AUTHENTICATE_CRAMMD5;
+ imapc->authused = SASL_MECH_CRAM_MD5;
+ }
+ else
+#endif
+#ifdef USE_NTLM
+ if((imapc->authmechs & SASL_MECH_NTLM) &&
+ (imapc->prefmech & SASL_MECH_NTLM)) {
+ *mech = SASL_MECH_STRING_NTLM;
+ *state1 = IMAP_AUTHENTICATE_NTLM;
+ *state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG;
+ imapc->authused = SASL_MECH_NTLM;
+
+ if(imapc->ir_supported || data->set.sasl_ir)
+ result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
+ &conn->ntlm,
+ initresp, len);
+ }
+ else
+#endif
+ if(((imapc->authmechs & SASL_MECH_XOAUTH2) &&
+ (imapc->prefmech & SASL_MECH_XOAUTH2) &&
+ (imapc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
+ *mech = SASL_MECH_STRING_XOAUTH2;
+ *state1 = IMAP_AUTHENTICATE_XOAUTH2;
+ *state2 = IMAP_AUTHENTICATE_FINAL;
+ imapc->authused = SASL_MECH_XOAUTH2;
+
+ if(imapc->ir_supported || data->set.sasl_ir)
+ result = Curl_sasl_create_xoauth2_message(data, conn->user,
+ conn->xoauth2_bearer,
+ initresp, len);
+ }
+ else if((imapc->authmechs & SASL_MECH_LOGIN) &&
+ (imapc->prefmech & SASL_MECH_LOGIN)) {
+ *mech = SASL_MECH_STRING_LOGIN;
+ *state1 = IMAP_AUTHENTICATE_LOGIN;
+ *state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD;
+ imapc->authused = SASL_MECH_LOGIN;
+
+ if(imapc->ir_supported || data->set.sasl_ir)
+ result = Curl_sasl_create_login_message(data, conn->user, initresp, len);
+ }
+ else if((imapc->authmechs & SASL_MECH_PLAIN) &&
+ (imapc->prefmech & SASL_MECH_PLAIN)) {
+ *mech = SASL_MECH_STRING_PLAIN;
+ *state1 = IMAP_AUTHENTICATE_PLAIN;
+ *state2 = IMAP_AUTHENTICATE_FINAL;
+ imapc->authused = SASL_MECH_PLAIN;
+
+ if(imapc->ir_supported || data->set.sasl_ir)
+ result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
+ initresp, len);
+ }
+
+ return result;
+}
+
+#endif /* CURL_DISABLE_IMAP */
diff --git a/external/libcurl_android/jni/libcurl/lib/imap.h b/external/libcurl_android/jni/libcurl/lib/imap.h
new file mode 100755
index 00000000..768fc4b8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/imap.h
@@ -0,0 +1,111 @@
+#ifndef HEADER_CURL_IMAP_H
+#define HEADER_CURL_IMAP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "pingpong.h"
+
+/****************************************************************************
+ * IMAP unique setup
+ ***************************************************************************/
+typedef enum {
+ IMAP_STOP, /* do nothing state, stops the state machine */
+ IMAP_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ IMAP_CAPABILITY,
+ IMAP_STARTTLS,
+ IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ IMAP_AUTHENTICATE_PLAIN,
+ IMAP_AUTHENTICATE_LOGIN,
+ IMAP_AUTHENTICATE_LOGIN_PASSWD,
+ IMAP_AUTHENTICATE_CRAMMD5,
+ IMAP_AUTHENTICATE_DIGESTMD5,
+ IMAP_AUTHENTICATE_DIGESTMD5_RESP,
+ IMAP_AUTHENTICATE_NTLM,
+ IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
+ IMAP_AUTHENTICATE_GSSAPI,
+ IMAP_AUTHENTICATE_GSSAPI_TOKEN,
+ IMAP_AUTHENTICATE_GSSAPI_NO_DATA,
+ IMAP_AUTHENTICATE_XOAUTH2,
+ IMAP_AUTHENTICATE_CANCEL,
+ IMAP_AUTHENTICATE_FINAL,
+ IMAP_LOGIN,
+ IMAP_LIST,
+ IMAP_SELECT,
+ IMAP_FETCH,
+ IMAP_FETCH_FINAL,
+ IMAP_APPEND,
+ IMAP_APPEND_FINAL,
+ IMAP_SEARCH,
+ IMAP_LOGOUT,
+ IMAP_LAST /* never used */
+} imapstate;
+
+/* This IMAP struct is used in the SessionHandle. All IMAP data that is
+ connection-oriented must be in imap_conn to properly deal with the fact that
+ perhaps the SessionHandle is changed between the times the connection is
+ used. */
+struct IMAP {
+ curl_pp_transfer transfer;
+ char *mailbox; /* Mailbox to select */
+ char *uidvalidity; /* UIDVALIDITY to check in select */
+ char *uid; /* Message UID to fetch */
+ char *section; /* Message SECTION to fetch */
+ char *partial; /* Message PARTIAL to fetch */
+ char *query; /* Query to search for */
+ char *custom; /* Custom request */
+ char *custom_params; /* Parameters for the custom request */
+};
+
+/* imap_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct imap_conn {
+ struct pingpong pp;
+ imapstate state; /* Always use imap.c:state() to change state! */
+ bool ssldone; /* Is connect() over SSL done? */
+ unsigned int authmechs; /* Accepted authentication mechanisms */
+ unsigned int preftype; /* Preferred authentication type */
+ unsigned int prefmech; /* Preferred authentication mechanism */
+ unsigned int authused; /* Auth mechanism used for the connection */
+ int cmdid; /* Last used command ID */
+ char resptag[5]; /* Response tag to wait for */
+ bool tls_supported; /* StartTLS capability supported by server */
+ bool login_disabled; /* LOGIN command disabled by server */
+ bool ir_supported; /* Initial response supported by server */
+ bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
+ char *mailbox; /* The last selected mailbox */
+ char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
+};
+
+extern const struct Curl_handler Curl_handler_imap;
+extern const struct Curl_handler Curl_handler_imaps;
+
+/* Authentication type flags */
+#define IMAP_TYPE_CLEARTEXT (1 << 0)
+#define IMAP_TYPE_SASL (1 << 1)
+
+/* Authentication type values */
+#define IMAP_TYPE_NONE 0
+#define IMAP_TYPE_ANY ~0U
+
+#endif /* HEADER_CURL_IMAP_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/inet_ntop.c b/external/libcurl_android/jni/libcurl/lib/inet_ntop.c
new file mode 100755
index 00000000..c3271500
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/inet_ntop.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 1996-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Original code by Paul Vixie. "curlified" by Gisle Vanem.
+ */
+
+#include "curl_setup.h"
+
+#ifndef HAVE_INET_NTOP
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "inet_ntop.h"
+
+#define IN6ADDRSZ 16
+#define INADDRSZ 4
+#define INT16SZ 2
+
+/*
+ * Format an IPv4 address, more or less like inet_ntoa().
+ *
+ * Returns `dst' (as a const)
+ * Note:
+ * - uses no statics
+ * - takes a unsigned char* not an in_addr as input
+ */
+static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
+{
+ char tmp[sizeof "255.255.255.255"];
+ size_t len;
+
+ DEBUGASSERT(size >= 16);
+
+ tmp[0] = '\0';
+ (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
+ ((int)((unsigned char)src[0])) & 0xff,
+ ((int)((unsigned char)src[1])) & 0xff,
+ ((int)((unsigned char)src[2])) & 0xff,
+ ((int)((unsigned char)src[3])) & 0xff);
+
+ len = strlen(tmp);
+ if(len == 0 || len >= size) {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return dst;
+}
+
+#ifdef ENABLE_IPV6
+/*
+ * Convert IPv6 binary address into presentation (printable) format.
+ */
+static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+ char *tp;
+ struct {
+ long base;
+ long len;
+ } best, cur;
+ unsigned long words[IN6ADDRSZ / INT16SZ];
+ int i;
+
+ /* Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof(words));
+ for(i = 0; i < IN6ADDRSZ; i++)
+ words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
+
+ best.base = -1;
+ cur.base = -1;
+ best.len = 0;
+ cur.len = 0;
+
+ for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+ if(words[i] == 0) {
+ if(cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ }
+ else if(cur.base != -1) {
+ if(best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
+ best = cur;
+ if(best.base != -1 && best.len < 2)
+ best.base = -1;
+ /* Format the result. */
+ tp = tmp;
+ for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if(best.base != -1 && i >= best.base && i < (best.base + best.len)) {
+ if(i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+
+ /* Are we following an initial run of 0x00s or any real hex?
+ */
+ if(i != 0)
+ *tp++ = ':';
+
+ /* Is this address an encapsulated IPv4?
+ */
+ if(i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+ if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += snprintf(tp, 5, "%lx", words[i]);
+ }
+
+ /* Was it a trailing run of 0x00's?
+ */
+ if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /* Check for overflow, copy, and we're done.
+ */
+ if((size_t)(tp - tmp) > size) {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return dst;
+}
+#endif /* ENABLE_IPV6 */
+
+/*
+ * Convert a network format address to presentation format.
+ *
+ * Returns pointer to presentation format address (`buf').
+ * Returns NULL on error and errno set with the specific
+ * error, EAFNOSUPPORT or ENOSPC.
+ *
+ * On Windows we store the error in the thread errno, not
+ * in the winsock error code. This is to avoid losing the
+ * actual last winsock error. So use macro ERRNO to fetch the
+ * errno this function sets when returning NULL, not SOCKERRNO.
+ */
+char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
+{
+ switch (af) {
+ case AF_INET:
+ return inet_ntop4((const unsigned char*)src, buf, size);
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ return inet_ntop6((const unsigned char*)src, buf, size);
+#endif
+ default:
+ SET_ERRNO(EAFNOSUPPORT);
+ return NULL;
+ }
+}
+#endif /* HAVE_INET_NTOP */
diff --git a/external/libcurl_android/jni/libcurl/lib/inet_ntop.h b/external/libcurl_android/jni/libcurl/lib/inet_ntop.h
new file mode 100755
index 00000000..db28ed80
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/inet_ntop.h
@@ -0,0 +1,38 @@
+#ifndef HEADER_CURL_INET_NTOP_H
+#define HEADER_CURL_INET_NTOP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
+
+#ifdef HAVE_INET_NTOP
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#define Curl_inet_ntop(af,addr,buf,size) \
+ inet_ntop(af,addr,buf,(curl_socklen_t)size)
+#endif
+
+#endif /* HEADER_CURL_INET_NTOP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/inet_pton.c b/external/libcurl_android/jni/libcurl/lib/inet_pton.c
new file mode 100755
index 00000000..f50b365d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/inet_pton.c
@@ -0,0 +1,234 @@
+/* This is from the BIND 4.9.4 release, modified to compile by itself */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "curl_setup.h"
+
+#ifndef HAVE_INET_PTON
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "inet_pton.h"
+
+#define IN6ADDRSZ 16
+#define INADDRSZ 4
+#define INT16SZ 2
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, unsigned char *dst);
+#ifdef ENABLE_IPV6
+static int inet_pton6(const char *src, unsigned char *dst);
+#endif
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * notice:
+ * On Windows we store the error in the thread errno, not
+ * in the winsock error code. This is to avoid losing the
+ * actual last winsock error. So use macro ERRNO to fetch the
+ * errno this function sets when returning (-1), not SOCKERRNO.
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+Curl_inet_pton(int af, const char *src, void *dst)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, (unsigned char *)dst));
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ return (inet_pton6(src, (unsigned char *)dst));
+#endif
+ default:
+ SET_ERRNO(EAFNOSUPPORT);
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ tp = tmp;
+ *tp = 0;
+ while((ch = *src++) != '\0') {
+ const char *pch;
+
+ if((pch = strchr(digits, ch)) != NULL) {
+ unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
+
+ if(saw_digit && *tp == 0)
+ return (0);
+ if(val > 255)
+ return (0);
+ *tp = (unsigned char)val;
+ if(! saw_digit) {
+ if(++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ }
+ else if(ch == '.' && saw_digit) {
+ if(octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ }
+ else
+ return (0);
+ }
+ if(octets < 4)
+ return (0);
+ memcpy(dst, tmp, INADDRSZ);
+ return (1);
+}
+
+#ifdef ENABLE_IPV6
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ size_t val;
+
+ memset((tp = tmp), 0, IN6ADDRSZ);
+ endp = tp + IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if(*src == ':')
+ if(*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while((ch = *src++) != '\0') {
+ const char *pch;
+
+ if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if(pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if(++saw_xdigit > 4)
+ return (0);
+ continue;
+ }
+ if(ch == ':') {
+ curtok = src;
+ if(!saw_xdigit) {
+ if(colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if(tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if(saw_xdigit) {
+ if(tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if(colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const ssize_t n = tp - colonp;
+ ssize_t i;
+
+ if(tp == endp)
+ return (0);
+ for(i = 1; i <= n; i++) {
+ *(endp - i) = *(colonp + n - i);
+ *(colonp + n - i) = 0;
+ }
+ tp = endp;
+ }
+ if(tp != endp)
+ return (0);
+ memcpy(dst, tmp, IN6ADDRSZ);
+ return (1);
+}
+#endif /* ENABLE_IPV6 */
+
+#endif /* HAVE_INET_PTON */
diff --git a/external/libcurl_android/jni/libcurl/lib/inet_pton.h b/external/libcurl_android/jni/libcurl/lib/inet_pton.h
new file mode 100755
index 00000000..43c54914
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/inet_pton.h
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_INET_PTON_H
+#define HEADER_CURL_INET_PTON_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+int Curl_inet_pton(int, const char *, void *);
+
+#ifdef HAVE_INET_PTON
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
+#endif
+
+#endif /* HEADER_CURL_INET_PTON_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/krb5.c b/external/libcurl_android/jni/libcurl/lib/krb5.c
new file mode 100755
index 00000000..7e82a680
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/krb5.c
@@ -0,0 +1,342 @@
+/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c
+ *
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2013 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * Copyright (c) 2004 - 2012 Daniel Stenberg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+#ifdef HAVE_GSSAPI
+
+#ifdef HAVE_OLD_GSSMIT
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#define NCOMPAT 1
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "urldata.h"
+#include "curl_base64.h"
+#include "ftp.h"
+#include "curl_gssapi.h"
+#include "sendf.h"
+#include "curl_sec.h"
+#include "curl_memory.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#define LOCAL_ADDR (&conn->local_addr)
+#define REMOTE_ADDR conn->ip_addr->ai_addr
+
+static int
+krb5_init(void *app_data)
+{
+ gss_ctx_id_t *context = app_data;
+ /* Make sure our context is initialized for krb5_end. */
+ *context = GSS_C_NO_CONTEXT;
+ return 0;
+}
+
+static int
+krb5_check_prot(void *app_data, int level)
+{
+ (void)app_data; /* unused */
+ if(level == PROT_CONFIDENTIAL)
+ return -1;
+ return 0;
+}
+
+static int
+krb5_decode(void *app_data, void *buf, int len,
+ int level UNUSED_PARAM,
+ struct connectdata *conn UNUSED_PARAM)
+{
+ gss_ctx_id_t *context = app_data;
+ OM_uint32 maj, min;
+ gss_buffer_desc enc, dec;
+
+ (void)level;
+ (void)conn;
+
+ enc.value = buf;
+ enc.length = len;
+ maj = gss_unseal(&min, *context, &enc, &dec, NULL, NULL);
+ if(maj != GSS_S_COMPLETE) {
+ if(len >= 4)
+ strcpy(buf, "599 ");
+ return -1;
+ }
+
+ memcpy(buf, dec.value, dec.length);
+ len = curlx_uztosi(dec.length);
+ gss_release_buffer(&min, &dec);
+
+ return len;
+}
+
+static int
+krb5_overhead(void *app_data, int level, int len)
+{
+ /* no arguments are used */
+ (void)app_data;
+ (void)level;
+ (void)len;
+ return 0;
+}
+
+static int
+krb5_encode(void *app_data, const void *from, int length, int level, void **to,
+ struct connectdata *conn UNUSED_PARAM)
+{
+ gss_ctx_id_t *context = app_data;
+ gss_buffer_desc dec, enc;
+ OM_uint32 maj, min;
+ int state;
+ int len;
+
+ /* shut gcc up */
+ conn = NULL;
+
+ /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
+ * libraries modify the input buffer in gss_seal()
+ */
+ dec.value = (void*)from;
+ dec.length = length;
+ maj = gss_seal(&min, *context,
+ level == PROT_PRIVATE,
+ GSS_C_QOP_DEFAULT,
+ &dec, &state, &enc);
+
+ if(maj != GSS_S_COMPLETE)
+ return -1;
+
+ /* malloc a new buffer, in case gss_release_buffer doesn't work as
+ expected */
+ *to = malloc(enc.length);
+ if(!*to)
+ return -1;
+ memcpy(*to, enc.value, enc.length);
+ len = curlx_uztosi(enc.length);
+ gss_release_buffer(&min, &enc);
+ return len;
+}
+
+static int
+krb5_auth(void *app_data, struct connectdata *conn)
+{
+ int ret = AUTH_OK;
+ char *p;
+ const char *host = conn->host.name;
+ ssize_t nread;
+ curl_socklen_t l = sizeof(conn->local_addr);
+ struct SessionHandle *data = conn->data;
+ CURLcode result;
+ const char *service = "ftp", *srv_host = "host";
+ gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp;
+ OM_uint32 maj, min;
+ gss_name_t gssname;
+ gss_ctx_id_t *context = app_data;
+ struct gss_channel_bindings_struct chan;
+ size_t base64_sz = 0;
+
+ if(getsockname(conn->sock[FIRSTSOCKET],
+ (struct sockaddr *)LOCAL_ADDR, &l) < 0)
+ perror("getsockname()");
+
+ chan.initiator_addrtype = GSS_C_AF_INET;
+ chan.initiator_address.length = l - 4;
+ chan.initiator_address.value =
+ &((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr;
+ chan.acceptor_addrtype = GSS_C_AF_INET;
+ chan.acceptor_address.length = l - 4;
+ chan.acceptor_address.value =
+ &((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr;
+ chan.application_data.length = 0;
+ chan.application_data.value = NULL;
+
+ /* this loop will execute twice (once for service, once for host) */
+ for(;;) {
+ /* this really shouldn't be repeated here, but can't help it */
+ if(service == srv_host) {
+ result = Curl_ftpsendf(conn, "AUTH GSSAPI");
+
+ if(result)
+ return -2;
+ if(Curl_GetFTPResponse(&nread, conn, NULL))
+ return -1;
+
+ if(data->state.buffer[0] != '3')
+ return -1;
+ }
+
+ input_buffer.value = data->state.buffer;
+ input_buffer.length = snprintf(input_buffer.value, BUFSIZE, "%s@%s",
+ service, host);
+ maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE,
+ &gssname);
+ if(maj != GSS_S_COMPLETE) {
+ gss_release_name(&min, &gssname);
+ if(service == srv_host) {
+ Curl_failf(data, "Error importing service name %s",
+ input_buffer.value);
+ return AUTH_ERROR;
+ }
+ service = srv_host;
+ continue;
+ }
+ /* We pass NULL as |output_name_type| to avoid a leak. */
+ gss_display_name(&min, gssname, &output_buffer, NULL);
+ Curl_infof(data, "Trying against %s\n", output_buffer.value);
+ gssresp = GSS_C_NO_BUFFER;
+ *context = GSS_C_NO_CONTEXT;
+
+ do {
+ /* Release the buffer at each iteration to avoid leaking: the first time
+ we are releasing the memory from gss_display_name. The last item is
+ taken care by a final gss_release_buffer. */
+ gss_release_buffer(&min, &output_buffer);
+ ret = AUTH_OK;
+ maj = Curl_gss_init_sec_context(data,
+ &min,
+ context,
+ gssname,
+ &Curl_krb5_mech_oid,
+ &chan,
+ gssresp,
+ &output_buffer,
+ NULL);
+
+ if(gssresp) {
+ free(_gssresp.value);
+ gssresp = NULL;
+ }
+
+ if(GSS_ERROR(maj)) {
+ Curl_infof(data, "Error creating security context\n");
+ ret = AUTH_ERROR;
+ break;
+ }
+
+ if(output_buffer.length != 0) {
+ result = Curl_base64_encode(data, (char *)output_buffer.value,
+ output_buffer.length, &p, &base64_sz);
+ if(result) {
+ Curl_infof(data,"base64-encoding: %s\n", curl_easy_strerror(result));
+ ret = AUTH_CONTINUE;
+ break;
+ }
+
+ result = Curl_ftpsendf(conn, "ADAT %s", p);
+
+ free(p);
+
+ if(result) {
+ ret = -2;
+ break;
+ }
+
+ if(Curl_GetFTPResponse(&nread, conn, NULL)) {
+ ret = -1;
+ break;
+ }
+
+ if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') {
+ Curl_infof(data, "Server didn't accept auth data\n");
+ ret = AUTH_ERROR;
+ break;
+ }
+
+ p = data->state.buffer + 4;
+ p = strstr(p, "ADAT=");
+ if(p) {
+ result = Curl_base64_decode(p + 5,
+ (unsigned char **)&_gssresp.value,
+ &_gssresp.length);
+ if(result) {
+ Curl_failf(data,"base64-decoding: %s", curl_easy_strerror(result));
+ ret = AUTH_CONTINUE;
+ break;
+ }
+ }
+
+ gssresp = &_gssresp;
+ }
+ } while(maj == GSS_S_CONTINUE_NEEDED);
+
+ gss_release_name(&min, &gssname);
+ gss_release_buffer(&min, &output_buffer);
+
+ if(gssresp)
+ free(_gssresp.value);
+
+ if(ret == AUTH_OK || service == srv_host)
+ return ret;
+
+ service = srv_host;
+ }
+ return ret;
+}
+
+static void krb5_end(void *app_data)
+{
+ OM_uint32 min;
+ gss_ctx_id_t *context = app_data;
+ if(*context != GSS_C_NO_CONTEXT) {
+#ifdef DEBUGBUILD
+ OM_uint32 maj =
+#endif
+ gss_delete_sec_context(&min, context, GSS_C_NO_BUFFER);
+ DEBUGASSERT(maj == GSS_S_COMPLETE);
+ }
+}
+
+struct Curl_sec_client_mech Curl_krb5_client_mech = {
+ "GSSAPI",
+ sizeof(gss_ctx_id_t),
+ krb5_init,
+ krb5_auth,
+ krb5_end,
+ krb5_check_prot,
+ krb5_overhead,
+ krb5_encode,
+ krb5_decode
+};
+
+#endif /* HAVE_GSSAPI */
+#endif /* CURL_DISABLE_FTP */
diff --git a/external/libcurl_android/jni/libcurl/lib/ldap.c b/external/libcurl_android/jni/libcurl/lib/ldap.c
new file mode 100755
index 00000000..ae484488
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/ldap.c
@@ -0,0 +1,709 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP)
+
+/*
+ * Notice that USE_OPENLDAP is only a source code selection switch. When
+ * libcurl is built with USE_OPENLDAP defined the libcurl source code that
+ * gets compiled is the code from openldap.c, otherwise the code that gets
+ * compiled is the code from ldap.c.
+ *
+ * When USE_OPENLDAP is defined a recent version of the OpenLDAP library
+ * might be required for compilation and runtime. In order to use ancient
+ * OpenLDAP library versions, USE_OPENLDAP shall not be defined.
+ */
+
+#ifdef CURL_LDAP_WIN /* Use Windows LDAP implementation. */
+# include <winldap.h>
+# ifndef LDAP_VENDOR_NAME
+# error Your Platform SDK is NOT sufficient for LDAP support! \
+ Update your Platform SDK, or disable LDAP support!
+# else
+# include <winber.h>
+# endif
+#else
+# define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */
+# ifdef HAVE_LBER_H
+# include <lber.h>
+# endif
+# include <ldap.h>
+# if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H))
+# include <ldap_ssl.h>
+# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "sendf.h"
+#include "escape.h"
+#include "progress.h"
+#include "transfer.h"
+#include "strequal.h"
+#include "strtok.h"
+#include "curl_ldap.h"
+#include "curl_memory.h"
+#include "curl_base64.h"
+#include "rawstr.h"
+#include "connect.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "memdebug.h"
+
+#ifndef HAVE_LDAP_URL_PARSE
+
+/* Use our own implementation. */
+
+typedef struct {
+ char *lud_host;
+ int lud_port;
+ char *lud_dn;
+ char **lud_attrs;
+ int lud_scope;
+ char *lud_filter;
+ char **lud_exts;
+ size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the
+ "real" struct so can only be used in code
+ without HAVE_LDAP_URL_PARSE defined */
+} CURL_LDAPURLDesc;
+
+#undef LDAPURLDesc
+#define LDAPURLDesc CURL_LDAPURLDesc
+
+static int _ldap_url_parse (const struct connectdata *conn,
+ LDAPURLDesc **ludp);
+static void _ldap_free_urldesc (LDAPURLDesc *ludp);
+
+#undef ldap_free_urldesc
+#define ldap_free_urldesc _ldap_free_urldesc
+#endif
+
+#ifdef DEBUG_LDAP
+ #define LDAP_TRACE(x) do { \
+ _ldap_trace ("%u: ", __LINE__); \
+ _ldap_trace x; \
+ } WHILE_FALSE
+
+ static void _ldap_trace (const char *fmt, ...);
+#else
+ #define LDAP_TRACE(x) Curl_nop_stmt
+#endif
+
+
+static CURLcode Curl_ldap(struct connectdata *conn, bool *done);
+
+/*
+ * LDAP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldap = {
+ "LDAP", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ Curl_ldap, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_LDAP, /* defport */
+ CURLPROTO_LDAP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef HAVE_LDAP_SSL
+/*
+ * LDAPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldaps = {
+ "LDAPS", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ Curl_ldap, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_LDAPS, /* defport */
+ CURLPROTO_LDAPS, /* protocol */
+ PROTOPT_SSL /* flags */
+};
+#endif
+
+
+static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
+{
+ CURLcode status = CURLE_OK;
+ int rc = 0;
+ LDAP *server = NULL;
+ LDAPURLDesc *ludp = NULL;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entryIterator;
+ int num = 0;
+ struct SessionHandle *data=conn->data;
+ int ldap_proto = LDAP_VERSION3;
+ int ldap_ssl = 0;
+ char *val_b64 = NULL;
+ size_t val_b64_sz = 0;
+ curl_off_t dlsize = 0;
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+ struct timeval ldap_timeout = {10,0}; /* 10 sec connection/search timeout */
+#endif
+
+ *done = TRUE; /* unconditionally */
+ infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
+ LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
+ infof(data, "LDAP local: %s\n", data->change.url);
+
+#ifdef HAVE_LDAP_URL_PARSE
+ rc = ldap_url_parse(data->change.url, &ludp);
+#else
+ rc = _ldap_url_parse(conn, &ludp);
+#endif
+ if(rc != 0) {
+ failf(data, "LDAP local: %s", ldap_err2string(rc));
+ status = CURLE_LDAP_INVALID_URL;
+ goto quit;
+ }
+
+ /* Get the URL scheme ( either ldap or ldaps ) */
+ if(conn->given->flags & PROTOPT_SSL)
+ ldap_ssl = 1;
+ infof(data, "LDAP local: trying to establish %s connection\n",
+ ldap_ssl ? "encrypted" : "cleartext");
+
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+ ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
+#endif
+ ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
+
+ if(ldap_ssl) {
+#ifdef HAVE_LDAP_SSL
+#ifdef CURL_LDAP_WIN
+ /* Win32 LDAP SDK doesn't support insecure mode without CA! */
+ server = ldap_sslinit(conn->host.name, (int)conn->port, 1);
+ ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
+#else
+ int ldap_option;
+ char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
+#if defined(CURL_HAS_NOVELL_LDAPSDK)
+ rc = ldapssl_client_init(NULL, NULL);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc));
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ if(data->set.ssl.verifypeer) {
+ /* Novell SDK supports DER or BASE64 files. */
+ int cert_type = LDAPSSL_CERT_FILETYPE_B64;
+ if((data->set.str[STRING_CERT_TYPE]) &&
+ (Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER")))
+ cert_type = LDAPSSL_CERT_FILETYPE_DER;
+ if(!ldap_ca) {
+ failf(data, "LDAP local: ERROR %s CA cert not set!",
+ (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"));
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ infof(data, "LDAP local: using %s CA cert '%s'\n",
+ (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
+ ldap_ca);
+ rc = ldapssl_add_trusted_cert(ldap_ca, cert_type);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting %s CA cert: %s",
+ (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
+ ldap_err2string(rc));
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ ldap_option = LDAPSSL_VERIFY_SERVER;
+ }
+ else
+ ldap_option = LDAPSSL_VERIFY_NONE;
+ rc = ldapssl_set_verify_mode(ldap_option);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting cert verify mode: %s",
+ ldap_err2string(rc));
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ server = ldapssl_init(conn->host.name, (int)conn->port, 1);
+ if(server == NULL) {
+ failf(data, "LDAP local: Cannot connect to %s:%ld",
+ conn->host.name, conn->port);
+ status = CURLE_COULDNT_CONNECT;
+ goto quit;
+ }
+#elif defined(LDAP_OPT_X_TLS)
+ if(data->set.ssl.verifypeer) {
+ /* OpenLDAP SDK supports BASE64 files. */
+ if((data->set.str[STRING_CERT_TYPE]) &&
+ (!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
+ failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ if(!ldap_ca) {
+ failf(data, "LDAP local: ERROR PEM CA cert not set!");
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca);
+ rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting PEM CA cert: %s",
+ ldap_err2string(rc));
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ ldap_option = LDAP_OPT_X_TLS_DEMAND;
+ }
+ else
+ ldap_option = LDAP_OPT_X_TLS_NEVER;
+
+ rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting cert verify mode: %s",
+ ldap_err2string(rc));
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+ server = ldap_init(conn->host.name, (int)conn->port);
+ if(server == NULL) {
+ failf(data, "LDAP local: Cannot connect to %s:%ld",
+ conn->host.name, conn->port);
+ status = CURLE_COULDNT_CONNECT;
+ goto quit;
+ }
+ ldap_option = LDAP_OPT_X_TLS_HARD;
+ rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s",
+ ldap_err2string(rc));
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+/*
+ rc = ldap_start_tls_s(server, NULL, NULL);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s",
+ ldap_err2string(rc));
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+ }
+*/
+#else
+ /* we should probably never come up to here since configure
+ should check in first place if we can support LDAP SSL/TLS */
+ failf(data, "LDAP local: SSL/TLS not supported with this version "
+ "of the OpenLDAP toolkit\n");
+ status = CURLE_SSL_CERTPROBLEM;
+ goto quit;
+#endif
+#endif
+#endif /* CURL_LDAP_USE_SSL */
+ }
+ else {
+ server = ldap_init(conn->host.name, (int)conn->port);
+ if(server == NULL) {
+ failf(data, "LDAP local: Cannot connect to %s:%ld",
+ conn->host.name, conn->port);
+ status = CURLE_COULDNT_CONNECT;
+ goto quit;
+ }
+ }
+#ifdef CURL_LDAP_WIN
+ ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
+#endif
+
+ rc = ldap_simple_bind_s(server,
+ conn->bits.user_passwd ? conn->user : NULL,
+ conn->bits.user_passwd ? conn->passwd : NULL);
+ if(!ldap_ssl && rc != 0) {
+ ldap_proto = LDAP_VERSION2;
+ ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
+ rc = ldap_simple_bind_s(server,
+ conn->bits.user_passwd ? conn->user : NULL,
+ conn->bits.user_passwd ? conn->passwd : NULL);
+ }
+ if(rc != 0) {
+ failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
+ status = CURLE_LDAP_CANNOT_BIND;
+ goto quit;
+ }
+
+ rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
+ ludp->lud_filter, ludp->lud_attrs, 0, &result);
+
+ if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) {
+ failf(data, "LDAP remote: %s", ldap_err2string(rc));
+ status = CURLE_LDAP_SEARCH_FAILED;
+ goto quit;
+ }
+
+ for(num = 0, entryIterator = ldap_first_entry(server, result);
+ entryIterator;
+ entryIterator = ldap_next_entry(server, entryIterator), num++) {
+ BerElement *ber = NULL;
+ char *attribute; /*! suspicious that this isn't 'const' */
+ char *dn = ldap_get_dn(server, entryIterator);
+ int i;
+
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)dn, 0);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+
+ dlsize += strlen(dn)+5;
+
+ for(attribute = ldap_first_attribute(server, entryIterator, &ber);
+ attribute;
+ attribute = ldap_next_attribute(server, entryIterator, ber)) {
+ BerValue **vals = ldap_get_values_len(server, entryIterator, attribute);
+
+ if(vals != NULL) {
+ for(i = 0; (vals[i] != NULL); i++) {
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *) attribute, 0);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
+ dlsize += strlen(attribute)+3;
+
+ if((strlen(attribute) > 7) &&
+ (strcmp(";binary",
+ (char *)attribute +
+ (strlen((char *)attribute) - 7)) == 0)) {
+ /* Binary attribute, encode to base64. */
+ CURLcode error = Curl_base64_encode(data,
+ vals[i]->bv_val,
+ vals[i]->bv_len,
+ &val_b64,
+ &val_b64_sz);
+ if(error) {
+ ldap_value_free_len(vals);
+ ldap_memfree(attribute);
+ ldap_memfree(dn);
+ if(ber)
+ ber_free(ber, 0);
+ status = error;
+ goto quit;
+ }
+ if(val_b64_sz > 0) {
+ Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
+ free(val_b64);
+ dlsize += val_b64_sz;
+ }
+ }
+ else {
+ Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val,
+ vals[i]->bv_len);
+ dlsize += vals[i]->bv_len;
+ }
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ dlsize++;
+ }
+
+ /* Free memory used to store values */
+ ldap_value_free_len(vals);
+ }
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ dlsize++;
+ Curl_pgrsSetDownloadCounter(data, dlsize);
+ ldap_memfree(attribute);
+ }
+ ldap_memfree(dn);
+ if(ber)
+ ber_free(ber, 0);
+ }
+
+quit:
+ if(result) {
+ ldap_msgfree(result);
+ LDAP_TRACE (("Received %d entries\n", num));
+ }
+ if(rc == LDAP_SIZELIMIT_EXCEEDED)
+ infof(data, "There are more than %d entries\n", num);
+ if(ludp)
+ ldap_free_urldesc(ludp);
+ if(server)
+ ldap_unbind_s(server);
+#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK)
+ if(ldap_ssl)
+ ldapssl_client_deinit();
+#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
+
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ connclose(conn, "LDAP connection always disable re-use");
+
+ return status;
+}
+
+#ifdef DEBUG_LDAP
+static void _ldap_trace (const char *fmt, ...)
+{
+ static int do_trace = -1;
+ va_list args;
+
+ if(do_trace == -1) {
+ const char *env = getenv("CURL_TRACE");
+ do_trace = (env && strtol(env, NULL, 10) > 0);
+ }
+ if(!do_trace)
+ return;
+
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ va_end (args);
+}
+#endif
+
+#ifndef HAVE_LDAP_URL_PARSE
+
+/*
+ * Return scope-value for a scope-string.
+ */
+static int str2scope (const char *p)
+{
+ if(strequal(p, "one"))
+ return LDAP_SCOPE_ONELEVEL;
+ if(strequal(p, "onetree"))
+ return LDAP_SCOPE_ONELEVEL;
+ if(strequal(p, "base"))
+ return LDAP_SCOPE_BASE;
+ if(strequal(p, "sub"))
+ return LDAP_SCOPE_SUBTREE;
+ if(strequal( p, "subtree"))
+ return LDAP_SCOPE_SUBTREE;
+ return (-1);
+}
+
+/*
+ * Split 'str' into strings separated by commas.
+ * Note: res[] points into 'str'.
+ */
+static char **split_str (char *str)
+{
+ char **res, *lasts, *s;
+ int i;
+
+ for(i = 2, s = strchr(str,','); s; i++)
+ s = strchr(++s,',');
+
+ res = calloc(i, sizeof(char*));
+ if(!res)
+ return NULL;
+
+ for(i = 0, s = strtok_r(str, ",", &lasts); s;
+ s = strtok_r(NULL, ",", &lasts), i++)
+ res[i] = s;
+ return res;
+}
+
+/*
+ * Unescape the LDAP-URL components
+ */
+static bool unescape_elements (void *data, LDAPURLDesc *ludp)
+{
+ int i;
+
+ if(ludp->lud_filter) {
+ ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL);
+ if(!ludp->lud_filter)
+ return FALSE;
+ }
+
+ for(i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) {
+ ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i],
+ 0, NULL);
+ if(!ludp->lud_attrs[i])
+ return FALSE;
+ ludp->lud_attrs_dups++;
+ }
+
+ if(ludp->lud_dn) {
+ char *dn = ludp->lud_dn;
+ char *new_dn = curl_easy_unescape(data, dn, 0, NULL);
+
+ free(dn);
+ ludp->lud_dn = new_dn;
+ if(!new_dn)
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * Break apart the pieces of an LDAP URL.
+ * Syntax:
+ * ldap://<hostname>:<port>/<base_dn>?<attributes>?<scope>?<filter>?<ext>
+ *
+ * <hostname> already known from 'conn->host.name'.
+ * <port> already known from 'conn->remote_port'.
+ * extract the rest from 'conn->data->state.path+1'. All fields are optional.
+ * e.g.
+ * ldap://<hostname>:<port>/?<attributes>?<scope>?<filter>
+ * yields ludp->lud_dn = "".
+ *
+ * Defined in RFC4516 section 2.
+ */
+static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
+{
+ char *p, *q;
+ int i;
+
+ if(!conn->data ||
+ !conn->data->state.path ||
+ conn->data->state.path[0] != '/' ||
+ !checkprefix("LDAP", conn->data->change.url))
+ return LDAP_INVALID_SYNTAX;
+
+ ludp->lud_scope = LDAP_SCOPE_BASE;
+ ludp->lud_port = conn->remote_port;
+ ludp->lud_host = conn->host.name;
+
+ /* parse DN (Distinguished Name).
+ */
+ ludp->lud_dn = strdup(conn->data->state.path+1);
+ if(!ludp->lud_dn)
+ return LDAP_NO_MEMORY;
+
+ p = strchr(ludp->lud_dn, '?');
+ LDAP_TRACE (("DN '%.*s'\n", p ? (size_t)(p-ludp->lud_dn) :
+ strlen(ludp->lud_dn), ludp->lud_dn));
+
+ if(!p)
+ goto success;
+
+ *p++ = '\0';
+
+ /* parse attributes. skip "??".
+ */
+ q = strchr(p, '?');
+ if(q)
+ *q++ = '\0';
+
+ if(*p && *p != '?') {
+ ludp->lud_attrs = split_str(p);
+ if(!ludp->lud_attrs)
+ return LDAP_NO_MEMORY;
+
+ for(i = 0; ludp->lud_attrs[i]; i++)
+ LDAP_TRACE (("attr[%d] '%s'\n", i, ludp->lud_attrs[i]));
+ }
+
+ p = q;
+ if(!p)
+ goto success;
+
+ /* parse scope. skip "??"
+ */
+ q = strchr(p, '?');
+ if(q)
+ *q++ = '\0';
+
+ if(*p && *p != '?') {
+ ludp->lud_scope = str2scope(p);
+ if(ludp->lud_scope == -1) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ LDAP_TRACE (("scope %d\n", ludp->lud_scope));
+ }
+
+ p = q;
+ if(!p)
+ goto success;
+
+ /* parse filter
+ */
+ q = strchr(p, '?');
+ if(q)
+ *q++ = '\0';
+ if(!*p) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ ludp->lud_filter = p;
+ LDAP_TRACE (("filter '%s'\n", ludp->lud_filter));
+
+ success:
+ if(!unescape_elements(conn->data, ludp))
+ return LDAP_NO_MEMORY;
+ return LDAP_SUCCESS;
+}
+
+static int _ldap_url_parse (const struct connectdata *conn,
+ LDAPURLDesc **ludpp)
+{
+ LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
+ int rc;
+
+ *ludpp = NULL;
+ if(!ludp)
+ return LDAP_NO_MEMORY;
+
+ rc = _ldap_url_parse2 (conn, ludp);
+ if(rc != LDAP_SUCCESS) {
+ _ldap_free_urldesc(ludp);
+ ludp = NULL;
+ }
+ *ludpp = ludp;
+ return (rc);
+}
+
+static void _ldap_free_urldesc (LDAPURLDesc *ludp)
+{
+ size_t i;
+
+ if(!ludp)
+ return;
+
+ if(ludp->lud_dn)
+ free(ludp->lud_dn);
+
+ if(ludp->lud_filter)
+ free(ludp->lud_filter);
+
+ if(ludp->lud_attrs) {
+ for(i = 0; i < ludp->lud_attrs_dups; i++)
+ free(ludp->lud_attrs[i]);
+ free(ludp->lud_attrs);
+ }
+
+ free (ludp);
+}
+#endif /* !HAVE_LDAP_URL_PARSE */
+#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */
diff --git a/external/libcurl_android/jni/libcurl/lib/libcurl.rc b/external/libcurl_android/jni/libcurl/lib/libcurl.rc
new file mode 100755
index 00000000..47b944ac
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/libcurl.rc
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include <winver.h>
+#include "../include/curl/curlver.h"
+
+LANGUAGE 0x09,0x01
+
+#define RC_VERSION LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RC_VERSION
+ PRODUCTVERSION RC_VERSION
+ FILEFLAGSMASK 0x3fL
+#if defined(DEBUGBUILD) || defined(_DEBUG)
+ FILEFLAGS 1
+#else
+ FILEFLAGS 0
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "The cURL library, http://curl.haxx.se/\0"
+ VALUE "FileDescription", "libcurl Shared Library\0"
+ VALUE "FileVersion", LIBCURL_VERSION "\0"
+ VALUE "InternalName", "libcurl\0"
+ VALUE "OriginalFilename", "libcurl.dll\0"
+ VALUE "ProductName", "The cURL library\0"
+ VALUE "ProductVersion", LIBCURL_VERSION "\0"
+ VALUE "LegalCopyright", "© " LIBCURL_COPYRIGHT "\0"
+ VALUE "License", "http://curl.haxx.se/docs/copyright.html\0"
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/external/libcurl_android/jni/libcurl/lib/llist.c b/external/libcurl_android/jni/libcurl/lib/llist.c
new file mode 100755
index 00000000..40bb6283
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/llist.c
@@ -0,0 +1,212 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "llist.h"
+#include "curl_memory.h"
+
+/* this must be the last include file */
+#include "memdebug.h"
+
+/*
+ * @unittest: 1300
+ */
+static void
+llist_init(struct curl_llist *l, curl_llist_dtor dtor)
+{
+ l->size = 0;
+ l->dtor = dtor;
+ l->head = NULL;
+ l->tail = NULL;
+}
+
+struct curl_llist *
+Curl_llist_alloc(curl_llist_dtor dtor)
+{
+ struct curl_llist *list;
+
+ list = malloc(sizeof(struct curl_llist));
+ if(!list)
+ return NULL;
+
+ llist_init(list, dtor);
+
+ return list;
+}
+
+/*
+ * Curl_llist_insert_next()
+ *
+ * Inserts a new list element after the given one 'e'. If the given existing
+ * entry is NULL and the list already has elements, the new one will be
+ * inserted first in the list.
+ *
+ * Returns: 1 on success and 0 on failure.
+ *
+ * @unittest: 1300
+ */
+int
+Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
+ const void *p)
+{
+ struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element));
+ if(!ne)
+ return 0;
+
+ ne->ptr = (void *) p;
+ if(list->size == 0) {
+ list->head = ne;
+ list->head->prev = NULL;
+ list->head->next = NULL;
+ list->tail = ne;
+ }
+ else {
+ /* if 'e' is NULL here, we insert the new element first in the list */
+ ne->next = e?e->next:list->head;
+ ne->prev = e;
+ if(!e) {
+ list->head->prev = ne;
+ list->head = ne;
+ }
+ else if(e->next) {
+ e->next->prev = ne;
+ }
+ else {
+ list->tail = ne;
+ }
+ if(e)
+ e->next = ne;
+ }
+
+ ++list->size;
+
+ return 1;
+}
+
+/*
+ * @unittest: 1300
+ */
+int
+Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
+ void *user)
+{
+ if(e == NULL || list->size == 0)
+ return 1;
+
+ if(e == list->head) {
+ list->head = e->next;
+
+ if(list->head == NULL)
+ list->tail = NULL;
+ else
+ e->next->prev = NULL;
+ }
+ else {
+ e->prev->next = e->next;
+ if(!e->next)
+ list->tail = e->prev;
+ else
+ e->next->prev = e->prev;
+ }
+
+ list->dtor(user, e->ptr);
+
+ e->ptr = NULL;
+ e->prev = NULL;
+ e->next = NULL;
+
+ free(e);
+ --list->size;
+
+ return 1;
+}
+
+void
+Curl_llist_destroy(struct curl_llist *list, void *user)
+{
+ if(list) {
+ while(list->size > 0)
+ Curl_llist_remove(list, list->tail, user);
+
+ free(list);
+ }
+}
+
+size_t
+Curl_llist_count(struct curl_llist *list)
+{
+ return list->size;
+}
+
+/*
+ * @unittest: 1300
+ */
+int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
+ struct curl_llist *to_list,
+ struct curl_llist_element *to_e)
+{
+ /* Remove element from list */
+ if(e == NULL || list->size == 0)
+ return 0;
+
+ if(e == list->head) {
+ list->head = e->next;
+
+ if(list->head == NULL)
+ list->tail = NULL;
+ else
+ e->next->prev = NULL;
+ }
+ else {
+ e->prev->next = e->next;
+ if(!e->next)
+ list->tail = e->prev;
+ else
+ e->next->prev = e->prev;
+ }
+
+ --list->size;
+
+ /* Add element to to_list after to_e */
+ if(to_list->size == 0) {
+ to_list->head = e;
+ to_list->head->prev = NULL;
+ to_list->head->next = NULL;
+ to_list->tail = e;
+ }
+ else {
+ e->next = to_e->next;
+ e->prev = to_e;
+ if(to_e->next) {
+ to_e->next->prev = e;
+ }
+ else {
+ to_list->tail = e;
+ }
+ to_e->next = e;
+ }
+
+ ++to_list->size;
+
+ return 1;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/llist.h b/external/libcurl_android/jni/libcurl/lib/llist.h
new file mode 100755
index 00000000..27ddb719
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/llist.h
@@ -0,0 +1,57 @@
+#ifndef HEADER_CURL_LLIST_H
+#define HEADER_CURL_LLIST_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include <stddef.h>
+
+typedef void (*curl_llist_dtor)(void *, void *);
+
+struct curl_llist_element {
+ void *ptr;
+
+ struct curl_llist_element *prev;
+ struct curl_llist_element *next;
+};
+
+struct curl_llist {
+ struct curl_llist_element *head;
+ struct curl_llist_element *tail;
+
+ curl_llist_dtor dtor;
+
+ size_t size;
+};
+
+struct curl_llist *Curl_llist_alloc(curl_llist_dtor);
+int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
+ const void *);
+int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
+ void *);
+size_t Curl_llist_count(struct curl_llist *);
+void Curl_llist_destroy(struct curl_llist *, void *);
+int Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
+ struct curl_llist *, struct curl_llist_element *);
+
+#endif /* HEADER_CURL_LLIST_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/md4.c b/external/libcurl_android/jni/libcurl/lib/md4.c
new file mode 100755
index 00000000..6930e021
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/md4.c
@@ -0,0 +1,282 @@
+/*-
+ Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD4 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#include "curl_setup.h"
+
+/* NSS crypto library does not provide the MD4 hash algorithm, so that we have
+ * a local implementation of it */
+#ifdef USE_NSS
+
+#include "curl_md4.h"
+#include "warnless.h"
+
+typedef unsigned int UINT4;
+
+typedef struct MD4Context {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD4_CTX;
+
+/* Constants for MD4Transform routine.
+ */
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+static void MD4Transform(UINT4 [4], const unsigned char [64]);
+static void Encode(unsigned char *, UINT4 *, unsigned int);
+static void Decode(UINT4 *, const unsigned char *, unsigned int);
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G and H are basic MD4 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s) { \
+ (a) += F ((b), (c), (d)) + (x); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define GG(a, b, c, d, x, s) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define HH(a, b, c, d, x, s) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context.
+ */
+static void MD4Init(MD4_CTX *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants.
+ */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD4 block update operation. Continues an MD4 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+static void MD4Update(MD4_CTX *context, const unsigned char *input,
+ unsigned int inputLen)
+{
+ unsigned int i, bufindex, partLen;
+
+ /* Compute number of bytes mod 64 */
+ bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F);
+ /* Update number of bits */
+ if((context->count[0] += ((UINT4)inputLen << 3))
+ < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - bufindex;
+ /* Transform as many times as possible.
+ */
+ if(inputLen >= partLen) {
+ memcpy(&context->buffer[bufindex], input, partLen);
+ MD4Transform (context->state, context->buffer);
+
+ for(i = partLen; i + 63 < inputLen; i += 64)
+ MD4Transform (context->state, &input[i]);
+
+ bufindex = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[bufindex], &input[i], inputLen-i);
+}
+
+/* MD4 padding. */
+static void MD4Pad(MD4_CTX *context)
+{
+ unsigned char bits[8];
+ unsigned int bufindex, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64.
+ */
+ bufindex = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (bufindex < 56) ? (56 - bufindex) : (120 - bufindex);
+ MD4Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD4Update (context, bits, 8);
+}
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+static void MD4Final (unsigned char digest[16], MD4_CTX *context)
+{
+ /* Do padding */
+ MD4Pad (context);
+
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information.
+ */
+ memset(context, 0, sizeof(*context));
+}
+
+/* MD4 basic transformation. Transforms state based on block.
+ */
+static void MD4Transform (UINT4 state[4], const unsigned char block[64])
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11); /* 1 */
+ FF (d, a, b, c, x[ 1], S12); /* 2 */
+ FF (c, d, a, b, x[ 2], S13); /* 3 */
+ FF (b, c, d, a, x[ 3], S14); /* 4 */
+ FF (a, b, c, d, x[ 4], S11); /* 5 */
+ FF (d, a, b, c, x[ 5], S12); /* 6 */
+ FF (c, d, a, b, x[ 6], S13); /* 7 */
+ FF (b, c, d, a, x[ 7], S14); /* 8 */
+ FF (a, b, c, d, x[ 8], S11); /* 9 */
+ FF (d, a, b, c, x[ 9], S12); /* 10 */
+ FF (c, d, a, b, x[10], S13); /* 11 */
+ FF (b, c, d, a, x[11], S14); /* 12 */
+ FF (a, b, c, d, x[12], S11); /* 13 */
+ FF (d, a, b, c, x[13], S12); /* 14 */
+ FF (c, d, a, b, x[14], S13); /* 15 */
+ FF (b, c, d, a, x[15], S14); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 0], S21); /* 17 */
+ GG (d, a, b, c, x[ 4], S22); /* 18 */
+ GG (c, d, a, b, x[ 8], S23); /* 19 */
+ GG (b, c, d, a, x[12], S24); /* 20 */
+ GG (a, b, c, d, x[ 1], S21); /* 21 */
+ GG (d, a, b, c, x[ 5], S22); /* 22 */
+ GG (c, d, a, b, x[ 9], S23); /* 23 */
+ GG (b, c, d, a, x[13], S24); /* 24 */
+ GG (a, b, c, d, x[ 2], S21); /* 25 */
+ GG (d, a, b, c, x[ 6], S22); /* 26 */
+ GG (c, d, a, b, x[10], S23); /* 27 */
+ GG (b, c, d, a, x[14], S24); /* 28 */
+ GG (a, b, c, d, x[ 3], S21); /* 29 */
+ GG (d, a, b, c, x[ 7], S22); /* 30 */
+ GG (c, d, a, b, x[11], S23); /* 31 */
+ GG (b, c, d, a, x[15], S24); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 0], S31); /* 33 */
+ HH (d, a, b, c, x[ 8], S32); /* 34 */
+ HH (c, d, a, b, x[ 4], S33); /* 35 */
+ HH (b, c, d, a, x[12], S34); /* 36 */
+ HH (a, b, c, d, x[ 2], S31); /* 37 */
+ HH (d, a, b, c, x[10], S32); /* 38 */
+ HH (c, d, a, b, x[ 6], S33); /* 39 */
+ HH (b, c, d, a, x[14], S34); /* 40 */
+ HH (a, b, c, d, x[ 1], S31); /* 41 */
+ HH (d, a, b, c, x[ 9], S32); /* 42 */
+ HH (c, d, a, b, x[ 5], S33); /* 43 */
+ HH (b, c, d, a, x[13], S34); /* 44 */
+ HH (a, b, c, d, x[ 3], S31); /* 45 */
+ HH (d, a, b, c, x[11], S32); /* 46 */
+ HH (c, d, a, b, x[ 7], S33); /* 47 */
+ HH (b, c, d, a, x[15], S34); /* 48 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information.
+ */
+ memset(x, 0, sizeof(x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void Encode(unsigned char *output, UINT4 *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for(i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ a multiple of 4.
+ */
+static void Decode (UINT4 *output, const unsigned char *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ for(i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
+{
+ MD4_CTX ctx;
+ MD4Init(&ctx);
+ MD4Update(&ctx, input, curlx_uztoui(len));
+ MD4Final(output, &ctx);
+}
+#endif /* USE_NSS */
diff --git a/external/libcurl_android/jni/libcurl/lib/md5.c b/external/libcurl_android/jni/libcurl/lib/md5.c
new file mode 100755
index 00000000..af39fd41
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/md5.c
@@ -0,0 +1,541 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+
+#include "curl_md5.h"
+#include "curl_hmac.h"
+#include "warnless.h"
+
+#include "curl_memory.h"
+
+#if defined(USE_GNUTLS_NETTLE)
+
+#include <nettle/md5.h>
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef struct md5_ctx MD5_CTX;
+
+static void MD5_Init(MD5_CTX * ctx)
+{
+ md5_init(ctx);
+}
+
+static void MD5_Update(MD5_CTX * ctx,
+ const unsigned char * input,
+ unsigned int inputLen)
+{
+ md5_update(ctx, inputLen, input);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+{
+ md5_digest(ctx, 16, digest);
+}
+
+#elif defined(USE_GNUTLS)
+
+#include <gcrypt.h>
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef gcry_md_hd_t MD5_CTX;
+
+static void MD5_Init(MD5_CTX * ctx)
+{
+ gcry_md_open(ctx, GCRY_MD_MD5, 0);
+}
+
+static void MD5_Update(MD5_CTX * ctx,
+ const unsigned char * input,
+ unsigned int inputLen)
+{
+ gcry_md_write(*ctx, input, inputLen);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+{
+ memcpy(digest, gcry_md_read(*ctx, 0), 16);
+ gcry_md_close(*ctx);
+}
+
+#elif defined(USE_SSLEAY)
+/* When OpenSSL is available we use the MD5-function from OpenSSL */
+
+# ifdef USE_OPENSSL
+# include <openssl/md5.h>
+# else
+# include <md5.h>
+# endif
+
+#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
+ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
+ (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
+
+/* For Apple operating systems: CommonCrypto has the functions we need.
+ These functions are available on Tiger and later, as well as iOS 2.0
+ and later. If you're building for an older cat, well, sorry.
+
+ Declaring the functions as static like this seems to be a bit more
+ reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
+# include <CommonCrypto/CommonDigest.h>
+# define MD5_CTX CC_MD5_CTX
+
+static void MD5_Init(MD5_CTX *ctx)
+{
+ CC_MD5_Init(ctx);
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ CC_MD5_Update(ctx, input, inputLen);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+{
+ CC_MD5_Final(digest, ctx);
+}
+
+#elif defined(_WIN32)
+
+#include <wincrypt.h>
+
+typedef struct {
+ HCRYPTPROV hCryptProv;
+ HCRYPTHASH hHash;
+} MD5_CTX;
+
+static void MD5_Init(MD5_CTX *ctx)
+{
+ if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash);
+ }
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+{
+ unsigned long length = 0;
+ CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
+ if(length == 16)
+ CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
+ if(ctx->hHash)
+ CryptDestroyHash(ctx->hHash);
+ if(ctx->hCryptProv)
+ CryptReleaseContext(ctx->hCryptProv, 0);
+}
+
+#else
+/* When no other crypto library is available we use this code segment */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* UINT4 defines a four byte word */
+typedef unsigned int UINT4;
+
+/* MD5 context. */
+struct md5_ctx {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+};
+
+typedef struct md5_ctx MD5_CTX;
+
+static void MD5_Init(struct md5_ctx *);
+static void MD5_Update(struct md5_ctx *, const unsigned char *, unsigned int);
+static void MD5_Final(unsigned char [16], struct md5_ctx *);
+
+/* Constants for MD5Transform routine.
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform(UINT4 [4], const unsigned char [64]);
+static void Encode(unsigned char *, UINT4 *, unsigned int);
+static void Decode(UINT4 *, const unsigned char *, unsigned int);
+
+static const unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+static void MD5_Init(struct md5_ctx *context)
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+static void MD5_Update (struct md5_ctx *context, /* context */
+ const unsigned char *input, /* input block */
+ unsigned int inputLen) /* length of input block */
+{
+ unsigned int i, bufindex, partLen;
+
+ /* Compute number of bytes mod 64 */
+ bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if((context->count[0] += ((UINT4)inputLen << 3))
+ < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - bufindex;
+
+ /* Transform as many times as possible. */
+ if(inputLen >= partLen) {
+ memcpy(&context->buffer[bufindex], input, partLen);
+ MD5Transform(context->state, context->buffer);
+
+ for(i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform(context->state, &input[i]);
+
+ bufindex = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[bufindex], &input[i], inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ the message digest and zeroizing the context.
+*/
+static void MD5_Final(unsigned char digest[16], /* message digest */
+ struct md5_ctx *context) /* context */
+{
+ unsigned char bits[8];
+ unsigned int count, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64. */
+ count = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (count < 56) ? (56 - count) : (120 - count);
+ MD5_Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5_Update (context, bits, 8);
+
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information. */
+ memset ((void *)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+static void MD5Transform(UINT4 state[4],
+ const unsigned char block[64])
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset((void *)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void Encode (unsigned char *output,
+ UINT4 *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ for(i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ a multiple of 4.
+*/
+static void Decode (UINT4 *output,
+ const unsigned char *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ for(i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+#endif /* CRYPTO LIBS */
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+const HMAC_params Curl_HMAC_MD5[] = {
+ {
+ (HMAC_hinit_func) MD5_Init, /* Hash initialization function. */
+ (HMAC_hupdate_func) MD5_Update, /* Hash update function. */
+ (HMAC_hfinal_func) MD5_Final, /* Hash computation end function. */
+ sizeof(MD5_CTX), /* Size of hash context structure. */
+ 64, /* Maximum key length. */
+ 16 /* Result size. */
+ }
+};
+
+const MD5_params Curl_DIGEST_MD5[] = {
+ {
+ (Curl_MD5_init_func) MD5_Init, /* Digest initialization function */
+ (Curl_MD5_update_func) MD5_Update, /* Digest update function */
+ (Curl_MD5_final_func) MD5_Final, /* Digest computation end function */
+ sizeof(MD5_CTX), /* Size of digest context struct */
+ 16 /* Result size */
+ }
+};
+
+void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
+ const unsigned char *input)
+{
+ MD5_CTX ctx;
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
+ MD5_Final(outbuffer, &ctx);
+}
+
+MD5_context *Curl_MD5_init(const MD5_params *md5params)
+{
+ MD5_context *ctxt;
+
+ /* Create MD5 context */
+ ctxt = malloc(sizeof *ctxt);
+
+ if(!ctxt)
+ return ctxt;
+
+ ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize);
+
+ if(!ctxt->md5_hashctx) {
+ free(ctxt);
+ return NULL;
+ }
+
+ ctxt->md5_hash = md5params;
+
+ (*md5params->md5_init_func)(ctxt->md5_hashctx);
+
+ return ctxt;
+}
+
+int Curl_MD5_update(MD5_context *context,
+ const unsigned char *data,
+ unsigned int len)
+{
+ (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
+
+ return 0;
+}
+
+int Curl_MD5_final(MD5_context *context, unsigned char *result)
+{
+ (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
+
+ free(context->md5_hashctx);
+ free(context);
+
+ return 0;
+}
+
+#endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/external/libcurl_android/jni/libcurl/lib/memdebug.c b/external/libcurl_android/jni/libcurl/lib/memdebug.c
new file mode 100755
index 00000000..4afa620a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/memdebug.c
@@ -0,0 +1,490 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef CURLDEBUG
+
+#include <curl/curl.h>
+
+#define _MPRINTF_REPLACE
+#include <curl/mprintf.h>
+#include "urldata.h"
+
+#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef HAVE_ASSERT_H
+# define assert(x) Curl_nop_stmt
+#endif
+
+/*
+ * Until 2011-08-17 libcurl's Memory Tracking feature also performed
+ * automatic malloc and free filling operations using 0xA5 and 0x13
+ * values. Our own preinitialization of dynamically allocated memory
+ * might be useful when not using third party memory debuggers, but
+ * on the other hand this would fool memory debuggers into thinking
+ * that all dynamically allocated memory is properly initialized.
+ *
+ * As a default setting, libcurl's Memory Tracking feature no longer
+ * performs preinitialization of dynamically allocated memory on its
+ * own. If you know what you are doing, and really want to retain old
+ * behavior, you can achieve this compiling with preprocessor symbols
+ * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate
+ * values.
+ */
+
+#ifdef CURL_MT_MALLOC_FILL
+# if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff)
+# error "invalid CURL_MT_MALLOC_FILL or out of range"
+# endif
+#endif
+
+#ifdef CURL_MT_FREE_FILL
+# if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff)
+# error "invalid CURL_MT_FREE_FILL or out of range"
+# endif
+#endif
+
+#if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL)
+# if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL)
+# error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL"
+# endif
+#endif
+
+#ifdef CURL_MT_MALLOC_FILL
+# define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len))
+#else
+# define mt_malloc_fill(buf,len) Curl_nop_stmt
+#endif
+
+#ifdef CURL_MT_FREE_FILL
+# define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len))
+#else
+# define mt_free_fill(buf,len) Curl_nop_stmt
+#endif
+
+struct memdebug {
+ size_t size;
+ union {
+ curl_off_t o;
+ double d;
+ void * p;
+ } mem[1];
+ /* I'm hoping this is the thing with the strictest alignment
+ * requirements. That also means we waste some space :-( */
+};
+
+/*
+ * Note that these debug functions are very simple and they are meant to
+ * remain so. For advanced analysis, record a log file and write perl scripts
+ * to analyze them!
+ *
+ * Don't use these with multithreaded test programs!
+ */
+
+#define logfile curl_debuglogfile
+FILE *curl_debuglogfile = NULL;
+static bool memlimit = FALSE; /* enable memory limit */
+static long memsize = 0; /* set number of mallocs allowed */
+
+/* this sets the log file name */
+void curl_memdebug(const char *logname)
+{
+ if(!logfile) {
+ if(logname && *logname)
+ logfile = fopen(logname, "w");
+ else
+ logfile = stderr;
+#ifdef MEMDEBUG_LOG_SYNC
+ /* Flush the log file after every line so the log isn't lost in a crash */
+ setvbuf(logfile, (char *)NULL, _IOLBF, 0);
+#endif
+ }
+}
+
+/* This function sets the number of malloc() calls that should return
+ successfully! */
+void curl_memlimit(long limit)
+{
+ if(!memlimit) {
+ memlimit = TRUE;
+ memsize = limit;
+ }
+}
+
+/* returns TRUE if this isn't allowed! */
+static bool countcheck(const char *func, int line, const char *source)
+{
+ /* if source is NULL, then the call is made internally and this check
+ should not be made */
+ if(memlimit && source) {
+ if(!memsize) {
+ if(source) {
+ /* log to file */
+ curl_memlog("LIMIT %s:%d %s reached memlimit\n",
+ source, line, func);
+ /* log to stderr also */
+ fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
+ source, line, func);
+ }
+ SET_ERRNO(ENOMEM);
+ return TRUE; /* RETURN ERROR! */
+ }
+ else
+ memsize--; /* countdown */
+
+ /* log the countdown */
+ if(source)
+ curl_memlog("LIMIT %s:%d %ld ALLOCS left\n",
+ source, line, memsize);
+
+ }
+
+ return FALSE; /* allow this */
+}
+
+void *curl_domalloc(size_t wantedsize, int line, const char *source)
+{
+ struct memdebug *mem;
+ size_t size;
+
+ assert(wantedsize != 0);
+
+ if(countcheck("malloc", line, source))
+ return NULL;
+
+ /* alloc at least 64 bytes */
+ size = sizeof(struct memdebug)+wantedsize;
+
+ mem = (Curl_cmalloc)(size);
+ if(mem) {
+ /* fill memory with junk */
+ mt_malloc_fill(mem->mem, wantedsize);
+ mem->size = wantedsize;
+ }
+
+ if(source)
+ curl_memlog("MEM %s:%d malloc(%zu) = %p\n",
+ source, line, wantedsize,
+ mem ? (void *)mem->mem : (void *)0);
+
+ return (mem ? mem->mem : NULL);
+}
+
+void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
+ int line, const char *source)
+{
+ struct memdebug *mem;
+ size_t size, user_size;
+
+ assert(wanted_elements != 0);
+ assert(wanted_size != 0);
+
+ if(countcheck("calloc", line, source))
+ return NULL;
+
+ /* alloc at least 64 bytes */
+ user_size = wanted_size * wanted_elements;
+ size = sizeof(struct memdebug) + user_size;
+
+ mem = (Curl_ccalloc)(1, size);
+ if(mem)
+ mem->size = user_size;
+
+ if(source)
+ curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
+ source, line, wanted_elements, wanted_size,
+ mem ? (void *)mem->mem : (void *)0);
+
+ return (mem ? mem->mem : NULL);
+}
+
+char *curl_dostrdup(const char *str, int line, const char *source)
+{
+ char *mem;
+ size_t len;
+
+ assert(str != NULL);
+
+ if(countcheck("strdup", line, source))
+ return NULL;
+
+ len=strlen(str)+1;
+
+ mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
+ if(mem)
+ memcpy(mem, str, len);
+
+ if(source)
+ curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
+ source, line, (void *)str, len, (void *)mem);
+
+ return mem;
+}
+
+#if defined(WIN32) && defined(UNICODE)
+wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
+{
+ wchar_t *mem;
+ size_t wsiz, bsiz;
+
+ assert(str != NULL);
+
+ if(countcheck("wcsdup", line, source))
+ return NULL;
+
+ wsiz = wcslen(str) + 1;
+ bsiz = wsiz * sizeof(wchar_t);
+
+ mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
+ if(mem)
+ memcpy(mem, str, bsiz);
+
+ if(source)
+ curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
+ source, line, (void *)str, bsiz, (void *)mem);
+
+ return mem;
+}
+#endif
+
+/* We provide a realloc() that accepts a NULL as pointer, which then
+ performs a malloc(). In order to work with ares. */
+void *curl_dorealloc(void *ptr, size_t wantedsize,
+ int line, const char *source)
+{
+ struct memdebug *mem=NULL;
+
+ size_t size = sizeof(struct memdebug)+wantedsize;
+
+ assert(wantedsize != 0);
+
+ if(countcheck("realloc", line, source))
+ return NULL;
+
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:1684)
+ /* 1684: conversion from pointer to same-sized integral type */
+#endif
+
+ if(ptr)
+ mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+
+ mem = (Curl_crealloc)(mem, size);
+ if(source)
+ curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
+ source, line, (void *)ptr, wantedsize,
+ mem ? (void *)mem->mem : (void *)0);
+
+ if(mem) {
+ mem->size = wantedsize;
+ return mem->mem;
+ }
+
+ return NULL;
+}
+
+void curl_dofree(void *ptr, int line, const char *source)
+{
+ struct memdebug *mem;
+
+ if(ptr) {
+
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:1684)
+ /* 1684: conversion from pointer to same-sized integral type */
+#endif
+
+ mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+
+ /* destroy */
+ mt_free_fill(mem->mem, mem->size);
+
+ /* free for real */
+ (Curl_cfree)(mem);
+ }
+
+ if(source)
+ curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
+}
+
+curl_socket_t curl_socket(int domain, int type, int protocol,
+ int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d socket() = %d\n" :
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d socket() = %ld\n" :
+ "FD %s:%d socket() = %zd\n" ;
+
+ curl_socket_t sockfd = socket(domain, type, protocol);
+
+ if(source && (sockfd != CURL_SOCKET_BAD))
+ curl_memlog(fmt, source, line, sockfd);
+
+ return sockfd;
+}
+
+#ifdef HAVE_SOCKETPAIR
+int curl_socketpair(int domain, int type, int protocol,
+ curl_socket_t socket_vector[2],
+ int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d socketpair() = %d %d\n" :
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d socketpair() = %ld %ld\n" :
+ "FD %s:%d socketpair() = %zd %zd\n" ;
+
+ int res = socketpair(domain, type, protocol, socket_vector);
+
+ if(source && (0 == res))
+ curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
+
+ return res;
+}
+#endif
+
+curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
+ int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d accept() = %d\n" :
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d accept() = %ld\n" :
+ "FD %s:%d accept() = %zd\n" ;
+
+ struct sockaddr *addr = (struct sockaddr *)saddr;
+ curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
+
+ curl_socket_t sockfd = accept(s, addr, addrlen);
+
+ if(source && (sockfd != CURL_SOCKET_BAD))
+ curl_memlog(fmt, source, line, sockfd);
+
+ return sockfd;
+}
+
+/* separate function to allow libcurl to mark a "faked" close */
+void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
+{
+ const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
+ "FD %s:%d sclose(%d)\n" :
+ (sizeof(curl_socket_t) == sizeof(long)) ?
+ "FD %s:%d sclose(%ld)\n" :
+ "FD %s:%d sclose(%zd)\n" ;
+
+ if(source)
+ curl_memlog(fmt, source, line, sockfd);
+}
+
+/* this is our own defined way to close sockets on *ALL* platforms */
+int curl_sclose(curl_socket_t sockfd, int line, const char *source)
+{
+ int res=sclose(sockfd);
+ curl_mark_sclose(sockfd, line, source);
+ return res;
+}
+
+FILE *curl_fopen(const char *file, const char *mode,
+ int line, const char *source)
+{
+ FILE *res=fopen(file, mode);
+
+ if(source)
+ curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
+ source, line, file, mode, (void *)res);
+
+ return res;
+}
+
+#ifdef HAVE_FDOPEN
+FILE *curl_fdopen(int filedes, const char *mode,
+ int line, const char *source)
+{
+ FILE *res=fdopen(filedes, mode);
+
+ if(source)
+ curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
+ source, line, filedes, mode, (void *)res);
+
+ return res;
+}
+#endif
+
+int curl_fclose(FILE *file, int line, const char *source)
+{
+ int res;
+
+ assert(file != NULL);
+
+ res=fclose(file);
+
+ if(source)
+ curl_memlog("FILE %s:%d fclose(%p)\n",
+ source, line, (void *)file);
+
+ return res;
+}
+
+#define LOGLINE_BUFSIZE 1024
+
+/* this does the writting to the memory tracking log file */
+void curl_memlog(const char *format, ...)
+{
+ char *buf;
+ int nchars;
+ va_list ap;
+
+ if(!logfile)
+ return;
+
+ buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
+ if(!buf)
+ return;
+
+ va_start(ap, format);
+ nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
+ va_end(ap);
+
+ if(nchars > LOGLINE_BUFSIZE - 1)
+ nchars = LOGLINE_BUFSIZE - 1;
+
+ if(nchars > 0)
+ fwrite(buf, 1, nchars, logfile);
+
+ (Curl_cfree)(buf);
+}
+
+#endif /* CURLDEBUG */
diff --git a/external/libcurl_android/jni/libcurl/lib/memdebug.h b/external/libcurl_android/jni/libcurl/lib/memdebug.h
new file mode 100755
index 00000000..bd565c8d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/memdebug.h
@@ -0,0 +1,176 @@
+#ifndef HEADER_CURL_MEMDEBUG_H
+#define HEADER_CURL_MEMDEBUG_H
+#ifdef CURLDEBUG
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * CAUTION: this header is designed to work when included by the app-side
+ * as well as the library. Do not mix with library internals!
+ */
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#define CURL_MT_LOGFNAME_BUFSIZE 512
+
+#define logfile curl_debuglogfile
+
+extern FILE *logfile;
+
+/* memory functions */
+CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source);
+CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line,
+ const char *source);
+CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line,
+ const char *source);
+CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
+CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
+#if defined(WIN32) && defined(UNICODE)
+CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line,
+ const char *source);
+#endif
+
+CURL_EXTERN void curl_memdebug(const char *logname);
+CURL_EXTERN void curl_memlimit(long limit);
+CURL_EXTERN void curl_memlog(const char *format, ...);
+
+/* file descriptor manipulators */
+CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol,
+ int line , const char *source);
+CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd,
+ int line , const char *source);
+CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
+ int line , const char *source);
+CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
+ int line, const char *source);
+#ifdef HAVE_SOCKETPAIR
+CURL_EXTERN int curl_socketpair(int domain, int type, int protocol,
+ curl_socket_t socket_vector[2],
+ int line , const char *source);
+#endif
+
+/* FILE functions */
+CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
+ const char *source);
+#ifdef HAVE_FDOPEN
+CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line,
+ const char *source);
+#endif
+CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
+
+#ifndef MEMDEBUG_NODEFINES
+
+/* Set this symbol on the command-line, recompile all lib-sources */
+#undef strdup
+#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
+#define malloc(size) curl_domalloc(size, __LINE__, __FILE__)
+#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__)
+#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
+#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
+
+#ifdef WIN32
+# ifdef UNICODE
+# undef wcsdup
+# define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+# undef _wcsdup
+# define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+# undef _tcsdup
+# define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+# else
+# undef _tcsdup
+# define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
+# endif
+#endif
+
+#define socket(domain,type,protocol)\
+ curl_socket(domain,type,protocol,__LINE__,__FILE__)
+#undef accept /* for those with accept as a macro */
+#define accept(sock,addr,len)\
+ curl_accept(sock,addr,len,__LINE__,__FILE__)
+#ifdef HAVE_SOCKETPAIR
+#define socketpair(domain,type,protocol,socket_vector)\
+ curl_socketpair(domain,type,protocol,socket_vector,__LINE__,__FILE__)
+#endif
+
+#ifdef HAVE_GETADDRINFO
+#if defined(getaddrinfo) && defined(__osf__)
+/* OSF/1 and Tru64 have getaddrinfo as a define already, so we cannot define
+ our macro as for other platforms. Instead, we redefine the new name they
+ define getaddrinfo to become! */
+#define ogetaddrinfo(host,serv,hint,res) \
+ curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
+#else
+#undef getaddrinfo
+#define getaddrinfo(host,serv,hint,res) \
+ curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
+#endif
+#endif /* HAVE_GETADDRINFO */
+
+#ifdef HAVE_GETNAMEINFO
+#undef getnameinfo
+#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
+ curl_dogetnameinfo(sa,salen,host,hostlen,serv,servlen,flags, __LINE__, \
+ __FILE__)
+#endif /* HAVE_GETNAMEINFO */
+
+#ifdef HAVE_FREEADDRINFO
+#undef freeaddrinfo
+#define freeaddrinfo(data) \
+ curl_dofreeaddrinfo(data,__LINE__,__FILE__)
+#endif /* HAVE_FREEADDRINFO */
+
+/* sclose is probably already defined, redefine it! */
+#undef sclose
+#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
+
+#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__)
+
+#undef fopen
+#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__)
+#undef fdopen
+#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__)
+#define fclose(file) curl_fclose(file,__LINE__,__FILE__)
+
+#endif /* MEMDEBUG_NODEFINES */
+
+#endif /* CURLDEBUG */
+
+/*
+** Following section applies even when CURLDEBUG is not defined.
+*/
+
+#ifndef fake_sclose
+#define fake_sclose(x) Curl_nop_stmt
+#endif
+
+/*
+ * Curl_safefree defined as a macro to allow MemoryTracking feature
+ * to log free() calls at same location where Curl_safefree is used.
+ * This macro also assigns NULL to given pointer when free'd.
+ */
+
+#define Curl_safefree(ptr) \
+ do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE
+
+#endif /* HEADER_CURL_MEMDEBUG_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/mprintf.c b/external/libcurl_android/jni/libcurl/lib/mprintf.c
new file mode 100755
index 00000000..23070a76
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/mprintf.c
@@ -0,0 +1,1142 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1999 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ *
+ * Purpose:
+ * A merge of Bjorn Reese's format() function and Daniel's dsprintf()
+ * 1.0. A full blooded printf() clone with full support for <num>$
+ * everywhere (parameters, widths and precisions) including variabled
+ * sized parameters (like doubles, long longs, long doubles and even
+ * void * in 64-bit architectures).
+ *
+ * Current restrictions:
+ * - Max 128 parameters
+ * - No 'long double' support.
+ *
+ * If you ever want truly portable and good *printf() clones, the project that
+ * took on from here is named 'Trio' and you find more details on the trio web
+ * page at http://daniel.haxx.se/trio/
+ */
+
+#include "curl_setup.h"
+
+#if defined(DJGPP) && (DJGPP_MINOR < 4)
+#undef _MPRINTF_REPLACE /* don't use x_was_used() here */
+#endif
+
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef SIZEOF_LONG_DOUBLE
+#define SIZEOF_LONG_DOUBLE 0
+#endif
+
+/*
+ * If SIZEOF_SIZE_T has not been defined, default to the size of long.
+ */
+
+#ifndef SIZEOF_SIZE_T
+# define SIZEOF_SIZE_T CURL_SIZEOF_LONG
+#endif
+
+#ifdef HAVE_LONGLONG
+# define LONG_LONG_TYPE long long
+# define HAVE_LONG_LONG_TYPE
+#else
+# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define LONG_LONG_TYPE __int64
+# define HAVE_LONG_LONG_TYPE
+# else
+# undef LONG_LONG_TYPE
+# undef HAVE_LONG_LONG_TYPE
+# endif
+#endif
+
+/*
+ * Non-ANSI integer extensions
+ */
+
+#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
+ (defined(__WATCOMC__) && defined(__386__)) || \
+ (defined(__POCC__) && defined(_MSC_VER)) || \
+ (defined(_WIN32_WCE)) || \
+ (defined(__MINGW32__)) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
+# define MP_HAVE_INT_EXTENSIONS
+#endif
+
+/*
+ * Max integer data types that mprintf.c is capable
+ */
+
+#ifdef HAVE_LONG_LONG_TYPE
+# define mp_intmax_t LONG_LONG_TYPE
+# define mp_uintmax_t unsigned LONG_LONG_TYPE
+#else
+# define mp_intmax_t long
+# define mp_uintmax_t unsigned long
+#endif
+
+#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
+#define MAX_PARAMETERS 128 /* lame static limit */
+
+#ifdef __AMIGA__
+# undef FORMAT_INT
+#endif
+
+/* Lower-case digits. */
+static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+/* Upper-case digits. */
+static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+#define OUTCHAR(x) \
+ do{ \
+ if(stream((unsigned char)(x), (FILE *)data) != -1) \
+ done++; \
+ else \
+ return done; /* return immediately on failure */ \
+ } WHILE_FALSE
+
+/* Data type to read from the arglist */
+typedef enum {
+ FORMAT_UNKNOWN = 0,
+ FORMAT_STRING,
+ FORMAT_PTR,
+ FORMAT_INT,
+ FORMAT_INTPTR,
+ FORMAT_LONG,
+ FORMAT_LONGLONG,
+ FORMAT_DOUBLE,
+ FORMAT_LONGDOUBLE,
+ FORMAT_WIDTH /* For internal use */
+} FormatType;
+
+/* conversion and display flags */
+enum {
+ FLAGS_NEW = 0,
+ FLAGS_SPACE = 1<<0,
+ FLAGS_SHOWSIGN = 1<<1,
+ FLAGS_LEFT = 1<<2,
+ FLAGS_ALT = 1<<3,
+ FLAGS_SHORT = 1<<4,
+ FLAGS_LONG = 1<<5,
+ FLAGS_LONGLONG = 1<<6,
+ FLAGS_LONGDOUBLE = 1<<7,
+ FLAGS_PAD_NIL = 1<<8,
+ FLAGS_UNSIGNED = 1<<9,
+ FLAGS_OCTAL = 1<<10,
+ FLAGS_HEX = 1<<11,
+ FLAGS_UPPER = 1<<12,
+ FLAGS_WIDTH = 1<<13, /* '*' or '*<num>$' used */
+ FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */
+ FLAGS_PREC = 1<<15, /* precision was specified */
+ FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */
+ FLAGS_CHAR = 1<<17, /* %c story */
+ FLAGS_FLOATE = 1<<18, /* %e or %E */
+ FLAGS_FLOATG = 1<<19 /* %g or %G */
+};
+
+typedef struct {
+ FormatType type;
+ int flags;
+ long width; /* width OR width parameter number */
+ long precision; /* precision OR precision parameter number */
+ union {
+ char *str;
+ void *ptr;
+ union {
+ mp_intmax_t as_signed;
+ mp_uintmax_t as_unsigned;
+ } num;
+ double dnum;
+ } data;
+} va_stack_t;
+
+struct nsprintf {
+ char *buffer;
+ size_t length;
+ size_t max;
+};
+
+struct asprintf {
+ char *buffer; /* allocated buffer */
+ size_t len; /* length of string */
+ size_t alloc; /* length of alloc */
+ int fail; /* (!= 0) if an alloc has failed and thus
+ the output is not the complete data */
+};
+
+static long dprintf_DollarString(char *input, char **end)
+{
+ int number=0;
+ while(ISDIGIT(*input)) {
+ number *= 10;
+ number += *input-'0';
+ input++;
+ }
+ if(number && ('$'==*input++)) {
+ *end = input;
+ return number;
+ }
+ return 0;
+}
+
+static bool dprintf_IsQualifierNoDollar(const char *fmt)
+{
+#if defined(MP_HAVE_INT_EXTENSIONS)
+ if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
+ return TRUE;
+ }
+#endif
+
+ switch(*fmt) {
+ case '-': case '+': case ' ': case '#': case '.':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'h': case 'l': case 'L': case 'z': case 'q':
+ case '*': case 'O':
+#if defined(MP_HAVE_INT_EXTENSIONS)
+ case 'I':
+#endif
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+/******************************************************************
+ *
+ * Pass 1:
+ * Create an index with the type of each parameter entry and its
+ * value (may vary in size)
+ *
+ ******************************************************************/
+
+static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
+ va_list arglist)
+{
+ char *fmt = (char *)format;
+ int param_num = 0;
+ long this_param;
+ long width;
+ long precision;
+ int flags;
+ long max_param=0;
+ long i;
+
+ while(*fmt) {
+ if(*fmt++ == '%') {
+ if(*fmt == '%') {
+ fmt++;
+ continue; /* while */
+ }
+
+ flags = FLAGS_NEW;
+
+ /* Handle the positional case (N$) */
+
+ param_num++;
+
+ this_param = dprintf_DollarString(fmt, &fmt);
+ if(0 == this_param)
+ /* we got no positional, get the next counter */
+ this_param = param_num;
+
+ if(this_param > max_param)
+ max_param = this_param;
+
+ /*
+ * The parameter with number 'i' should be used. Next, we need
+ * to get SIZE and TYPE of the parameter. Add the information
+ * to our array.
+ */
+
+ width = 0;
+ precision = 0;
+
+ /* Handle the flags */
+
+ while(dprintf_IsQualifierNoDollar(fmt)) {
+#if defined(MP_HAVE_INT_EXTENSIONS)
+ if(!strncmp(fmt, "I32", 3)) {
+ flags |= FLAGS_LONG;
+ fmt += 3;
+ }
+ else if(!strncmp(fmt, "I64", 3)) {
+ flags |= FLAGS_LONGLONG;
+ fmt += 3;
+ }
+ else
+#endif
+
+ switch(*fmt++) {
+ case ' ':
+ flags |= FLAGS_SPACE;
+ break;
+ case '+':
+ flags |= FLAGS_SHOWSIGN;
+ break;
+ case '-':
+ flags |= FLAGS_LEFT;
+ flags &= ~FLAGS_PAD_NIL;
+ break;
+ case '#':
+ flags |= FLAGS_ALT;
+ break;
+ case '.':
+ flags |= FLAGS_PREC;
+ if('*' == *fmt) {
+ /* The precision is picked from a specified parameter */
+
+ flags |= FLAGS_PRECPARAM;
+ fmt++;
+ param_num++;
+
+ i = dprintf_DollarString(fmt, &fmt);
+ if(i)
+ precision = i;
+ else
+ precision = param_num;
+
+ if(precision > max_param)
+ max_param = precision;
+ }
+ else {
+ flags |= FLAGS_PREC;
+ precision = strtol(fmt, &fmt, 10);
+ }
+ break;
+ case 'h':
+ flags |= FLAGS_SHORT;
+ break;
+#if defined(MP_HAVE_INT_EXTENSIONS)
+ case 'I':
+#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ break;
+#endif
+ case 'l':
+ if(flags & FLAGS_LONG)
+ flags |= FLAGS_LONGLONG;
+ else
+ flags |= FLAGS_LONG;
+ break;
+ case 'L':
+ flags |= FLAGS_LONGDOUBLE;
+ break;
+ case 'q':
+ flags |= FLAGS_LONGLONG;
+ break;
+ case 'z':
+ /* the code below generates a warning if -Wunreachable-code is
+ used */
+#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ break;
+ case 'O':
+#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ break;
+ case '0':
+ if(!(flags & FLAGS_LEFT))
+ flags |= FLAGS_PAD_NIL;
+ /* FALLTHROUGH */
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ flags |= FLAGS_WIDTH;
+ width = strtol(fmt-1, &fmt, 10);
+ break;
+ case '*': /* Special case */
+ flags |= FLAGS_WIDTHPARAM;
+ param_num++;
+
+ i = dprintf_DollarString(fmt, &fmt);
+ if(i)
+ width = i;
+ else
+ width = param_num;
+ if(width > max_param)
+ max_param=width;
+ break;
+ default:
+ break;
+ }
+ } /* switch */
+
+ /* Handle the specifier */
+
+ i = this_param - 1;
+
+ switch (*fmt) {
+ case 'S':
+ flags |= FLAGS_ALT;
+ /* FALLTHROUGH */
+ case 's':
+ vto[i].type = FORMAT_STRING;
+ break;
+ case 'n':
+ vto[i].type = FORMAT_INTPTR;
+ break;
+ case 'p':
+ vto[i].type = FORMAT_PTR;
+ break;
+ case 'd': case 'i':
+ vto[i].type = FORMAT_INT;
+ break;
+ case 'u':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_UNSIGNED;
+ break;
+ case 'o':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_OCTAL;
+ break;
+ case 'x':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_HEX|FLAGS_UNSIGNED;
+ break;
+ case 'X':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
+ break;
+ case 'c':
+ vto[i].type = FORMAT_INT;
+ flags |= FLAGS_CHAR;
+ break;
+ case 'f':
+ vto[i].type = FORMAT_DOUBLE;
+ break;
+ case 'e':
+ vto[i].type = FORMAT_DOUBLE;
+ flags |= FLAGS_FLOATE;
+ break;
+ case 'E':
+ vto[i].type = FORMAT_DOUBLE;
+ flags |= FLAGS_FLOATE|FLAGS_UPPER;
+ break;
+ case 'g':
+ vto[i].type = FORMAT_DOUBLE;
+ flags |= FLAGS_FLOATG;
+ break;
+ case 'G':
+ vto[i].type = FORMAT_DOUBLE;
+ flags |= FLAGS_FLOATG|FLAGS_UPPER;
+ break;
+ default:
+ vto[i].type = FORMAT_UNKNOWN;
+ break;
+ } /* switch */
+
+ vto[i].flags = flags;
+ vto[i].width = width;
+ vto[i].precision = precision;
+
+ if(flags & FLAGS_WIDTHPARAM) {
+ /* we have the width specified from a parameter, so we make that
+ parameter's info setup properly */
+ vto[i].width = width - 1;
+ i = width - 1;
+ vto[i].type = FORMAT_WIDTH;
+ vto[i].flags = FLAGS_NEW;
+ vto[i].precision = vto[i].width = 0; /* can't use width or precision
+ of width! */
+ }
+ if(flags & FLAGS_PRECPARAM) {
+ /* we have the precision specified from a parameter, so we make that
+ parameter's info setup properly */
+ vto[i].precision = precision - 1;
+ i = precision - 1;
+ vto[i].type = FORMAT_WIDTH;
+ vto[i].flags = FLAGS_NEW;
+ vto[i].precision = vto[i].width = 0; /* can't use width or precision
+ of width! */
+ }
+ *endpos++ = fmt + 1; /* end of this sequence */
+ }
+ }
+
+ /* Read the arg list parameters into our data list */
+ for(i=0; i<max_param; i++) {
+ if((i + 1 < max_param) && (vto[i + 1].type == FORMAT_WIDTH)) {
+ /* Width/precision arguments must be read before the main argument
+ * they are attached to
+ */
+ vto[i + 1].data.num.as_signed = (mp_intmax_t)va_arg(arglist, int);
+ }
+
+ switch (vto[i].type) {
+ case FORMAT_STRING:
+ vto[i].data.str = va_arg(arglist, char *);
+ break;
+
+ case FORMAT_INTPTR:
+ case FORMAT_UNKNOWN:
+ case FORMAT_PTR:
+ vto[i].data.ptr = va_arg(arglist, void *);
+ break;
+
+ case FORMAT_INT:
+#ifdef HAVE_LONG_LONG_TYPE
+ if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
+ vto[i].data.num.as_unsigned =
+ (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
+ else if(vto[i].flags & FLAGS_LONGLONG)
+ vto[i].data.num.as_signed =
+ (mp_intmax_t)va_arg(arglist, mp_intmax_t);
+ else
+#endif
+ {
+ if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
+ vto[i].data.num.as_unsigned =
+ (mp_uintmax_t)va_arg(arglist, unsigned long);
+ else if(vto[i].flags & FLAGS_LONG)
+ vto[i].data.num.as_signed =
+ (mp_intmax_t)va_arg(arglist, long);
+ else if(vto[i].flags & FLAGS_UNSIGNED)
+ vto[i].data.num.as_unsigned =
+ (mp_uintmax_t)va_arg(arglist, unsigned int);
+ else
+ vto[i].data.num.as_signed =
+ (mp_intmax_t)va_arg(arglist, int);
+ }
+ break;
+
+ case FORMAT_DOUBLE:
+ vto[i].data.dnum = va_arg(arglist, double);
+ break;
+
+ case FORMAT_WIDTH:
+ /* Argument has been read. Silently convert it into an integer
+ * for later use
+ */
+ vto[i].type = FORMAT_INT;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return max_param;
+
+}
+
+static int dprintf_formatf(
+ void *data, /* untouched by format(), just sent to the stream() function in
+ the second argument */
+ /* function pointer called for each output character */
+ int (*stream)(int, FILE *),
+ const char *format, /* %-formatted string */
+ va_list ap_save) /* list of parameters */
+{
+ /* Base-36 digits for numbers. */
+ const char *digits = lower_digits;
+
+ /* Pointer into the format string. */
+ char *f;
+
+ /* Number of characters written. */
+ int done = 0;
+
+ long param; /* current parameter to read */
+ long param_num=0; /* parameter counter */
+
+ va_stack_t vto[MAX_PARAMETERS];
+ char *endpos[MAX_PARAMETERS];
+ char **end;
+
+ char work[BUFFSIZE];
+
+ va_stack_t *p;
+
+ /* Do the actual %-code parsing */
+ dprintf_Pass1(format, vto, endpos, ap_save);
+
+ end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
+ created for us */
+
+ f = (char *)format;
+ while(*f != '\0') {
+ /* Format spec modifiers. */
+ int is_alt;
+
+ /* Width of a field. */
+ long width;
+
+ /* Precision of a field. */
+ long prec;
+
+ /* Decimal integer is negative. */
+ int is_neg;
+
+ /* Base of a number to be written. */
+ long base;
+
+ /* Integral values to be written. */
+ mp_uintmax_t num;
+
+ /* Used to convert negative in positive. */
+ mp_intmax_t signed_num;
+
+ if(*f != '%') {
+ /* This isn't a format spec, so write everything out until the next one
+ OR end of string is reached. */
+ do {
+ OUTCHAR(*f);
+ } while(*++f && ('%' != *f));
+ continue;
+ }
+
+ ++f;
+
+ /* Check for "%%". Note that although the ANSI standard lists
+ '%' as a conversion specifier, it says "The complete format
+ specification shall be `%%'," so we can avoid all the width
+ and precision processing. */
+ if(*f == '%') {
+ ++f;
+ OUTCHAR('%');
+ continue;
+ }
+
+ /* If this is a positional parameter, the position must follow immediately
+ after the %, thus create a %<num>$ sequence */
+ param=dprintf_DollarString(f, &f);
+
+ if(!param)
+ param = param_num;
+ else
+ --param;
+
+ param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
+ third %s will pick the 3rd argument */
+
+ p = &vto[param];
+
+ /* pick up the specified width */
+ if(p->flags & FLAGS_WIDTHPARAM)
+ width = (long)vto[p->width].data.num.as_signed;
+ else
+ width = p->width;
+
+ /* pick up the specified precision */
+ if(p->flags & FLAGS_PRECPARAM) {
+ prec = (long)vto[p->precision].data.num.as_signed;
+ param_num++; /* since the precision is extraced from a parameter, we
+ must skip that to get to the next one properly */
+ }
+ else if(p->flags & FLAGS_PREC)
+ prec = p->precision;
+ else
+ prec = -1;
+
+ is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
+
+ switch (p->type) {
+ case FORMAT_INT:
+ num = p->data.num.as_unsigned;
+ if(p->flags & FLAGS_CHAR) {
+ /* Character. */
+ if(!(p->flags & FLAGS_LEFT))
+ while(--width > 0)
+ OUTCHAR(' ');
+ OUTCHAR((char) num);
+ if(p->flags & FLAGS_LEFT)
+ while(--width > 0)
+ OUTCHAR(' ');
+ break;
+ }
+ if(p->flags & FLAGS_OCTAL) {
+ /* Octal unsigned integer. */
+ base = 8;
+ goto unsigned_number;
+ }
+ else if(p->flags & FLAGS_HEX) {
+ /* Hexadecimal unsigned integer. */
+
+ digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
+ base = 16;
+ goto unsigned_number;
+ }
+ else if(p->flags & FLAGS_UNSIGNED) {
+ /* Decimal unsigned integer. */
+ base = 10;
+ goto unsigned_number;
+ }
+
+ /* Decimal integer. */
+ base = 10;
+
+ is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
+ if(is_neg) {
+ /* signed_num might fail to hold absolute negative minimum by 1 */
+ signed_num = p->data.num.as_signed + (mp_intmax_t)1;
+ signed_num = -signed_num;
+ num = (mp_uintmax_t)signed_num;
+ num += (mp_uintmax_t)1;
+ }
+
+ goto number;
+
+ unsigned_number:
+ /* Unsigned number of base BASE. */
+ is_neg = 0;
+
+ number:
+ /* Number of base BASE. */
+ {
+ char *workend = &work[sizeof(work) - 1];
+ char *w;
+
+ /* Supply a default precision if none was given. */
+ if(prec == -1)
+ prec = 1;
+
+ /* Put the number in WORK. */
+ w = workend;
+ while(num > 0) {
+ *w-- = digits[num % base];
+ num /= base;
+ }
+ width -= (long)(workend - w);
+ prec -= (long)(workend - w);
+
+ if(is_alt && base == 8 && prec <= 0) {
+ *w-- = '0';
+ --width;
+ }
+
+ if(prec > 0) {
+ width -= prec;
+ while(prec-- > 0)
+ *w-- = '0';
+ }
+
+ if(is_alt && base == 16)
+ width -= 2;
+
+ if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
+ --width;
+
+ if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ if(is_neg)
+ OUTCHAR('-');
+ else if(p->flags & FLAGS_SHOWSIGN)
+ OUTCHAR('+');
+ else if(p->flags & FLAGS_SPACE)
+ OUTCHAR(' ');
+
+ if(is_alt && base == 16) {
+ OUTCHAR('0');
+ if(p->flags & FLAGS_UPPER)
+ OUTCHAR('X');
+ else
+ OUTCHAR('x');
+ }
+
+ if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
+ while(width-- > 0)
+ OUTCHAR('0');
+
+ /* Write the number. */
+ while(++w <= workend) {
+ OUTCHAR(*w);
+ }
+
+ if(p->flags & FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+ }
+ break;
+
+ case FORMAT_STRING:
+ /* String. */
+ {
+ static const char null[] = "(nil)";
+ const char *str;
+ size_t len;
+
+ str = (char *) p->data.str;
+ if(str == NULL) {
+ /* Write null[] if there's space. */
+ if(prec == -1 || prec >= (long) sizeof(null) - 1) {
+ str = null;
+ len = sizeof(null) - 1;
+ /* Disable quotes around (nil) */
+ p->flags &= (~FLAGS_ALT);
+ }
+ else {
+ str = "";
+ len = 0;
+ }
+ }
+ else if(prec != -1)
+ len = (size_t)prec;
+ else
+ len = strlen(str);
+
+ width -= (long)len;
+
+ if(p->flags & FLAGS_ALT)
+ OUTCHAR('"');
+
+ if(!(p->flags&FLAGS_LEFT))
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ while((len-- > 0) && *str)
+ OUTCHAR(*str++);
+ if(p->flags&FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ if(p->flags & FLAGS_ALT)
+ OUTCHAR('"');
+ }
+ break;
+
+ case FORMAT_PTR:
+ /* Generic pointer. */
+ {
+ void *ptr;
+ ptr = (void *) p->data.ptr;
+ if(ptr != NULL) {
+ /* If the pointer is not NULL, write it as a %#x spec. */
+ base = 16;
+ digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
+ is_alt = 1;
+ num = (size_t) ptr;
+ is_neg = 0;
+ goto number;
+ }
+ else {
+ /* Write "(nil)" for a nil pointer. */
+ static const char strnil[] = "(nil)";
+ const char *point;
+
+ width -= (long)(sizeof(strnil) - 1);
+ if(p->flags & FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+ for(point = strnil; *point != '\0'; ++point)
+ OUTCHAR(*point);
+ if(! (p->flags & FLAGS_LEFT))
+ while(width-- > 0)
+ OUTCHAR(' ');
+ }
+ }
+ break;
+
+ case FORMAT_DOUBLE:
+ {
+ char formatbuf[32]="%";
+ char *fptr = &formatbuf[1];
+ size_t left = sizeof(formatbuf)-strlen(formatbuf);
+ int len;
+
+ width = -1;
+ if(p->flags & FLAGS_WIDTH)
+ width = p->width;
+ else if(p->flags & FLAGS_WIDTHPARAM)
+ width = (long)vto[p->width].data.num.as_signed;
+
+ prec = -1;
+ if(p->flags & FLAGS_PREC)
+ prec = p->precision;
+ else if(p->flags & FLAGS_PRECPARAM)
+ prec = (long)vto[p->precision].data.num.as_signed;
+
+ if(p->flags & FLAGS_LEFT)
+ *fptr++ = '-';
+ if(p->flags & FLAGS_SHOWSIGN)
+ *fptr++ = '+';
+ if(p->flags & FLAGS_SPACE)
+ *fptr++ = ' ';
+ if(p->flags & FLAGS_ALT)
+ *fptr++ = '#';
+
+ *fptr = 0;
+
+ if(width >= 0) {
+ /* RECURSIVE USAGE */
+ len = curl_msnprintf(fptr, left, "%ld", width);
+ fptr += len;
+ left -= len;
+ }
+ if(prec >= 0) {
+ /* RECURSIVE USAGE */
+ len = curl_msnprintf(fptr, left, ".%ld", prec);
+ fptr += len;
+ }
+ if(p->flags & FLAGS_LONG)
+ *fptr++ = 'l';
+
+ if(p->flags & FLAGS_FLOATE)
+ *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
+ else if(p->flags & FLAGS_FLOATG)
+ *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
+ else
+ *fptr++ = 'f';
+
+ *fptr = 0; /* and a final zero termination */
+
+ /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
+ output characters */
+ (sprintf)(work, formatbuf, p->data.dnum);
+
+ for(fptr=work; *fptr; fptr++)
+ OUTCHAR(*fptr);
+ }
+ break;
+
+ case FORMAT_INTPTR:
+ /* Answer the count of characters written. */
+#ifdef HAVE_LONG_LONG_TYPE
+ if(p->flags & FLAGS_LONGLONG)
+ *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
+ else
+#endif
+ if(p->flags & FLAGS_LONG)
+ *(long *) p->data.ptr = (long)done;
+ else if(!(p->flags & FLAGS_SHORT))
+ *(int *) p->data.ptr = (int)done;
+ else
+ *(short *) p->data.ptr = (short)done;
+ break;
+
+ default:
+ break;
+ }
+ f = *end++; /* goto end of %-code */
+
+ }
+ return done;
+}
+
+/* fputc() look-alike */
+static int addbyter(int output, FILE *data)
+{
+ struct nsprintf *infop=(struct nsprintf *)data;
+ unsigned char outc = (unsigned char)output;
+
+ if(infop->length < infop->max) {
+ /* only do this if we haven't reached max length yet */
+ infop->buffer[0] = outc; /* store */
+ infop->buffer++; /* increase pointer */
+ infop->length++; /* we are now one byte larger */
+ return outc; /* fputc() returns like this on success */
+ }
+ return -1;
+}
+
+int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
+ va_list ap_save)
+{
+ int retcode;
+ struct nsprintf info;
+
+ info.buffer = buffer;
+ info.length = 0;
+ info.max = maxlength;
+
+ retcode = dprintf_formatf(&info, addbyter, format, ap_save);
+ if(info.max) {
+ /* we terminate this with a zero byte */
+ if(info.max == info.length)
+ /* we're at maximum, scrap the last letter */
+ info.buffer[-1] = 0;
+ else
+ info.buffer[0] = 0;
+ }
+ return retcode;
+}
+
+int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
+{
+ int retcode;
+ va_list ap_save; /* argument pointer */
+ va_start(ap_save, format);
+ retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
+ va_end(ap_save);
+ return retcode;
+}
+
+/* fputc() look-alike */
+static int alloc_addbyter(int output, FILE *data)
+{
+ struct asprintf *infop=(struct asprintf *)data;
+ unsigned char outc = (unsigned char)output;
+
+ if(!infop->buffer) {
+ infop->buffer = malloc(32);
+ if(!infop->buffer) {
+ infop->fail = 1;
+ return -1; /* fail */
+ }
+ infop->alloc = 32;
+ infop->len =0;
+ }
+ else if(infop->len+1 >= infop->alloc) {
+ char *newptr;
+
+ newptr = realloc(infop->buffer, infop->alloc*2);
+
+ if(!newptr) {
+ infop->fail = 1;
+ return -1; /* fail */
+ }
+ infop->buffer = newptr;
+ infop->alloc *= 2;
+ }
+
+ infop->buffer[ infop->len ] = outc;
+
+ infop->len++;
+
+ return outc; /* fputc() returns like this on success */
+}
+
+char *curl_maprintf(const char *format, ...)
+{
+ va_list ap_save; /* argument pointer */
+ int retcode;
+ struct asprintf info;
+
+ info.buffer = NULL;
+ info.len = 0;
+ info.alloc = 0;
+ info.fail = 0;
+
+ va_start(ap_save, format);
+ retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
+ va_end(ap_save);
+ if((-1 == retcode) || info.fail) {
+ if(info.alloc)
+ free(info.buffer);
+ return NULL;
+ }
+ if(info.alloc) {
+ info.buffer[info.len] = 0; /* we terminate this with a zero byte */
+ return info.buffer;
+ }
+ else
+ return strdup("");
+}
+
+char *curl_mvaprintf(const char *format, va_list ap_save)
+{
+ int retcode;
+ struct asprintf info;
+
+ info.buffer = NULL;
+ info.len = 0;
+ info.alloc = 0;
+ info.fail = 0;
+
+ retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
+ if((-1 == retcode) || info.fail) {
+ if(info.alloc)
+ free(info.buffer);
+ return NULL;
+ }
+
+ if(info.alloc) {
+ info.buffer[info.len] = 0; /* we terminate this with a zero byte */
+ return info.buffer;
+ }
+ else
+ return strdup("");
+}
+
+static int storebuffer(int output, FILE *data)
+{
+ char **buffer = (char **)data;
+ unsigned char outc = (unsigned char)output;
+ **buffer = outc;
+ (*buffer)++;
+ return outc; /* act like fputc() ! */
+}
+
+int curl_msprintf(char *buffer, const char *format, ...)
+{
+ va_list ap_save; /* argument pointer */
+ int retcode;
+ va_start(ap_save, format);
+ retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
+ va_end(ap_save);
+ *buffer=0; /* we terminate this with a zero byte */
+ return retcode;
+}
+
+int curl_mprintf(const char *format, ...)
+{
+ int retcode;
+ va_list ap_save; /* argument pointer */
+ va_start(ap_save, format);
+
+ retcode = dprintf_formatf(stdout, fputc, format, ap_save);
+ va_end(ap_save);
+ return retcode;
+}
+
+int curl_mfprintf(FILE *whereto, const char *format, ...)
+{
+ int retcode;
+ va_list ap_save; /* argument pointer */
+ va_start(ap_save, format);
+ retcode = dprintf_formatf(whereto, fputc, format, ap_save);
+ va_end(ap_save);
+ return retcode;
+}
+
+int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
+{
+ int retcode;
+ retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
+ *buffer=0; /* we terminate this with a zero byte */
+ return retcode;
+}
+
+int curl_mvprintf(const char *format, va_list ap_save)
+{
+ return dprintf_formatf(stdout, fputc, format, ap_save);
+}
+
+int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
+{
+ return dprintf_formatf(whereto, fputc, format, ap_save);
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/multi.c b/external/libcurl_android/jni/libcurl/lib/multi.c
new file mode 100755
index 00000000..a1dc2c82
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/multi.c
@@ -0,0 +1,2835 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "transfer.h"
+#include "url.h"
+#include "connect.h"
+#include "progress.h"
+#include "easyif.h"
+#include "share.h"
+#include "multiif.h"
+#include "sendf.h"
+#include "timeval.h"
+#include "http.h"
+#include "select.h"
+#include "warnless.h"
+#include "speedcheck.h"
+#include "conncache.h"
+#include "bundles.h"
+#include "multihandle.h"
+#include "pipeline.h"
+#include "sigpipe.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
+ to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
+ CURL handle takes 45-50 K memory, therefore this 3K are not significant.
+*/
+#ifndef CURL_SOCKET_HASH_TABLE_SIZE
+#define CURL_SOCKET_HASH_TABLE_SIZE 911
+#endif
+
+#define CURL_CONNECTION_HASH_SIZE 97
+
+#define CURL_MULTI_HANDLE 0x000bab1e
+
+#define GOOD_MULTI_HANDLE(x) \
+ ((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
+#define GOOD_EASY_HANDLE(x) \
+ ((x) && (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER))
+
+static void singlesocket(struct Curl_multi *multi,
+ struct SessionHandle *data);
+static int update_timer(struct Curl_multi *multi);
+
+static bool isHandleAtHead(struct SessionHandle *handle,
+ struct curl_llist *pipeline);
+static CURLMcode add_next_timeout(struct timeval now,
+ struct Curl_multi *multi,
+ struct SessionHandle *d);
+static CURLMcode multi_timeout(struct Curl_multi *multi,
+ long *timeout_ms);
+
+#ifdef DEBUGBUILD
+static const char * const statename[]={
+ "INIT",
+ "CONNECT_PEND",
+ "CONNECT",
+ "WAITRESOLVE",
+ "WAITCONNECT",
+ "WAITPROXYCONNECT",
+ "PROTOCONNECT",
+ "WAITDO",
+ "DO",
+ "DOING",
+ "DO_MORE",
+ "DO_DONE",
+ "WAITPERFORM",
+ "PERFORM",
+ "TOOFAST",
+ "DONE",
+ "COMPLETED",
+ "MSGSENT",
+};
+#endif
+
+static void multi_freetimeout(void *a, void *b);
+
+/* always use this function to change state, to make debugging easier */
+static void mstate(struct SessionHandle *data, CURLMstate state
+#ifdef DEBUGBUILD
+ , int lineno
+#endif
+)
+{
+#ifdef DEBUGBUILD
+ long connection_id = -5000;
+#endif
+ CURLMstate oldstate = data->mstate;
+
+ if(oldstate == state)
+ /* don't bother when the new state is the same as the old state */
+ return;
+
+ data->mstate = state;
+
+#ifdef DEBUGBUILD
+ if(data->mstate >= CURLM_STATE_CONNECT_PEND &&
+ data->mstate < CURLM_STATE_COMPLETED) {
+ if(data->easy_conn)
+ connection_id = data->easy_conn->connection_id;
+
+ infof(data,
+ "STATE: %s => %s handle %p; line %d (connection #%ld) \n",
+ statename[oldstate], statename[data->mstate],
+ (void *)data, lineno, connection_id);
+ }
+#endif
+ if(state == CURLM_STATE_COMPLETED)
+ /* changing to COMPLETED means there's one less easy handle 'alive' */
+ data->multi->num_alive--;
+}
+
+#ifndef DEBUGBUILD
+#define multistate(x,y) mstate(x,y)
+#else
+#define multistate(x,y) mstate(x,y, __LINE__)
+#endif
+
+/*
+ * We add one of these structs to the sockhash for a particular socket
+ */
+
+struct Curl_sh_entry {
+ struct SessionHandle *easy;
+ time_t timestamp;
+ int action; /* what action READ/WRITE this socket waits for */
+ curl_socket_t socket; /* mainly to ease debugging */
+ void *socketp; /* settable by users with curl_multi_assign() */
+};
+/* bits for 'action' having no bits means this socket is not expecting any
+ action */
+#define SH_READ 1
+#define SH_WRITE 2
+
+/* make sure this socket is present in the hash for this handle */
+static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
+ curl_socket_t s,
+ struct SessionHandle *data)
+{
+ struct Curl_sh_entry *there =
+ Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
+ struct Curl_sh_entry *check;
+
+ if(there)
+ /* it is present, return fine */
+ return there;
+
+ /* not present, add it */
+ check = calloc(1, sizeof(struct Curl_sh_entry));
+ if(!check)
+ return NULL; /* major failure */
+ check->easy = data;
+ check->socket = s;
+
+ /* make/add new hash entry */
+ if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
+ free(check);
+ return NULL; /* major failure */
+ }
+
+ return check; /* things are good in sockhash land */
+}
+
+
+/* delete the given socket + handle from the hash */
+static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
+{
+ struct Curl_sh_entry *there =
+ Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
+
+ if(there) {
+ /* this socket is in the hash */
+ /* We remove the hash entry. (This'll end up in a call to
+ sh_freeentry().) */
+ Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
+ }
+}
+
+/*
+ * free a sockhash entry
+ */
+static void sh_freeentry(void *freethis)
+{
+ struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
+
+ if(p)
+ free(p);
+}
+
+static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
+{
+ (void) k1_len; (void) k2_len;
+
+ return (*((int *) k1)) == (*((int *) k2));
+}
+
+static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
+{
+ int fd = *((int *) key);
+ (void) key_length;
+
+ return (fd % (int)slots_num);
+}
+
+/*
+ * sh_init() creates a new socket hash and returns the handle for it.
+ *
+ * Quote from README.multi_socket:
+ *
+ * "Some tests at 7000 and 9000 connections showed that the socket hash lookup
+ * is somewhat of a bottle neck. Its current implementation may be a bit too
+ * limiting. It simply has a fixed-size array, and on each entry in the array
+ * it has a linked list with entries. So the hash only checks which list to
+ * scan through. The code I had used so for used a list with merely 7 slots
+ * (as that is what the DNS hash uses) but with 7000 connections that would
+ * make an average of 1000 nodes in each list to run through. I upped that to
+ * 97 slots (I believe a prime is suitable) and noticed a significant speed
+ * increase. I need to reconsider the hash implementation or use a rather
+ * large default value like this. At 9000 connections I was still below 10us
+ * per call."
+ *
+ */
+static struct curl_hash *sh_init(int hashsize)
+{
+ return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
+ sh_freeentry);
+}
+
+/*
+ * multi_addmsg()
+ *
+ * Called when a transfer is completed. Adds the given msg pointer to
+ * the list kept in the multi handle.
+ */
+static CURLMcode multi_addmsg(struct Curl_multi *multi,
+ struct Curl_message *msg)
+{
+ if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
+ return CURLM_OUT_OF_MEMORY;
+
+ return CURLM_OK;
+}
+
+/*
+ * multi_freeamsg()
+ *
+ * Callback used by the llist system when a single list entry is destroyed.
+ */
+static void multi_freeamsg(void *a, void *b)
+{
+ (void)a;
+ (void)b;
+}
+
+struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
+ int chashsize) /* connection hash */
+{
+ struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
+
+ if(!multi)
+ return NULL;
+
+ multi->type = CURL_MULTI_HANDLE;
+
+ multi->hostcache = Curl_mk_dnscache();
+ if(!multi->hostcache)
+ goto error;
+
+ multi->sockhash = sh_init(hashsize);
+ if(!multi->sockhash)
+ goto error;
+
+ multi->conn_cache = Curl_conncache_init(chashsize);
+ if(!multi->conn_cache)
+ goto error;
+
+ multi->msglist = Curl_llist_alloc(multi_freeamsg);
+ if(!multi->msglist)
+ goto error;
+
+ multi->pending = Curl_llist_alloc(multi_freeamsg);
+ if(!multi->pending)
+ goto error;
+
+ /* allocate a new easy handle to use when closing cached connections */
+ multi->closure_handle = curl_easy_init();
+ if(!multi->closure_handle)
+ goto error;
+
+ multi->closure_handle->multi = multi;
+ multi->closure_handle->state.conn_cache = multi->conn_cache;
+
+ multi->max_pipeline_length = 5;
+
+ /* -1 means it not set by user, use the default value */
+ multi->maxconnects = -1;
+ return (CURLM *) multi;
+
+ error:
+
+ Curl_hash_destroy(multi->sockhash);
+ multi->sockhash = NULL;
+ Curl_hash_destroy(multi->hostcache);
+ multi->hostcache = NULL;
+ Curl_conncache_destroy(multi->conn_cache);
+ multi->conn_cache = NULL;
+ Curl_close(multi->closure_handle);
+ multi->closure_handle = NULL;
+ Curl_llist_destroy(multi->msglist, NULL);
+ Curl_llist_destroy(multi->pending, NULL);
+
+ free(multi);
+ return NULL;
+}
+
+CURLM *curl_multi_init(void)
+{
+ return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
+ CURL_CONNECTION_HASH_SIZE);
+}
+
+CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+ CURL *easy_handle)
+{
+ struct curl_llist *timeoutlist;
+ struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
+ struct SessionHandle *data = (struct SessionHandle *)easy_handle;
+
+ /* First, make some basic checks that the CURLM handle is a good handle */
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ /* Verify that we got a somewhat good easy handle too */
+ if(!GOOD_EASY_HANDLE(easy_handle))
+ return CURLM_BAD_EASY_HANDLE;
+
+ /* Prevent users from adding same easy handle more than once and prevent
+ adding to more than one multi stack */
+ if(data->multi)
+ return CURLM_ADDED_ALREADY;
+
+ /* Allocate and initialize timeout list for easy handle */
+ timeoutlist = Curl_llist_alloc(multi_freetimeout);
+ if(!timeoutlist)
+ return CURLM_OUT_OF_MEMORY;
+
+ /*
+ * No failure allowed in this function beyond this point. And no
+ * modification of easy nor multi handle allowed before this except for
+ * potential multi's connection cache growing which won't be undone in this
+ * function no matter what.
+ */
+
+ /* Make easy handle use timeout list initialized above */
+ data->state.timeoutlist = timeoutlist;
+ timeoutlist = NULL;
+
+ /* set the easy handle */
+ multistate(data, CURLM_STATE_INIT);
+
+ if((data->set.global_dns_cache) &&
+ (data->dns.hostcachetype != HCACHE_GLOBAL)) {
+ /* global dns cache was requested but still isn't */
+ struct curl_hash *global = Curl_global_host_cache_init();
+ if(global) {
+ /* only do this if the global cache init works */
+ data->dns.hostcache = global;
+ data->dns.hostcachetype = HCACHE_GLOBAL;
+ }
+ }
+ /* for multi interface connections, we share DNS cache automatically if the
+ easy handle's one is currently not set. */
+ else if(!data->dns.hostcache ||
+ (data->dns.hostcachetype == HCACHE_NONE)) {
+ data->dns.hostcache = multi->hostcache;
+ data->dns.hostcachetype = HCACHE_MULTI;
+ }
+
+ /* Point to the multi's connection cache */
+ data->state.conn_cache = multi->conn_cache;
+
+ data->state.infilesize = data->set.filesize;
+
+ /* This adds the new entry at the 'end' of the doubly-linked circular
+ list of SessionHandle structs to try and maintain a FIFO queue so
+ the pipelined requests are in order. */
+
+ /* We add this new entry last in the list. */
+
+ data->next = NULL; /* end of the line */
+ if(multi->easyp) {
+ struct SessionHandle *last = multi->easylp;
+ last->next = data;
+ data->prev = last;
+ multi->easylp = data; /* the new last node */
+ }
+ else {
+ /* first node, make both prev and next be NULL! */
+ data->next = NULL;
+ data->prev = NULL;
+ multi->easylp = multi->easyp = data; /* both first and last */
+ }
+
+ /* make the SessionHandle refer back to this multi handle */
+ data->multi = multi_handle;
+
+ /* Set the timeout for this handle to expire really soon so that it will
+ be taken care of even when this handle is added in the midst of operation
+ when only the curl_multi_socket() API is used. During that flow, only
+ sockets that time-out or have actions will be dealt with. Since this
+ handle has no action yet, we make sure it times out to get things to
+ happen. */
+ Curl_expire(data, 1);
+
+ /* increase the node-counter */
+ multi->num_easy++;
+
+ /* increase the alive-counter */
+ multi->num_alive++;
+
+ /* A somewhat crude work-around for a little glitch in update_timer() that
+ happens if the lastcall time is set to the same time when the handle is
+ removed as when the next handle is added, as then the check in
+ update_timer() that prevents calling the application multiple times with
+ the same timer infor will not trigger and then the new handle's timeout
+ will not be notified to the app.
+
+ The work-around is thus simply to clear the 'lastcall' variable to force
+ update_timer() to always trigger a callback to the app when a new easy
+ handle is added */
+ memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
+
+ update_timer(multi);
+ return CURLM_OK;
+}
+
+#if 0
+/* Debug-function, used like this:
+ *
+ * Curl_hash_print(multi->sockhash, debug_print_sock_hash);
+ *
+ * Enable the hash print function first by editing hash.c
+ */
+static void debug_print_sock_hash(void *p)
+{
+ struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
+
+ fprintf(stderr, " [easy %p/magic %x/socket %d]",
+ (void *)sh->data, sh->data->magic, (int)sh->socket);
+}
+#endif
+
+CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+ CURL *curl_handle)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *easy = curl_handle;
+ struct SessionHandle *data = easy;
+
+ /* First, make some basic checks that the CURLM handle is a good handle */
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ /* Verify that we got a somewhat good easy handle too */
+ if(!GOOD_EASY_HANDLE(curl_handle))
+ return CURLM_BAD_EASY_HANDLE;
+
+ /* Prevent users from trying to remove same easy handle more than once */
+ if(!data->multi)
+ return CURLM_OK; /* it is already removed so let's say it is fine! */
+
+ if(easy) {
+ bool premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
+ bool easy_owns_conn = (data->easy_conn &&
+ (data->easy_conn->data == easy)) ?
+ TRUE : FALSE;
+
+ /* If the 'state' is not INIT or COMPLETED, we might need to do something
+ nice to put the easy_handle in a good known state when this returns. */
+ if(premature)
+ /* this handle is "alive" so we need to count down the total number of
+ alive connections when this is removed */
+ multi->num_alive--;
+
+ if(data->easy_conn &&
+ (data->easy_conn->send_pipe->size +
+ data->easy_conn->recv_pipe->size > 1) &&
+ data->mstate > CURLM_STATE_WAITDO &&
+ data->mstate < CURLM_STATE_COMPLETED) {
+ /* If the handle is in a pipeline and has started sending off its
+ request but not received its response yet, we need to close
+ connection. */
+ connclose(data->easy_conn, "Removed with partial response");
+ /* Set connection owner so that Curl_done() closes it.
+ We can sefely do this here since connection is killed. */
+ data->easy_conn->data = easy;
+ }
+
+ /* The timer must be shut down before data->multi is set to NULL,
+ else the timenode will remain in the splay tree after
+ curl_easy_cleanup is called. */
+ Curl_expire(data, 0);
+
+ /* destroy the timeout list that is held in the easy handle */
+ if(data->state.timeoutlist) {
+ Curl_llist_destroy(data->state.timeoutlist, NULL);
+ data->state.timeoutlist = NULL;
+ }
+
+ if(data->dns.hostcachetype == HCACHE_MULTI) {
+ /* stop using the multi handle's DNS cache */
+ data->dns.hostcache = NULL;
+ data->dns.hostcachetype = HCACHE_NONE;
+ }
+
+ if(data->easy_conn) {
+
+ /* we must call Curl_done() here (if we still "own it") so that we don't
+ leave a half-baked one around */
+ if(easy_owns_conn) {
+
+ /* Curl_done() clears the conn->data field to lose the association
+ between the easy handle and the connection
+
+ Note that this ignores the return code simply because there's
+ nothing really useful to do with it anyway! */
+ (void)Curl_done(&data->easy_conn, data->result, premature);
+ }
+ else
+ /* Clear connection pipelines, if Curl_done above was not called */
+ Curl_getoff_all_pipelines(data, data->easy_conn);
+ }
+
+ Curl_wildcard_dtor(&data->wildcard);
+
+ /* as this was using a shared connection cache we clear the pointer
+ to that since we're not part of that multi handle anymore */
+ data->state.conn_cache = NULL;
+
+ /* change state without using multistate(), only to make singlesocket() do
+ what we want */
+ data->mstate = CURLM_STATE_COMPLETED;
+ singlesocket(multi, easy); /* to let the application know what sockets
+ that vanish with this handle */
+
+ /* Remove the association between the connection and the handle */
+ if(data->easy_conn) {
+ data->easy_conn->data = NULL;
+ data->easy_conn = NULL;
+ }
+
+ data->multi = NULL; /* clear the association to this multi handle */
+
+ {
+ /* make sure there's no pending message in the queue sent from this easy
+ handle */
+ struct curl_llist_element *e;
+
+ for(e = multi->msglist->head; e; e = e->next) {
+ struct Curl_message *msg = e->ptr;
+
+ if(msg->extmsg.easy_handle == easy) {
+ Curl_llist_remove(multi->msglist, e, NULL);
+ /* there can only be one from this specific handle */
+ break;
+ }
+ }
+ }
+
+ /* make the previous node point to our next */
+ if(data->prev)
+ data->prev->next = data->next;
+ else
+ multi->easyp = data->next; /* point to first node */
+
+ /* make our next point to our previous node */
+ if(data->next)
+ data->next->prev = data->prev;
+ else
+ multi->easylp = data->prev; /* point to last node */
+
+ /* NOTE NOTE NOTE
+ We do not touch the easy handle here! */
+
+ multi->num_easy--; /* one less to care about now */
+
+ update_timer(multi);
+ return CURLM_OK;
+ }
+ else
+ return CURLM_BAD_EASY_HANDLE; /* twasn't found */
+}
+
+bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
+{
+ return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
+}
+
+void Curl_multi_handlePipeBreak(struct SessionHandle *data)
+{
+ data->easy_conn = NULL;
+}
+
+static int waitconnect_getsock(struct connectdata *conn,
+ curl_socket_t *sock,
+ int numsocks)
+{
+ int i;
+ int s=0;
+ int rc=0;
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ for(i=0; i<2; i++) {
+ if(conn->tempsock[i] != CURL_SOCKET_BAD) {
+ sock[s] = conn->tempsock[i];
+ rc |= GETSOCK_WRITESOCK(s++);
+ }
+ }
+
+ /* when we've sent a CONNECT to a proxy, we should rather wait for the
+ socket to become readable to be able to get the response headers */
+ if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) {
+ sock[0] = conn->sock[FIRSTSOCKET];
+ rc = GETSOCK_READSOCK(0);
+ }
+
+ return rc;
+}
+
+static int domore_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ if(conn && conn->handler->domore_getsock)
+ return conn->handler->domore_getsock(conn, socks, numsocks);
+ return GETSOCK_BLANK;
+}
+
+/* returns bitmapped flags for this handle and its sockets */
+static int multi_getsock(struct SessionHandle *data,
+ curl_socket_t *socks, /* points to numsocks number
+ of sockets */
+ int numsocks)
+{
+ /* If the pipe broke, or if there's no connection left for this easy handle,
+ then we MUST bail out now with no bitmask set. The no connection case can
+ happen when this is called from curl_multi_remove_handle() =>
+ singlesocket() => multi_getsock().
+ */
+ if(data->state.pipe_broke || !data->easy_conn)
+ return 0;
+
+ if(data->mstate > CURLM_STATE_CONNECT &&
+ data->mstate < CURLM_STATE_COMPLETED) {
+ /* Set up ownership correctly */
+ data->easy_conn->data = data;
+ }
+
+ switch(data->mstate) {
+ default:
+#if 0 /* switch back on these cases to get the compiler to check for all enums
+ to be present */
+ case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */
+ case CURLM_STATE_COMPLETED:
+ case CURLM_STATE_MSGSENT:
+ case CURLM_STATE_INIT:
+ case CURLM_STATE_CONNECT:
+ case CURLM_STATE_WAITDO:
+ case CURLM_STATE_DONE:
+ case CURLM_STATE_LAST:
+ /* this will get called with CURLM_STATE_COMPLETED when a handle is
+ removed */
+#endif
+ return 0;
+
+ case CURLM_STATE_WAITRESOLVE:
+ return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_PROTOCONNECT:
+ return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_DO:
+ case CURLM_STATE_DOING:
+ return Curl_doing_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_WAITPROXYCONNECT:
+ case CURLM_STATE_WAITCONNECT:
+ return waitconnect_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_DO_MORE:
+ return domore_getsock(data->easy_conn, socks, numsocks);
+
+ case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
+ to waiting for the same as the *PERFORM
+ states */
+ case CURLM_STATE_PERFORM:
+ case CURLM_STATE_WAITPERFORM:
+ return Curl_single_getsock(data->easy_conn, socks, numsocks);
+ }
+
+}
+
+CURLMcode curl_multi_fdset(CURLM *multi_handle,
+ fd_set *read_fd_set, fd_set *write_fd_set,
+ fd_set *exc_fd_set, int *max_fd)
+{
+ /* Scan through all the easy handles to get the file descriptors set.
+ Some easy handles may not have connected to the remote host yet,
+ and then we must make sure that is done. */
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ int this_max_fd=-1;
+ curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
+ int bitmap;
+ int i;
+ (void)exc_fd_set; /* not used */
+
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ data=multi->easyp;
+ while(data) {
+ bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+
+ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ curl_socket_t s = CURL_SOCKET_BAD;
+
+ if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
+ FD_SET(sockbunch[i], read_fd_set);
+ s = sockbunch[i];
+ }
+ if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
+ FD_SET(sockbunch[i], write_fd_set);
+ s = sockbunch[i];
+ }
+ if(s == CURL_SOCKET_BAD)
+ /* this socket is unused, break out of loop */
+ break;
+ else {
+ if((int)s > this_max_fd)
+ this_max_fd = (int)s;
+ }
+ }
+
+ data = data->next; /* check next handle */
+ }
+
+ *max_fd = this_max_fd;
+
+ return CURLM_OK;
+}
+
+CURLMcode curl_multi_wait(CURLM *multi_handle,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
+ int bitmap;
+ unsigned int i;
+ unsigned int nfds = 0;
+ unsigned int curlfds;
+ struct pollfd *ufds = NULL;
+ long timeout_internal;
+
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ /* If the internally desired timeout is actually shorter than requested from
+ the outside, then use the shorter time! But only if the internal timer
+ is actually larger than -1! */
+ (void)multi_timeout(multi, &timeout_internal);
+ if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
+ timeout_ms = (int)timeout_internal;
+
+ /* Count up how many fds we have from the multi handle */
+ data=multi->easyp;
+ while(data) {
+ bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+
+ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ curl_socket_t s = CURL_SOCKET_BAD;
+
+ if(bitmap & GETSOCK_READSOCK(i)) {
+ ++nfds;
+ s = sockbunch[i];
+ }
+ if(bitmap & GETSOCK_WRITESOCK(i)) {
+ ++nfds;
+ s = sockbunch[i];
+ }
+ if(s == CURL_SOCKET_BAD) {
+ break;
+ }
+ }
+
+ data = data->next; /* check next handle */
+ }
+
+ curlfds = nfds; /* number of internal file descriptors */
+ nfds += extra_nfds; /* add the externally provided ones */
+
+ if(nfds || extra_nfds) {
+ ufds = malloc(nfds * sizeof(struct pollfd));
+ if(!ufds)
+ return CURLM_OUT_OF_MEMORY;
+ }
+ nfds = 0;
+
+ /* only do the second loop if we found descriptors in the first stage run
+ above */
+
+ if(curlfds) {
+ /* Add the curl handles to our pollfds first */
+ data=multi->easyp;
+ while(data) {
+ bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+
+ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ curl_socket_t s = CURL_SOCKET_BAD;
+
+ if(bitmap & GETSOCK_READSOCK(i)) {
+ ufds[nfds].fd = sockbunch[i];
+ ufds[nfds].events = POLLIN;
+ ++nfds;
+ s = sockbunch[i];
+ }
+ if(bitmap & GETSOCK_WRITESOCK(i)) {
+ ufds[nfds].fd = sockbunch[i];
+ ufds[nfds].events = POLLOUT;
+ ++nfds;
+ s = sockbunch[i];
+ }
+ if(s == CURL_SOCKET_BAD) {
+ break;
+ }
+ }
+
+ data = data->next; /* check next handle */
+ }
+ }
+
+ /* Add external file descriptions from poll-like struct curl_waitfd */
+ for(i = 0; i < extra_nfds; i++) {
+ ufds[nfds].fd = extra_fds[i].fd;
+ ufds[nfds].events = 0;
+ if(extra_fds[i].events & CURL_WAIT_POLLIN)
+ ufds[nfds].events |= POLLIN;
+ if(extra_fds[i].events & CURL_WAIT_POLLPRI)
+ ufds[nfds].events |= POLLPRI;
+ if(extra_fds[i].events & CURL_WAIT_POLLOUT)
+ ufds[nfds].events |= POLLOUT;
+ ++nfds;
+ }
+
+ if(nfds) {
+ /* wait... */
+ infof(data, "Curl_poll(%d ds, %d ms)\n", nfds, timeout_ms);
+ i = Curl_poll(ufds, nfds, timeout_ms);
+
+ if(i) {
+ unsigned int j;
+ /* copy revents results from the poll to the curl_multi_wait poll
+ struct, the bit values of the actual underlying poll() implementation
+ may not be the same as the ones in the public libcurl API! */
+ for(j = 0; j < extra_nfds; j++) {
+ unsigned short mask = 0;
+ unsigned r = ufds[curlfds + j].revents;
+
+ if(r & POLLIN)
+ mask |= CURL_WAIT_POLLIN;
+ if(r & POLLOUT)
+ mask |= CURL_WAIT_POLLOUT;
+ if(r & POLLPRI)
+ mask |= CURL_WAIT_POLLPRI;
+
+ extra_fds[j].revents = mask;
+ }
+ }
+ }
+ else
+ i = 0;
+
+ Curl_safefree(ufds);
+ if(ret)
+ *ret = i;
+ return CURLM_OK;
+}
+
+static CURLMcode multi_runsingle(struct Curl_multi *multi,
+ struct timeval now,
+ struct SessionHandle *data)
+{
+ struct Curl_message *msg = NULL;
+ bool connected;
+ bool async;
+ bool protocol_connect = FALSE;
+ bool dophase_done = FALSE;
+ bool done = FALSE;
+ CURLMcode result = CURLM_OK;
+ struct SingleRequest *k;
+ long timeout_ms;
+ int control;
+
+ if(!GOOD_EASY_HANDLE(data))
+ return CURLM_BAD_EASY_HANDLE;
+
+ do {
+ /* this is a single-iteration do-while loop just to allow a
+ break to skip to the end of it */
+ bool disconnect_conn = FALSE;
+
+ /* Handle the case when the pipe breaks, i.e., the connection
+ we're using gets cleaned up and we're left with nothing. */
+ if(data->state.pipe_broke) {
+ infof(data, "Pipe broke: handle 0x%p, url = %s\n",
+ (void *)data, data->state.path);
+
+ if(data->mstate < CURLM_STATE_COMPLETED) {
+ /* Head back to the CONNECT state */
+ multistate(data, CURLM_STATE_CONNECT);
+ result = CURLM_CALL_MULTI_PERFORM;
+ data->result = CURLE_OK;
+ }
+
+ data->state.pipe_broke = FALSE;
+ data->easy_conn = NULL;
+ break;
+ }
+
+ if(!data->easy_conn &&
+ data->mstate > CURLM_STATE_CONNECT &&
+ data->mstate < CURLM_STATE_DONE) {
+ /* In all these states, the code will blindly access 'data->easy_conn'
+ so this is precaution that it isn't NULL. And it silences static
+ analyzers. */
+ failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
+ return CURLM_INTERNAL_ERROR;
+ }
+
+ if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
+ data->mstate < CURLM_STATE_COMPLETED)
+ /* Make sure we set the connection's current owner */
+ data->easy_conn->data = data;
+
+ if(data->easy_conn &&
+ (data->mstate >= CURLM_STATE_CONNECT) &&
+ (data->mstate < CURLM_STATE_COMPLETED)) {
+ /* we need to wait for the connect state as only then is the start time
+ stored, but we must not check already completed handles */
+
+ timeout_ms = Curl_timeleft(data, &now,
+ (data->mstate <= CURLM_STATE_WAITDO)?
+ TRUE:FALSE);
+
+ if(timeout_ms < 0) {
+ /* Handle timed out */
+ if(data->mstate == CURLM_STATE_WAITRESOLVE)
+ failf(data, "Resolving timed out after %ld milliseconds",
+ Curl_tvdiff(now, data->progress.t_startsingle));
+ else if(data->mstate == CURLM_STATE_WAITCONNECT)
+ failf(data, "Connection timed out after %ld milliseconds",
+ Curl_tvdiff(now, data->progress.t_startsingle));
+ else {
+ k = &data->req;
+ if(k->size != -1) {
+ failf(data, "Operation timed out after %ld milliseconds with %"
+ CURL_FORMAT_CURL_OFF_T " out of %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_tvdiff(k->now, data->progress.t_startsingle),
+ k->bytecount, k->size);
+ }
+ else {
+ failf(data, "Operation timed out after %ld milliseconds with %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_tvdiff(now, data->progress.t_startsingle),
+ k->bytecount);
+ }
+ }
+
+ /* Force the connection closed because the server could continue to
+ send us stuff at any time. (The disconnect_conn logic used below
+ doesn't work at this point). */
+ connclose(data->easy_conn, "Disconnected with pending data");
+ data->result = CURLE_OPERATION_TIMEDOUT;
+ multistate(data, CURLM_STATE_COMPLETED);
+ break;
+ }
+ }
+
+ switch(data->mstate) {
+ case CURLM_STATE_INIT:
+ /* init this transfer. */
+ data->result=Curl_pretransfer(data);
+
+ if(CURLE_OK == data->result) {
+ /* after init, go CONNECT */
+ multistate(data, CURLM_STATE_CONNECT);
+ Curl_pgrsTime(data, TIMER_STARTOP);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ break;
+
+ case CURLM_STATE_CONNECT_PEND:
+ /* We will stay here until there is a connection available. Then
+ we try again in the CURLM_STATE_CONNECT state. */
+ break;
+
+ case CURLM_STATE_CONNECT:
+ /* Connect. We want to get a connection identifier filled in. */
+ Curl_pgrsTime(data, TIMER_STARTSINGLE);
+ data->result = Curl_connect(data, &data->easy_conn,
+ &async, &protocol_connect);
+ if(CURLE_NO_CONNECTION_AVAILABLE == data->result) {
+ /* There was no connection available. We will go to the pending
+ state and wait for an available connection. */
+ multistate(data, CURLM_STATE_CONNECT_PEND);
+
+ /* add this handle to the list of connect-pending handles */
+ if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data))
+ data->result = CURLE_OUT_OF_MEMORY;
+ else
+ data->result = CURLE_OK;
+ break;
+ }
+
+ if(CURLE_OK == data->result) {
+ /* Add this handle to the send or pend pipeline */
+ data->result = Curl_add_handle_to_pipeline(data, data->easy_conn);
+ if(CURLE_OK != data->result)
+ disconnect_conn = TRUE;
+ else {
+ if(async)
+ /* We're now waiting for an asynchronous name lookup */
+ multistate(data, CURLM_STATE_WAITRESOLVE);
+ else {
+ /* after the connect has been sent off, go WAITCONNECT unless the
+ protocol connect is already done and we can go directly to
+ WAITDO or DO! */
+ result = CURLM_CALL_MULTI_PERFORM;
+
+ if(protocol_connect)
+ multistate(data, multi->pipelining_enabled?
+ CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ else {
+#ifndef CURL_DISABLE_HTTP
+ if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+ multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ else
+#endif
+ multistate(data, CURLM_STATE_WAITCONNECT);
+ }
+ }
+ }
+ }
+ break;
+
+ case CURLM_STATE_WAITRESOLVE:
+ /* awaiting an asynch name resolve to complete */
+ {
+ struct Curl_dns_entry *dns = NULL;
+ struct connectdata *conn = data->easy_conn;
+ int stale;
+
+ /* check if we have the name resolved by now */
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ dns = Curl_fetch_addr(conn, conn->host.name, (int)conn->port, &stale);
+
+ if(dns) {
+ dns->inuse++; /* we use it! */
+#ifdef CURLRES_ASYNCH
+ conn->async.dns = dns;
+ conn->async.done = TRUE;
+#endif
+ data->result = CURLRESOLV_RESOLVED;
+ infof(data, "Hostname was found in DNS cache\n");
+ }
+ if(stale)
+ infof(data, "Hostname in DNS cache was stale, zapped\n");
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ if(!dns)
+ data->result = Curl_resolver_is_resolved(data->easy_conn, &dns);
+
+ /* Update sockets here, because the socket(s) may have been
+ closed and the application thus needs to be told, even if it
+ is likely that the same socket(s) will again be used further
+ down. If the name has not yet been resolved, it is likely
+ that new sockets have been opened in an attempt to contact
+ another resolver. */
+ singlesocket(multi, data);
+
+ if(dns) {
+ /* Perform the next step in the connection phase, and then move on
+ to the WAITCONNECT state */
+ data->result = Curl_async_resolved(data->easy_conn,
+ &protocol_connect);
+
+ if(CURLE_OK != data->result)
+ /* if Curl_async_resolved() returns failure, the connection struct
+ is already freed and gone */
+ data->easy_conn = NULL; /* no more connection */
+ else {
+ /* call again please so that we get the next socket setup */
+ result = CURLM_CALL_MULTI_PERFORM;
+ if(protocol_connect)
+ multistate(data, multi->pipelining_enabled?
+ CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ else {
+#ifndef CURL_DISABLE_HTTP
+ if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+ multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ else
+#endif
+ multistate(data, CURLM_STATE_WAITCONNECT);
+ }
+ }
+ }
+
+ if(CURLE_OK != data->result) {
+ /* failure detected */
+ disconnect_conn = TRUE;
+ break;
+ }
+ }
+ break;
+
+#ifndef CURL_DISABLE_HTTP
+ case CURLM_STATE_WAITPROXYCONNECT:
+ /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
+ data->result = Curl_http_connect(data->easy_conn, &protocol_connect);
+
+ if(data->easy_conn->bits.proxy_connect_closed) {
+ /* connect back to proxy again */
+ data->result = CURLE_OK;
+ result = CURLM_CALL_MULTI_PERFORM;
+ multistate(data, CURLM_STATE_CONNECT);
+ }
+ else if(CURLE_OK == data->result) {
+ if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
+ multistate(data, CURLM_STATE_WAITCONNECT);
+ }
+ break;
+#endif
+
+ case CURLM_STATE_WAITCONNECT:
+ /* awaiting a completion of an asynch connect */
+ data->result = Curl_is_connected(data->easy_conn,
+ FIRSTSOCKET,
+ &connected);
+ if(connected) {
+
+ if(!data->result)
+ /* if everything is still fine we do the protocol-specific connect
+ setup */
+ data->result = Curl_protocol_connect(data->easy_conn,
+ &protocol_connect);
+ }
+
+ if(data->easy_conn->bits.proxy_connect_closed) {
+ /* connect back to proxy again since it was closed in a proxy CONNECT
+ setup */
+ data->result = CURLE_OK;
+ result = CURLM_CALL_MULTI_PERFORM;
+ multistate(data, CURLM_STATE_CONNECT);
+ break;
+ }
+ else if(CURLE_OK != data->result) {
+ /* failure detected */
+ /* Just break, the cleaning up is handled all in one place */
+ disconnect_conn = TRUE;
+ break;
+ }
+
+ if(connected) {
+ if(!protocol_connect) {
+ /* We have a TCP connection, but 'protocol_connect' may be false
+ and then we continue to 'STATE_PROTOCONNECT'. If protocol
+ connect is TRUE, we move on to STATE_DO.
+ BUT if we are using a proxy we must change to WAITPROXYCONNECT
+ */
+#ifndef CURL_DISABLE_HTTP
+ if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
+ multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ else
+#endif
+ multistate(data, CURLM_STATE_PROTOCONNECT);
+
+ }
+ else
+ /* after the connect has completed, go WAITDO or DO */
+ multistate(data, multi->pipelining_enabled?
+ CURLM_STATE_WAITDO:CURLM_STATE_DO);
+
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ break;
+
+ case CURLM_STATE_PROTOCONNECT:
+ /* protocol-specific connect phase */
+ data->result = Curl_protocol_connecting(data->easy_conn,
+ &protocol_connect);
+ if((data->result == CURLE_OK) && protocol_connect) {
+ /* after the connect has completed, go WAITDO or DO */
+ multistate(data, multi->pipelining_enabled?
+ CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ else if(data->result) {
+ /* failure detected */
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, data->result, TRUE);
+ disconnect_conn = TRUE;
+ }
+ break;
+
+ case CURLM_STATE_WAITDO:
+ /* Wait for our turn to DO when we're pipelining requests */
+#ifdef DEBUGBUILD
+ infof(data, "WAITDO: Conn %ld send pipe %zu inuse %s athead %s\n",
+ data->easy_conn->connection_id,
+ data->easy_conn->send_pipe->size,
+ data->easy_conn->writechannel_inuse?"TRUE":"FALSE",
+ isHandleAtHead(data,
+ data->easy_conn->send_pipe)?"TRUE":"FALSE");
+#endif
+ if(!data->easy_conn->writechannel_inuse &&
+ isHandleAtHead(data,
+ data->easy_conn->send_pipe)) {
+ /* Grab the channel */
+ data->easy_conn->writechannel_inuse = TRUE;
+ multistate(data, CURLM_STATE_DO);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ break;
+
+ case CURLM_STATE_DO:
+ if(data->set.connect_only) {
+ /* keep connection open for application to use the socket */
+ connkeep(data->easy_conn, "CONNECT_ONLY");
+ multistate(data, CURLM_STATE_DONE);
+ data->result = CURLE_OK;
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ else {
+ /* Perform the protocol's DO action */
+ data->result = Curl_do(&data->easy_conn, &dophase_done);
+
+ /* When Curl_do() returns failure, data->easy_conn might be NULL! */
+
+ if(CURLE_OK == data->result) {
+ if(!dophase_done) {
+ /* some steps needed for wildcard matching */
+ if(data->set.wildcardmatch) {
+ struct WildcardData *wc = &data->wildcard;
+ if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
+ /* skip some states if it is important */
+ Curl_done(&data->easy_conn, CURLE_OK, FALSE);
+ multistate(data, CURLM_STATE_DONE);
+ result = CURLM_CALL_MULTI_PERFORM;
+ break;
+ }
+ }
+ /* DO was not completed in one function call, we must continue
+ DOING... */
+ multistate(data, CURLM_STATE_DOING);
+ result = CURLM_OK;
+ }
+
+ /* after DO, go DO_DONE... or DO_MORE */
+ else if(data->easy_conn->bits.do_more) {
+ /* we're supposed to do more, but we need to sit down, relax
+ and wait a little while first */
+ multistate(data, CURLM_STATE_DO_MORE);
+ result = CURLM_OK;
+ }
+ else {
+ /* we're done with the DO, now DO_DONE */
+ multistate(data, CURLM_STATE_DO_DONE);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
+ else if((CURLE_SEND_ERROR == data->result) &&
+ data->easy_conn->bits.reuse) {
+ /*
+ * In this situation, a connection that we were trying to use
+ * may have unexpectedly died. If possible, send the connection
+ * back to the CONNECT phase so we can try again.
+ */
+ char *newurl = NULL;
+ followtype follow=FOLLOW_NONE;
+ CURLcode drc;
+ bool retry = FALSE;
+
+ drc = Curl_retry_request(data->easy_conn, &newurl);
+ if(drc) {
+ /* a failure here pretty much implies an out of memory */
+ data->result = drc;
+ disconnect_conn = TRUE;
+ }
+ else
+ retry = (newurl)?TRUE:FALSE;
+
+ Curl_posttransfer(data);
+ drc = Curl_done(&data->easy_conn, data->result, FALSE);
+
+ /* When set to retry the connection, we must to go back to
+ * the CONNECT state */
+ if(retry) {
+ if((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
+ follow = FOLLOW_RETRY;
+ drc = Curl_follow(data, newurl, follow);
+ if(drc == CURLE_OK) {
+ multistate(data, CURLM_STATE_CONNECT);
+ result = CURLM_CALL_MULTI_PERFORM;
+ data->result = CURLE_OK;
+ }
+ else {
+ /* Follow failed */
+ data->result = drc;
+ free(newurl);
+ }
+ }
+ else {
+ /* done didn't return OK or SEND_ERROR */
+ data->result = drc;
+ free(newurl);
+ }
+ }
+ else {
+ /* Have error handler disconnect conn if we can't retry */
+ disconnect_conn = TRUE;
+ }
+ }
+ else {
+ /* failure detected */
+ Curl_posttransfer(data);
+ if(data->easy_conn)
+ Curl_done(&data->easy_conn, data->result, FALSE);
+ disconnect_conn = TRUE;
+ }
+ }
+ break;
+
+ case CURLM_STATE_DOING:
+ /* we continue DOING until the DO phase is complete */
+ data->result = Curl_protocol_doing(data->easy_conn,
+ &dophase_done);
+ if(CURLE_OK == data->result) {
+ if(dophase_done) {
+ /* after DO, go DO_DONE or DO_MORE */
+ multistate(data, data->easy_conn->bits.do_more?
+ CURLM_STATE_DO_MORE:
+ CURLM_STATE_DO_DONE);
+ result = CURLM_CALL_MULTI_PERFORM;
+ } /* dophase_done */
+ }
+ else {
+ /* failure detected */
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, data->result, FALSE);
+ disconnect_conn = TRUE;
+ }
+ break;
+
+ case CURLM_STATE_DO_MORE:
+ /*
+ * When we are connected, DO MORE and then go DO_DONE
+ */
+ data->result = Curl_do_more(data->easy_conn, &control);
+
+ /* No need to remove this handle from the send pipeline here since that
+ is done in Curl_done() */
+ if(CURLE_OK == data->result) {
+ if(control) {
+ /* if positive, advance to DO_DONE
+ if negative, go back to DOING */
+ multistate(data, control==1?
+ CURLM_STATE_DO_DONE:
+ CURLM_STATE_DOING);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ else
+ /* stay in DO_MORE */
+ result = CURLM_OK;
+ }
+ else {
+ /* failure detected */
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, data->result, FALSE);
+ disconnect_conn = TRUE;
+ }
+ break;
+
+ case CURLM_STATE_DO_DONE:
+ /* Move ourselves from the send to recv pipeline */
+ Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
+ /* Check if we can move pending requests to send pipe */
+ Curl_multi_process_pending_handles(multi);
+
+ /* Only perform the transfer if there's a good socket to work with.
+ Having both BAD is a signal to skip immediately to DONE */
+ if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
+ (data->easy_conn->writesockfd != CURL_SOCKET_BAD))
+ multistate(data, CURLM_STATE_WAITPERFORM);
+ else
+ multistate(data, CURLM_STATE_DONE);
+ result = CURLM_CALL_MULTI_PERFORM;
+ break;
+
+ case CURLM_STATE_WAITPERFORM:
+ /* Wait for our turn to PERFORM */
+ if(!data->easy_conn->readchannel_inuse &&
+ isHandleAtHead(data,
+ data->easy_conn->recv_pipe)) {
+ /* Grab the channel */
+ data->easy_conn->readchannel_inuse = TRUE;
+ multistate(data, CURLM_STATE_PERFORM);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+#ifdef DEBUGBUILD
+ else {
+ infof(data, "WAITPERFORM: Conn %ld recv pipe %zu inuse %s athead %s\n",
+ data->easy_conn->connection_id,
+ data->easy_conn->recv_pipe->size,
+ data->easy_conn->readchannel_inuse?"TRUE":"FALSE",
+ isHandleAtHead(data,
+ data->easy_conn->recv_pipe)?"TRUE":"FALSE");
+ }
+#endif
+ break;
+
+ case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
+ /* if both rates are within spec, resume transfer */
+ if(Curl_pgrsUpdate(data->easy_conn))
+ data->result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ data->result = Curl_speedcheck(data, now);
+
+ if(( (data->set.max_send_speed == 0) ||
+ (data->progress.ulspeed < data->set.max_send_speed )) &&
+ ( (data->set.max_recv_speed == 0) ||
+ (data->progress.dlspeed < data->set.max_recv_speed)))
+ multistate(data, CURLM_STATE_PERFORM);
+ break;
+
+ case CURLM_STATE_PERFORM:
+ {
+ char *newurl = NULL;
+ bool retry = FALSE;
+
+ /* check if over send speed */
+ if((data->set.max_send_speed > 0) &&
+ (data->progress.ulspeed > data->set.max_send_speed)) {
+ int buffersize;
+
+ multistate(data, CURLM_STATE_TOOFAST);
+
+ /* calculate upload rate-limitation timeout. */
+ buffersize = (int)(data->set.buffer_size ?
+ data->set.buffer_size : BUFSIZE);
+ timeout_ms = Curl_sleep_time(data->set.max_send_speed,
+ data->progress.ulspeed, buffersize);
+ Curl_expire_latest(data, timeout_ms);
+ break;
+ }
+
+ /* check if over recv speed */
+ if((data->set.max_recv_speed > 0) &&
+ (data->progress.dlspeed > data->set.max_recv_speed)) {
+ int buffersize;
+
+ multistate(data, CURLM_STATE_TOOFAST);
+
+ /* Calculate download rate-limitation timeout. */
+ buffersize = (int)(data->set.buffer_size ?
+ data->set.buffer_size : BUFSIZE);
+ timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
+ data->progress.dlspeed, buffersize);
+ Curl_expire_latest(data, timeout_ms);
+ break;
+ }
+
+ /* read/write data if it is ready to do so */
+ data->result = Curl_readwrite(data->easy_conn, &done);
+
+ k = &data->req;
+
+ if(!(k->keepon & KEEP_RECV)) {
+ /* We're done receiving */
+ data->easy_conn->readchannel_inuse = FALSE;
+ }
+
+ if(!(k->keepon & KEEP_SEND)) {
+ /* We're done sending */
+ data->easy_conn->writechannel_inuse = FALSE;
+ }
+
+ if(done || (data->result == CURLE_RECV_ERROR)) {
+ /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
+ * condition and the server closed the re-used connection exactly when
+ * we wanted to use it, so figure out if that is indeed the case.
+ */
+ CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
+ if(!ret)
+ retry = (newurl)?TRUE:FALSE;
+
+ if(retry) {
+ /* if we are to retry, set the result to OK and consider the
+ request as done */
+ data->result = CURLE_OK;
+ done = TRUE;
+ }
+ }
+
+ if(data->result) {
+ /*
+ * The transfer phase returned error, we mark the connection to get
+ * closed to prevent being re-used. This is because we can't possibly
+ * know if the connection is in a good shape or not now. Unless it is
+ * a protocol which uses two "channels" like FTP, as then the error
+ * happened in the data connection.
+ */
+
+ if(!(data->easy_conn->handler->flags & PROTOPT_DUAL))
+ connclose(data->easy_conn, "Transfer returned error");
+
+ Curl_posttransfer(data);
+ Curl_done(&data->easy_conn, data->result, FALSE);
+ }
+ else if(done) {
+ followtype follow=FOLLOW_NONE;
+
+ /* call this even if the readwrite function returned error */
+ Curl_posttransfer(data);
+
+ /* we're no longer receiving */
+ Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
+
+ /* expire the new receiving pipeline head */
+ if(data->easy_conn->recv_pipe->head)
+ Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1);
+
+ /* Check if we can move pending requests to send pipe */
+ Curl_multi_process_pending_handles(multi);
+
+ /* When we follow redirects or is set to retry the connection, we must
+ to go back to the CONNECT state */
+ if(data->req.newurl || retry) {
+ if(!retry) {
+ /* if the URL is a follow-location and not just a retried request
+ then figure out the URL here */
+ newurl = data->req.newurl;
+ data->req.newurl = NULL;
+ follow = FOLLOW_REDIR;
+ }
+ else
+ follow = FOLLOW_RETRY;
+ data->result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
+ if(CURLE_OK == data->result) {
+ data->result = Curl_follow(data, newurl, follow);
+ if(CURLE_OK == data->result) {
+ multistate(data, CURLM_STATE_CONNECT);
+ result = CURLM_CALL_MULTI_PERFORM;
+ newurl = NULL; /* handed over the memory ownership to
+ Curl_follow(), make sure we don't free() it
+ here */
+ }
+ }
+ }
+ else {
+ /* after the transfer is done, go DONE */
+
+ /* but first check to see if we got a location info even though we're
+ not following redirects */
+ if(data->req.location) {
+ if(newurl)
+ free(newurl);
+ newurl = data->req.location;
+ data->req.location = NULL;
+ data->result = Curl_follow(data, newurl, FOLLOW_FAKE);
+ if(CURLE_OK == data->result)
+ newurl = NULL; /* allocation was handed over Curl_follow() */
+ else
+ disconnect_conn = TRUE;
+ }
+
+ multistate(data, CURLM_STATE_DONE);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
+
+ if(newurl)
+ free(newurl);
+ break;
+ }
+
+ case CURLM_STATE_DONE:
+ /* this state is highly transient, so run another loop after this */
+ result = CURLM_CALL_MULTI_PERFORM;
+
+ if(data->easy_conn) {
+ CURLcode res;
+
+ /* Remove ourselves from the receive pipeline, if we are there. */
+ Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
+ /* Check if we can move pending requests to send pipe */
+ Curl_multi_process_pending_handles(multi);
+
+ /* post-transfer command */
+ res = Curl_done(&data->easy_conn, data->result, FALSE);
+
+ /* allow a previously set error code take precedence */
+ if(!data->result)
+ data->result = res;
+
+ /*
+ * If there are other handles on the pipeline, Curl_done won't set
+ * easy_conn to NULL. In such a case, curl_multi_remove_handle() can
+ * access free'd data, if the connection is free'd and the handle
+ * removed before we perform the processing in CURLM_STATE_COMPLETED
+ */
+ if(data->easy_conn)
+ data->easy_conn = NULL;
+ }
+
+ if(data->set.wildcardmatch) {
+ if(data->wildcard.state != CURLWC_DONE) {
+ /* if a wildcard is set and we are not ending -> lets start again
+ with CURLM_STATE_INIT */
+ multistate(data, CURLM_STATE_INIT);
+ break;
+ }
+ }
+
+ /* after we have DONE what we're supposed to do, go COMPLETED, and
+ it doesn't matter what the Curl_done() returned! */
+ multistate(data, CURLM_STATE_COMPLETED);
+ break;
+
+ case CURLM_STATE_COMPLETED:
+ /* this is a completed transfer, it is likely to still be connected */
+
+ /* This node should be delinked from the list now and we should post
+ an information message that we are complete. */
+
+ /* Important: reset the conn pointer so that we don't point to memory
+ that could be freed anytime */
+ data->easy_conn = NULL;
+
+ Curl_expire(data, 0); /* stop all timers */
+ break;
+
+ case CURLM_STATE_MSGSENT:
+ return CURLM_OK; /* do nothing */
+
+ default:
+ return CURLM_INTERNAL_ERROR;
+ }
+
+ if(data->mstate < CURLM_STATE_COMPLETED) {
+ if(CURLE_OK != data->result) {
+ /*
+ * If an error was returned, and we aren't in completed state now,
+ * then we go to completed and consider this transfer aborted.
+ */
+
+ /* NOTE: no attempt to disconnect connections must be made
+ in the case blocks above - cleanup happens only here */
+
+ data->state.pipe_broke = FALSE;
+
+ if(data->easy_conn) {
+ /* if this has a connection, unsubscribe from the pipelines */
+ data->easy_conn->writechannel_inuse = FALSE;
+ data->easy_conn->readchannel_inuse = FALSE;
+ Curl_removeHandleFromPipeline(data,
+ data->easy_conn->send_pipe);
+ Curl_removeHandleFromPipeline(data,
+ data->easy_conn->recv_pipe);
+ /* Check if we can move pending requests to send pipe */
+ Curl_multi_process_pending_handles(multi);
+
+ if(disconnect_conn) {
+ /* disconnect properly */
+ Curl_disconnect(data->easy_conn, /* dead_connection */ FALSE);
+
+ /* This is where we make sure that the easy_conn pointer is reset.
+ We don't have to do this in every case block above where a
+ failure is detected */
+ data->easy_conn = NULL;
+ }
+ }
+ else if(data->mstate == CURLM_STATE_CONNECT) {
+ /* Curl_connect() failed */
+ (void)Curl_posttransfer(data);
+ }
+
+ multistate(data, CURLM_STATE_COMPLETED);
+ }
+ /* if there's still a connection to use, call the progress function */
+ else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
+ /* aborted due to progress callback return code must close the
+ connection */
+ data->result = CURLE_ABORTED_BY_CALLBACK;
+ connclose(data->easy_conn, "Aborted by callback");
+
+ /* if not yet in DONE state, go there, otherwise COMPLETED */
+ multistate(data, (data->mstate < CURLM_STATE_DONE)?
+ CURLM_STATE_DONE: CURLM_STATE_COMPLETED);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
+ } WHILE_FALSE; /* just to break out from! */
+
+ if(CURLM_STATE_COMPLETED == data->mstate) {
+ /* now fill in the Curl_message with this info */
+ msg = &data->msg;
+
+ msg->extmsg.msg = CURLMSG_DONE;
+ msg->extmsg.easy_handle = data;
+ msg->extmsg.data.result = data->result;
+
+ result = multi_addmsg(multi, msg);
+
+ multistate(data, CURLM_STATE_MSGSENT);
+ }
+
+ return result;
+}
+
+
+CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ CURLMcode returncode=CURLM_OK;
+ struct Curl_tree *t;
+ struct timeval now = Curl_tvnow();
+
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ data=multi->easyp;
+ while(data) {
+ CURLMcode result;
+ struct WildcardData *wc = &data->wildcard;
+ SIGPIPE_VARIABLE(pipe_st);
+
+ if(data->set.wildcardmatch) {
+ if(!wc->filelist) {
+ CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
+ if(ret)
+ return CURLM_OUT_OF_MEMORY;
+ }
+ }
+
+ sigpipe_ignore(data, &pipe_st);
+ do
+ result = multi_runsingle(multi, now, data);
+ while(CURLM_CALL_MULTI_PERFORM == result);
+ sigpipe_restore(&pipe_st);
+
+ if(data->set.wildcardmatch) {
+ /* destruct wildcard structures if it is needed */
+ if(wc->state == CURLWC_DONE || result)
+ Curl_wildcard_dtor(wc);
+ }
+
+ if(result)
+ returncode = result;
+
+ data = data->next; /* operate on next handle */
+ }
+
+ /*
+ * Simply remove all expired timers from the splay since handles are dealt
+ * with unconditionally by this function and curl_multi_timeout() requires
+ * that already passed/handled expire times are removed from the splay.
+ *
+ * It is important that the 'now' value is set at the entry of this function
+ * and not for the current time as it may have ticked a little while since
+ * then and then we risk this loop to remove timers that actually have not
+ * been handled!
+ */
+ do {
+ multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
+ if(t)
+ /* the removed may have another timeout in queue */
+ (void)add_next_timeout(now, multi, t->payload);
+
+ } while(t);
+
+ *running_handles = multi->num_alive;
+
+ if(CURLM_OK >= returncode)
+ update_timer(multi);
+
+ return returncode;
+}
+
+static void close_all_connections(struct Curl_multi *multi)
+{
+ struct connectdata *conn;
+
+ conn = Curl_conncache_find_first_connection(multi->conn_cache);
+ while(conn) {
+ SIGPIPE_VARIABLE(pipe_st);
+ conn->data = multi->closure_handle;
+
+ sigpipe_ignore(conn->data, &pipe_st);
+ /* This will remove the connection from the cache */
+ (void)Curl_disconnect(conn, FALSE);
+ sigpipe_restore(&pipe_st);
+
+ conn = Curl_conncache_find_first_connection(multi->conn_cache);
+ }
+}
+
+CURLMcode curl_multi_cleanup(CURLM *multi_handle)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ struct SessionHandle *nextdata;
+
+ if(GOOD_MULTI_HANDLE(multi)) {
+ bool restore_pipe = FALSE;
+ SIGPIPE_VARIABLE(pipe_st);
+
+ multi->type = 0; /* not good anymore */
+
+ /* Close all the connections in the connection cache */
+ close_all_connections(multi);
+
+ if(multi->closure_handle) {
+ sigpipe_ignore(multi->closure_handle, &pipe_st);
+ restore_pipe = TRUE;
+
+ multi->closure_handle->dns.hostcache = multi->hostcache;
+ Curl_hostcache_clean(multi->closure_handle,
+ multi->closure_handle->dns.hostcache);
+
+ Curl_close(multi->closure_handle);
+ }
+
+ Curl_hash_destroy(multi->sockhash);
+ Curl_conncache_destroy(multi->conn_cache);
+ Curl_llist_destroy(multi->msglist, NULL);
+ Curl_llist_destroy(multi->pending, NULL);
+
+ /* remove all easy handles */
+ data = multi->easyp;
+ while(data) {
+ nextdata=data->next;
+ if(data->dns.hostcachetype == HCACHE_MULTI) {
+ /* clear out the usage of the shared DNS cache */
+ Curl_hostcache_clean(data, data->dns.hostcache);
+ data->dns.hostcache = NULL;
+ data->dns.hostcachetype = HCACHE_NONE;
+ }
+
+ /* Clear the pointer to the connection cache */
+ data->state.conn_cache = NULL;
+ data->multi = NULL; /* clear the association */
+
+ data = nextdata;
+ }
+
+ Curl_hash_destroy(multi->hostcache);
+
+ /* Free the blacklists by setting them to NULL */
+ Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
+ Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
+
+ free(multi);
+ if(restore_pipe)
+ sigpipe_restore(&pipe_st);
+
+ return CURLM_OK;
+ }
+ else
+ return CURLM_BAD_HANDLE;
+}
+
+/*
+ * curl_multi_info_read()
+ *
+ * This function is the primary way for a multi/multi_socket application to
+ * figure out if a transfer has ended. We MUST make this function as fast as
+ * possible as it will be polled frequently and we MUST NOT scan any lists in
+ * here to figure out things. We must scale fine to thousands of handles and
+ * beyond. The current design is fully O(1).
+ */
+
+CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct Curl_message *msg;
+
+ *msgs_in_queue = 0; /* default to none */
+
+ if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
+ /* there is one or more messages in the list */
+ struct curl_llist_element *e;
+
+ /* extract the head of the list to return */
+ e = multi->msglist->head;
+
+ msg = e->ptr;
+
+ /* remove the extracted entry */
+ Curl_llist_remove(multi->msglist, e, NULL);
+
+ *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
+
+ return &msg->extmsg;
+ }
+ else
+ return NULL;
+}
+
+/*
+ * singlesocket() checks what sockets we deal with and their "action state"
+ * and if we have a different state in any of those sockets from last time we
+ * call the callback accordingly.
+ */
+static void singlesocket(struct Curl_multi *multi,
+ struct SessionHandle *data)
+{
+ curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
+ int i;
+ struct Curl_sh_entry *entry;
+ curl_socket_t s;
+ int num;
+ unsigned int curraction;
+ bool remove_sock_from_hash;
+
+ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
+ socks[i] = CURL_SOCKET_BAD;
+
+ /* Fill in the 'current' struct with the state as it is now: what sockets to
+ supervise and for what actions */
+ curraction = multi_getsock(data, socks, MAX_SOCKSPEREASYHANDLE);
+
+ /* We have 0 .. N sockets already and we get to know about the 0 .. M
+ sockets we should have from now on. Detect the differences, remove no
+ longer supervised ones and add new ones */
+
+ /* walk over the sockets we got right now */
+ for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
+ (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
+ i++) {
+ int action = CURL_POLL_NONE;
+
+ s = socks[i];
+
+ /* get it from the hash */
+ entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+ if(curraction & GETSOCK_READSOCK(i))
+ action |= CURL_POLL_IN;
+ if(curraction & GETSOCK_WRITESOCK(i))
+ action |= CURL_POLL_OUT;
+
+ if(entry) {
+ /* yeps, already present so check if it has the same action set */
+ if(entry->action == action)
+ /* same, continue */
+ continue;
+ }
+ else {
+ /* this is a socket we didn't have before, add it! */
+ entry = sh_addentry(multi->sockhash, s, data);
+ if(!entry)
+ /* fatal */
+ return;
+ }
+
+ /* we know (entry != NULL) at this point, see the logic above */
+ if(multi->socket_cb)
+ multi->socket_cb(data,
+ s,
+ action,
+ multi->socket_userp,
+ entry->socketp);
+
+ entry->action = action; /* store the current action state */
+ }
+
+ num = i; /* number of sockets */
+
+ /* when we've walked over all the sockets we should have right now, we must
+ make sure to detect sockets that are removed */
+ for(i=0; i< data->numsocks; i++) {
+ int j;
+ s = data->sockets[i];
+ for(j=0; j<num; j++) {
+ if(s == socks[j]) {
+ /* this is still supervised */
+ s = CURL_SOCKET_BAD;
+ break;
+ }
+ }
+ if(s != CURL_SOCKET_BAD) {
+
+ /* this socket has been removed. Tell the app to remove it */
+ remove_sock_from_hash = TRUE;
+
+ entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+ if(entry) {
+ /* check if the socket to be removed serves a connection which has
+ other easy-s in a pipeline. In this case the socket should not be
+ removed. */
+ struct connectdata *easy_conn = data->easy_conn;
+ if(easy_conn) {
+ if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
+ /* the handle should not be removed from the pipe yet */
+ remove_sock_from_hash = FALSE;
+
+ /* Update the sockhash entry to instead point to the next in line
+ for the recv_pipe, or the first (in case this particular easy
+ isn't already) */
+ if(entry->easy == data) {
+ if(isHandleAtHead(data, easy_conn->recv_pipe))
+ entry->easy = easy_conn->recv_pipe->head->next->ptr;
+ else
+ entry->easy = easy_conn->recv_pipe->head->ptr;
+ }
+ }
+ if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) {
+ /* the handle should not be removed from the pipe yet */
+ remove_sock_from_hash = FALSE;
+
+ /* Update the sockhash entry to instead point to the next in line
+ for the send_pipe, or the first (in case this particular easy
+ isn't already) */
+ if(entry->easy == data) {
+ if(isHandleAtHead(data, easy_conn->send_pipe))
+ entry->easy = easy_conn->send_pipe->head->next->ptr;
+ else
+ entry->easy = easy_conn->send_pipe->head->ptr;
+ }
+ }
+ /* Don't worry about overwriting recv_pipe head with send_pipe_head,
+ when action will be asked on the socket (see multi_socket()), the
+ head of the correct pipe will be taken according to the
+ action. */
+ }
+ }
+ else
+ /* just a precaution, this socket really SHOULD be in the hash already
+ but in case it isn't, we don't have to tell the app to remove it
+ either since it never got to know about it */
+ remove_sock_from_hash = FALSE;
+
+ if(remove_sock_from_hash) {
+ /* in this case 'entry' is always non-NULL */
+ if(multi->socket_cb)
+ multi->socket_cb(data,
+ s,
+ CURL_POLL_REMOVE,
+ multi->socket_userp,
+ entry->socketp);
+ sh_delentry(multi->sockhash, s);
+ }
+
+ }
+ }
+
+ memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
+ data->numsocks = num;
+}
+
+/*
+ * Curl_multi_closed()
+ *
+ * Used by the connect code to tell the multi_socket code that one of the
+ * sockets we were using have just been closed. This function will then
+ * remove it from the sockethash for this handle to make the multi_socket API
+ * behave properly, especially for the case when libcurl will create another
+ * socket again and it gets the same file descriptor number.
+ */
+
+void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
+{
+ struct Curl_multi *multi = conn->data->multi;
+ if(multi) {
+ /* this is set if this connection is part of a handle that is added to
+ a multi handle, and only then this is necessary */
+ struct Curl_sh_entry *entry =
+ Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+ if(entry) {
+ if(multi->socket_cb)
+ multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
+ multi->socket_userp,
+ entry->socketp);
+
+ /* now remove it from the socket hash */
+ sh_delentry(multi->sockhash, s);
+ }
+ }
+}
+
+
+
+/*
+ * add_next_timeout()
+ *
+ * Each SessionHandle has a list of timeouts. The add_next_timeout() is called
+ * when it has just been removed from the splay tree because the timeout has
+ * expired. This function is then to advance in the list to pick the next
+ * timeout to use (skip the already expired ones) and add this node back to
+ * the splay tree again.
+ *
+ * The splay tree only has each sessionhandle as a single node and the nearest
+ * timeout is used to sort it on.
+ */
+static CURLMcode add_next_timeout(struct timeval now,
+ struct Curl_multi *multi,
+ struct SessionHandle *d)
+{
+ struct timeval *tv = &d->state.expiretime;
+ struct curl_llist *list = d->state.timeoutlist;
+ struct curl_llist_element *e;
+
+ /* move over the timeout list for this specific handle and remove all
+ timeouts that are now passed tense and store the next pending
+ timeout in *tv */
+ for(e = list->head; e; ) {
+ struct curl_llist_element *n = e->next;
+ long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
+ if(diff <= 0)
+ /* remove outdated entry */
+ Curl_llist_remove(list, e, NULL);
+ else
+ /* the list is sorted so get out on the first mismatch */
+ break;
+ e = n;
+ }
+ e = list->head;
+ if(!e) {
+ /* clear the expire times within the handles that we remove from the
+ splay tree */
+ tv->tv_sec = 0;
+ tv->tv_usec = 0;
+ }
+ else {
+ /* copy the first entry to 'tv' */
+ memcpy(tv, e->ptr, sizeof(*tv));
+
+ /* remove first entry from list */
+ Curl_llist_remove(list, e, NULL);
+
+ /* insert this node again into the splay */
+ multi->timetree = Curl_splayinsert(*tv, multi->timetree,
+ &d->state.timenode);
+ }
+ return CURLM_OK;
+}
+
+static CURLMcode multi_socket(struct Curl_multi *multi,
+ bool checkall,
+ curl_socket_t s,
+ int ev_bitmask,
+ int *running_handles)
+{
+ CURLMcode result = CURLM_OK;
+ struct SessionHandle *data = NULL;
+ struct Curl_tree *t;
+ struct timeval now = Curl_tvnow();
+
+ if(checkall) {
+ /* *perform() deals with running_handles on its own */
+ result = curl_multi_perform(multi, running_handles);
+
+ /* walk through each easy handle and do the socket state change magic
+ and callbacks */
+ if(result != CURLM_BAD_HANDLE) {
+ data=multi->easyp;
+ while(data) {
+ singlesocket(multi, data);
+ data = data->next;
+ }
+ }
+
+ /* or should we fall-through and do the timer-based stuff? */
+ return result;
+ }
+ else if(s != CURL_SOCKET_TIMEOUT) {
+
+ struct Curl_sh_entry *entry =
+ Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+ if(!entry)
+ /* Unmatched socket, we can't act on it but we ignore this fact. In
+ real-world tests it has been proved that libevent can in fact give
+ the application actions even though the socket was just previously
+ asked to get removed, so thus we better survive stray socket actions
+ and just move on. */
+ ;
+ else {
+ SIGPIPE_VARIABLE(pipe_st);
+
+ data = entry->easy;
+
+ if(data->magic != CURLEASY_MAGIC_NUMBER)
+ /* bad bad bad bad bad bad bad */
+ return CURLM_INTERNAL_ERROR;
+
+ /* If the pipeline is enabled, take the handle which is in the head of
+ the pipeline. If we should write into the socket, take the send_pipe
+ head. If we should read from the socket, take the recv_pipe head. */
+ if(data->easy_conn) {
+ if((ev_bitmask & CURL_POLL_OUT) &&
+ data->easy_conn->send_pipe &&
+ data->easy_conn->send_pipe->head)
+ data = data->easy_conn->send_pipe->head->ptr;
+ else if((ev_bitmask & CURL_POLL_IN) &&
+ data->easy_conn->recv_pipe &&
+ data->easy_conn->recv_pipe->head)
+ data = data->easy_conn->recv_pipe->head->ptr;
+ }
+
+ if(data->easy_conn &&
+ !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
+ /* set socket event bitmask if they're not locked */
+ data->easy_conn->cselect_bits = ev_bitmask;
+
+ sigpipe_ignore(data, &pipe_st);
+ do
+ result = multi_runsingle(multi, now, data);
+ while(CURLM_CALL_MULTI_PERFORM == result);
+ sigpipe_restore(&pipe_st);
+
+ if(data->easy_conn &&
+ !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
+ /* clear the bitmask only if not locked */
+ data->easy_conn->cselect_bits = 0;
+
+ if(CURLM_OK >= result)
+ /* get the socket(s) and check if the state has been changed since
+ last */
+ singlesocket(multi, data);
+
+ /* Now we fall-through and do the timer-based stuff, since we don't want
+ to force the user to have to deal with timeouts as long as at least
+ one connection in fact has traffic. */
+
+ data = NULL; /* set data to NULL again to avoid calling
+ multi_runsingle() in case there's no need to */
+ now = Curl_tvnow(); /* get a newer time since the multi_runsingle() loop
+ may have taken some time */
+ }
+ }
+ else {
+ /* Asked to run due to time-out. Clear the 'lastcall' variable to force
+ update_timer() to trigger a callback to the app again even if the same
+ timeout is still the one to run after this call. That handles the case
+ when the application asks libcurl to run the timeout prematurely. */
+ memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
+ }
+
+ /*
+ * The loop following here will go on as long as there are expire-times left
+ * to process in the splay and 'data' will be re-assigned for every expired
+ * handle we deal with.
+ */
+ do {
+ /* the first loop lap 'data' can be NULL */
+ if(data) {
+ SIGPIPE_VARIABLE(pipe_st);
+
+ sigpipe_ignore(data, &pipe_st);
+ do
+ result = multi_runsingle(multi, now, data);
+ while(CURLM_CALL_MULTI_PERFORM == result);
+ sigpipe_restore(&pipe_st);
+
+ if(CURLM_OK >= result)
+ /* get the socket(s) and check if the state has been changed since
+ last */
+ singlesocket(multi, data);
+ }
+
+ /* Check if there's one (more) expired timer to deal with! This function
+ extracts a matching node if there is one */
+
+ multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
+ if(t) {
+ data = t->payload; /* assign this for next loop */
+ (void)add_next_timeout(now, multi, t->payload);
+ }
+
+ } while(t);
+
+ *running_handles = multi->num_alive;
+ return result;
+}
+
+#undef curl_multi_setopt
+CURLMcode curl_multi_setopt(CURLM *multi_handle,
+ CURLMoption option, ...)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ CURLMcode res = CURLM_OK;
+ va_list param;
+
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ va_start(param, option);
+
+ switch(option) {
+ case CURLMOPT_SOCKETFUNCTION:
+ multi->socket_cb = va_arg(param, curl_socket_callback);
+ break;
+ case CURLMOPT_SOCKETDATA:
+ multi->socket_userp = va_arg(param, void *);
+ break;
+ case CURLMOPT_PIPELINING:
+ multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLMOPT_TIMERFUNCTION:
+ multi->timer_cb = va_arg(param, curl_multi_timer_callback);
+ break;
+ case CURLMOPT_TIMERDATA:
+ multi->timer_userp = va_arg(param, void *);
+ break;
+ case CURLMOPT_MAXCONNECTS:
+ multi->maxconnects = va_arg(param, long);
+ break;
+ case CURLMOPT_MAX_HOST_CONNECTIONS:
+ multi->max_host_connections = va_arg(param, long);
+ break;
+ case CURLMOPT_MAX_PIPELINE_LENGTH:
+ multi->max_pipeline_length = va_arg(param, long);
+ break;
+ case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
+ multi->content_length_penalty_size = va_arg(param, long);
+ break;
+ case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
+ multi->chunk_length_penalty_size = va_arg(param, long);
+ break;
+ case CURLMOPT_PIPELINING_SITE_BL:
+ res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
+ &multi->pipelining_site_bl);
+ break;
+ case CURLMOPT_PIPELINING_SERVER_BL:
+ res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
+ &multi->pipelining_server_bl);
+ break;
+ case CURLMOPT_MAX_TOTAL_CONNECTIONS:
+ multi->max_total_connections = va_arg(param, long);
+ break;
+ default:
+ res = CURLM_UNKNOWN_OPTION;
+ break;
+ }
+ va_end(param);
+ return res;
+}
+
+/* we define curl_multi_socket() in the public multi.h header */
+#undef curl_multi_socket
+
+CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+ int *running_handles)
+{
+ CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
+ 0, running_handles);
+ if(CURLM_OK >= result)
+ update_timer((struct Curl_multi *)multi_handle);
+ return result;
+}
+
+CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
+ int ev_bitmask, int *running_handles)
+{
+ CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
+ ev_bitmask, running_handles);
+ if(CURLM_OK >= result)
+ update_timer((struct Curl_multi *)multi_handle);
+ return result;
+}
+
+CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
+
+{
+ CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
+ TRUE, CURL_SOCKET_BAD, 0, running_handles);
+ if(CURLM_OK >= result)
+ update_timer((struct Curl_multi *)multi_handle);
+ return result;
+}
+
+static CURLMcode multi_timeout(struct Curl_multi *multi,
+ long *timeout_ms)
+{
+ static struct timeval tv_zero = {0,0};
+
+ if(multi->timetree) {
+ /* we have a tree of expire times */
+ struct timeval now = Curl_tvnow();
+
+ /* splay the lowest to the bottom */
+ multi->timetree = Curl_splay(tv_zero, multi->timetree);
+
+ if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
+ /* some time left before expiration */
+ *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
+ if(!*timeout_ms)
+ /*
+ * Since we only provide millisecond resolution on the returned value
+ * and the diff might be less than one millisecond here, we don't
+ * return zero as that may cause short bursts of busyloops on fast
+ * processors while the diff is still present but less than one
+ * millisecond! instead we return 1 until the time is ripe.
+ */
+ *timeout_ms=1;
+ }
+ else
+ /* 0 means immediately */
+ *timeout_ms = 0;
+ }
+ else
+ *timeout_ms = -1;
+
+ return CURLM_OK;
+}
+
+CURLMcode curl_multi_timeout(CURLM *multi_handle,
+ long *timeout_ms)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+
+ /* First, make some basic checks that the CURLM handle is a good handle */
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ return multi_timeout(multi, timeout_ms);
+}
+
+/*
+ * Tell the application it should update its timers, if it subscribes to the
+ * update timer callback.
+ */
+static int update_timer(struct Curl_multi *multi)
+{
+ long timeout_ms;
+
+ if(!multi->timer_cb)
+ return 0;
+ if(multi_timeout(multi, &timeout_ms)) {
+ return -1;
+ }
+ if(timeout_ms < 0) {
+ static const struct timeval none={0,0};
+ if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
+ multi->timer_lastcall = none;
+ /* there's no timeout now but there was one previously, tell the app to
+ disable it */
+ return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
+ }
+ return 0;
+ }
+
+ /* When multi_timeout() is done, multi->timetree points to the node with the
+ * timeout we got the (relative) time-out time for. We can thus easily check
+ * if this is the same (fixed) time as we got in a previous call and then
+ * avoid calling the callback again. */
+ if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
+ return 0;
+
+ multi->timer_lastcall = multi->timetree->key;
+
+ return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
+}
+
+void Curl_multi_set_easy_connection(struct SessionHandle *handle,
+ struct connectdata *conn)
+{
+ handle->easy_conn = conn;
+}
+
+static bool isHandleAtHead(struct SessionHandle *handle,
+ struct curl_llist *pipeline)
+{
+ struct curl_llist_element *curr = pipeline->head;
+ if(curr)
+ return (curr->ptr == handle) ? TRUE : FALSE;
+
+ return FALSE;
+}
+
+/*
+ * multi_freetimeout()
+ *
+ * Callback used by the llist system when a single timeout list entry is
+ * destroyed.
+ */
+static void multi_freetimeout(void *user, void *entryptr)
+{
+ (void)user;
+
+ /* the entry was plain malloc()'ed */
+ free(entryptr);
+}
+
+/*
+ * multi_addtimeout()
+ *
+ * Add a timestamp to the list of timeouts. Keep the list sorted so that head
+ * of list is always the timeout nearest in time.
+ *
+ */
+static CURLMcode
+multi_addtimeout(struct curl_llist *timeoutlist,
+ struct timeval *stamp)
+{
+ struct curl_llist_element *e;
+ struct timeval *timedup;
+ struct curl_llist_element *prev = NULL;
+
+ timedup = malloc(sizeof(*timedup));
+ if(!timedup)
+ return CURLM_OUT_OF_MEMORY;
+
+ /* copy the timestamp */
+ memcpy(timedup, stamp, sizeof(*timedup));
+
+ if(Curl_llist_count(timeoutlist)) {
+ /* find the correct spot in the list */
+ for(e = timeoutlist->head; e; e = e->next) {
+ struct timeval *checktime = e->ptr;
+ long diff = curlx_tvdiff(*checktime, *timedup);
+ if(diff > 0)
+ break;
+ prev = e;
+ }
+
+ }
+ /* else
+ this is the first timeout on the list */
+
+ if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
+ free(timedup);
+ return CURLM_OUT_OF_MEMORY;
+ }
+
+ return CURLM_OK;
+}
+
+/*
+ * Curl_expire()
+ *
+ * given a number of milliseconds from now to use to set the 'act before
+ * this'-time for the transfer, to be extracted by curl_multi_timeout()
+ *
+ * Note that the timeout will be added to a queue of timeouts if it defines a
+ * moment in time that is later than the current head of queue.
+ *
+ * Pass zero to clear all timeout values for this handle.
+*/
+void Curl_expire(struct SessionHandle *data, long milli)
+{
+ struct Curl_multi *multi = data->multi;
+ struct timeval *nowp = &data->state.expiretime;
+ int rc;
+
+ /* this is only interesting while there is still an associated multi struct
+ remaining! */
+ if(!multi)
+ return;
+
+ if(!milli) {
+ /* No timeout, clear the time data. */
+ if(nowp->tv_sec || nowp->tv_usec) {
+ /* Since this is an cleared time, we must remove the previous entry from
+ the splay tree */
+ struct curl_llist *list = data->state.timeoutlist;
+
+ rc = Curl_splayremovebyaddr(multi->timetree,
+ &data->state.timenode,
+ &multi->timetree);
+ if(rc)
+ infof(data, "Internal error clearing splay node = %d\n", rc);
+
+ /* flush the timeout list too */
+ while(list->size > 0)
+ Curl_llist_remove(list, list->tail, NULL);
+
+#ifdef DEBUGBUILD
+ infof(data, "Expire cleared\n");
+#endif
+ nowp->tv_sec = 0;
+ nowp->tv_usec = 0;
+ }
+ }
+ else {
+ struct timeval set;
+
+ set = Curl_tvnow();
+ set.tv_sec += milli/1000;
+ set.tv_usec += (milli%1000)*1000;
+
+ if(set.tv_usec >= 1000000) {
+ set.tv_sec++;
+ set.tv_usec -= 1000000;
+ }
+
+ if(nowp->tv_sec || nowp->tv_usec) {
+ /* This means that the struct is added as a node in the splay tree.
+ Compare if the new time is earlier, and only remove-old/add-new if it
+ is. */
+ long diff = curlx_tvdiff(set, *nowp);
+ if(diff > 0) {
+ /* the new expire time was later so just add it to the queue
+ and get out */
+ multi_addtimeout(data->state.timeoutlist, &set);
+ return;
+ }
+
+ /* the new time is newer than the presently set one, so add the current
+ to the queue and update the head */
+ multi_addtimeout(data->state.timeoutlist, nowp);
+
+ /* Since this is an updated time, we must remove the previous entry from
+ the splay tree first and then re-add the new value */
+ rc = Curl_splayremovebyaddr(multi->timetree,
+ &data->state.timenode,
+ &multi->timetree);
+ if(rc)
+ infof(data, "Internal error removing splay node = %d\n", rc);
+ }
+
+ *nowp = set;
+ data->state.timenode.payload = data;
+ multi->timetree = Curl_splayinsert(*nowp,
+ multi->timetree,
+ &data->state.timenode);
+ }
+#if 0
+ Curl_splayprint(multi->timetree, 0, TRUE);
+#endif
+}
+
+/*
+ * Curl_expire_latest()
+ *
+ * This is like Curl_expire() but will only add a timeout node to the list of
+ * timers if there is no timeout that will expire before the given time.
+ *
+ * Use this function if the code logic risks calling this function many times
+ * or if there's no particular conditional wait in the code for this specific
+ * time-out period to expire.
+ *
+ */
+void Curl_expire_latest(struct SessionHandle *data, long milli)
+{
+ struct timeval *exp = &data->state.expiretime;
+
+ struct timeval set;
+
+ set = Curl_tvnow();
+ set.tv_sec += milli/1000;
+ set.tv_usec += (milli%1000)*1000;
+
+ if(set.tv_usec >= 1000000) {
+ set.tv_sec++;
+ set.tv_usec -= 1000000;
+ }
+
+ if(exp->tv_sec || exp->tv_usec) {
+ /* This means that the struct is added as a node in the splay tree.
+ Compare if the new time is earlier, and only remove-old/add-new if it
+ is. */
+ long diff = curlx_tvdiff(set, *exp);
+ if(diff > 0)
+ /* the new expire time was later than the top time, so just skip this */
+ return;
+ }
+
+ /* Just add the timeout like normal */
+ Curl_expire(data, milli);
+}
+
+CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t s, void *hashp)
+{
+ struct Curl_sh_entry *there = NULL;
+ struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
+
+ if(s != CURL_SOCKET_BAD)
+ there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t));
+
+ if(!there)
+ return CURLM_BAD_SOCKET;
+
+ there->socketp = hashp;
+
+ return CURLM_OK;
+}
+
+size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
+{
+ return multi ? multi->max_host_connections : 0;
+}
+
+size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
+{
+ return multi ? multi->max_total_connections : 0;
+}
+
+size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
+{
+ return multi ? multi->max_pipeline_length : 0;
+}
+
+curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
+{
+ return multi ? multi->content_length_penalty_size : 0;
+}
+
+curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
+{
+ return multi ? multi->chunk_length_penalty_size : 0;
+}
+
+struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
+{
+ return multi->pipelining_site_bl;
+}
+
+struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
+{
+ return multi->pipelining_server_bl;
+}
+
+void Curl_multi_process_pending_handles(struct Curl_multi *multi)
+{
+ struct curl_llist_element *e = multi->pending->head;
+
+ while(e) {
+ struct SessionHandle *data = e->ptr;
+ struct curl_llist_element *next = e->next;
+
+ if(data->mstate == CURLM_STATE_CONNECT_PEND) {
+ multistate(data, CURLM_STATE_CONNECT);
+
+ /* Remove this node from the list */
+ Curl_llist_remove(multi->pending, e, NULL);
+
+ /* Make sure that the handle will be processed soonish. */
+ Curl_expire_latest(data, 1);
+ }
+
+ e = next; /* operate on next handle */
+ }
+}
+
+#ifdef DEBUGBUILD
+void Curl_multi_dump(const struct Curl_multi *multi_handle)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct SessionHandle *data;
+ int i;
+ fprintf(stderr, "* Multi status: %d handles, %d alive\n",
+ multi->num_easy, multi->num_alive);
+ for(data=multi->easyp; data; data = data->next) {
+ if(data->mstate < CURLM_STATE_COMPLETED) {
+ /* only display handles that are not completed */
+ fprintf(stderr, "handle %p, state %s, %d sockets\n",
+ (void *)data,
+ statename[data->mstate], data->numsocks);
+ for(i=0; i < data->numsocks; i++) {
+ curl_socket_t s = data->sockets[i];
+ struct Curl_sh_entry *entry =
+ Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
+
+ fprintf(stderr, "%d ", (int)s);
+ if(!entry) {
+ fprintf(stderr, "INTERNAL CONFUSION\n");
+ continue;
+ }
+ fprintf(stderr, "[%s %s] ",
+ entry->action&CURL_POLL_IN?"RECVING":"",
+ entry->action&CURL_POLL_OUT?"SENDING":"");
+ }
+ if(data->numsocks)
+ fprintf(stderr, "\n");
+ }
+ }
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/multihandle.h b/external/libcurl_android/jni/libcurl/lib/multihandle.h
new file mode 100755
index 00000000..1a4b1d96
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/multihandle.h
@@ -0,0 +1,142 @@
+#ifndef HEADER_CURL_MULTIHANDLE_H
+#define HEADER_CURL_MULTIHANDLE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct Curl_message {
+ /* the 'CURLMsg' is the part that is visible to the external user */
+ struct CURLMsg extmsg;
+};
+
+/* NOTE: if you add a state here, add the name to the statename[] array as
+ well!
+*/
+typedef enum {
+ CURLM_STATE_INIT, /* 0 - start in this state */
+ CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */
+ CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */
+ CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */
+ CURLM_STATE_WAITCONNECT, /* 4 - awaiting the connect to finalize */
+ CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */
+ CURLM_STATE_PROTOCONNECT, /* 6 - completing the protocol-specific connect
+ phase */
+ CURLM_STATE_WAITDO, /* 7 - wait for our turn to send the request */
+ CURLM_STATE_DO, /* 8 - start send off the request (part 1) */
+ CURLM_STATE_DOING, /* 9 - sending off the request (part 1) */
+ CURLM_STATE_DO_MORE, /* 10 - send off the request (part 2) */
+ CURLM_STATE_DO_DONE, /* 11 - done sending off request */
+ CURLM_STATE_WAITPERFORM, /* 12 - wait for our turn to read the response */
+ CURLM_STATE_PERFORM, /* 13 - transfer data */
+ CURLM_STATE_TOOFAST, /* 14 - wait because limit-rate exceeded */
+ CURLM_STATE_DONE, /* 15 - post data transfer operation */
+ CURLM_STATE_COMPLETED, /* 16 - operation complete */
+ CURLM_STATE_MSGSENT, /* 17 - the operation complete message is sent */
+ CURLM_STATE_LAST /* 18 - not a true state, never use this */
+} CURLMstate;
+
+/* we support N sockets per easy handle. Set the corresponding bit to what
+ action we should wait for */
+#define MAX_SOCKSPEREASYHANDLE 5
+#define GETSOCK_READABLE (0x00ff)
+#define GETSOCK_WRITABLE (0xff00)
+
+/* This is the struct known as CURLM on the outside */
+struct Curl_multi {
+ /* First a simple identifier to easier detect if a user mix up
+ this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
+ long type;
+
+ /* We have a doubly-linked circular list with easy handles */
+ struct SessionHandle *easyp;
+ struct SessionHandle *easylp; /* last node */
+
+ int num_easy; /* amount of entries in the linked list above. */
+ int num_alive; /* amount of easy handles that are added but have not yet
+ reached COMPLETE state */
+
+ struct curl_llist *msglist; /* a list of messages from completed transfers */
+
+ struct curl_llist *pending; /* SessionHandles that are in the
+ CURLM_STATE_CONNECT_PEND state */
+
+ /* callback function and user data pointer for the *socket() API */
+ curl_socket_callback socket_cb;
+ void *socket_userp;
+
+ /* Hostname cache */
+ struct curl_hash *hostcache;
+
+ /* timetree points to the splay-tree of time nodes to figure out expire
+ times of all currently set timers */
+ struct Curl_tree *timetree;
+
+ /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
+ the pluralis form, there can be more than one easy handle waiting on the
+ same actual socket) */
+ struct curl_hash *sockhash;
+
+ /* Whether pipelining is enabled for this multi handle */
+ bool pipelining_enabled;
+
+ /* Shared connection cache (bundles)*/
+ struct conncache *conn_cache;
+
+ /* This handle will be used for closing the cached connections in
+ curl_multi_cleanup() */
+ struct SessionHandle *closure_handle;
+
+ long maxconnects; /* if >0, a fixed limit of the maximum number of entries
+ we're allowed to grow the connection cache to */
+
+ long max_host_connections; /* if >0, a fixed limit of the maximum number
+ of connections per host */
+
+ long max_total_connections; /* if >0, a fixed limit of the maximum number
+ of connections in total */
+
+ long max_pipeline_length; /* if >0, maximum number of requests in a
+ pipeline */
+
+ long content_length_penalty_size; /* a connection with a
+ content-length bigger than
+ this is not considered
+ for pipelining */
+
+ long chunk_length_penalty_size; /* a connection with a chunk length
+ bigger than this is not
+ considered for pipelining */
+
+ struct curl_llist *pipelining_site_bl; /* List of sites that are blacklisted
+ from pipelining */
+
+ struct curl_llist *pipelining_server_bl; /* List of server types that are
+ blacklisted from pipelining */
+
+ /* timer callback and user data pointer for the *socket() API */
+ curl_multi_timer_callback timer_cb;
+ void *timer_userp;
+ struct timeval timer_lastcall; /* the fixed time for the timeout for the
+ previous callback */
+};
+
+#endif /* HEADER_CURL_MULTIHANDLE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/multiif.h b/external/libcurl_android/jni/libcurl/lib/multiif.h
new file mode 100755
index 00000000..c77b3ca3
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/multiif.h
@@ -0,0 +1,97 @@
+#ifndef HEADER_CURL_MULTIIF_H
+#define HEADER_CURL_MULTIIF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Prototypes for library-wide functions provided by multi.c
+ */
+void Curl_expire(struct SessionHandle *data, long milli);
+void Curl_expire_latest(struct SessionHandle *data, long milli);
+
+bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
+void Curl_multi_handlePipeBreak(struct SessionHandle *data);
+
+/* Internal version of curl_multi_init() accepts size parameters for the
+ socket and connection hashes */
+struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
+
+/* the write bits start at bit 16 for the *getsock() bitmap */
+#define GETSOCK_WRITEBITSTART 16
+
+#define GETSOCK_BLANK 0 /* no bits set */
+
+/* set the bit for the given sock number to make the bitmap for writable */
+#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x)))
+
+/* set the bit for the given sock number to make the bitmap for readable */
+#define GETSOCK_READSOCK(x) (1 << (x))
+
+#ifdef DEBUGBUILD
+ /*
+ * Curl_multi_dump is not a stable public function, this is only meant to
+ * allow easier tracking of the internal handle's state and what sockets
+ * they use. Only for research and development DEBUGBUILD enabled builds.
+ */
+void Curl_multi_dump(const struct Curl_multi *multi_handle);
+#endif
+
+/* Update the current connection of a One_Easy handle */
+void Curl_multi_set_easy_connection(struct SessionHandle *handle,
+ struct connectdata *conn);
+
+void Curl_multi_process_pending_handles(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
+size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_MAX_PIPELINE_LENGTH option */
+size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */
+curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE option */
+curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_PIPELINING_SITE_BL option */
+struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_PIPELINING_SERVER_BL option */
+struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi);
+
+/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
+size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
+
+/*
+ * Curl_multi_closed()
+ *
+ * Used by the connect code to tell the multi_socket code that one of the
+ * sockets we were using have just been closed. This function will then
+ * remove it from the sockethash for this handle to make the multi_socket API
+ * behave properly, especially for the case when libcurl will create another
+ * socket again and it gets the same file descriptor number.
+ */
+
+void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
+
+#endif /* HEADER_CURL_MULTIIF_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/netrc.c b/external/libcurl_android/jni/libcurl/lib/netrc.c
new file mode 100755
index 00000000..7435d94c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/netrc.c
@@ -0,0 +1,201 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#include <curl/curl.h>
+#include "netrc.h"
+
+#include "strequal.h"
+#include "strtok.h"
+#include "curl_memory.h"
+#include "rawstr.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Get user and password from .netrc when given a machine name */
+
+enum host_lookup_state {
+ NOTHING,
+ HOSTFOUND, /* the 'machine' keyword was found */
+ HOSTVALID /* this is "our" machine! */
+};
+
+/*
+ * @unittest: 1304
+ *
+ * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
+ * in.
+ */
+int Curl_parsenetrc(const char *host,
+ char **loginp,
+ char **passwordp,
+ char *netrcfile)
+{
+ FILE *file;
+ int retcode=1;
+ int specific_login = (*loginp && **loginp != 0);
+ bool netrc_alloc = FALSE;
+ enum host_lookup_state state=NOTHING;
+
+ char state_login=0; /* Found a login keyword */
+ char state_password=0; /* Found a password keyword */
+ int state_our_login=FALSE; /* With specific_login, found *our* login name */
+
+#define NETRC DOT_CHAR "netrc"
+
+ if(!netrcfile) {
+ bool home_alloc = FALSE;
+ char *home = curl_getenv("HOME"); /* portable environment reader */
+ if(home) {
+ home_alloc = TRUE;
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
+ }
+ else {
+ struct passwd pw, *pw_res;
+ char pwbuf[1024];
+ if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res)
+ && pw_res) {
+ home = strdup(pw.pw_dir);
+ if(!home)
+ return CURLE_OUT_OF_MEMORY;
+ home_alloc = TRUE;
+ }
+#elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
+ }
+ else {
+ struct passwd *pw;
+ pw= getpwuid(geteuid());
+ if(pw) {
+ home = pw->pw_dir;
+ }
+#endif
+ }
+
+ if(!home)
+ return retcode; /* no home directory found (or possibly out of memory) */
+
+ netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
+ if(home_alloc)
+ Curl_safefree(home);
+ if(!netrcfile) {
+ return -1;
+ }
+ netrc_alloc = TRUE;
+ }
+
+ file = fopen(netrcfile, "r");
+ if(netrc_alloc)
+ Curl_safefree(netrcfile);
+ if(file) {
+ char *tok;
+ char *tok_buf;
+ bool done=FALSE;
+ char netrcbuffer[256];
+ int netrcbuffsize = (int)sizeof(netrcbuffer);
+
+ while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
+ tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
+ while(!done && tok) {
+
+ if((*loginp && **loginp) && (*passwordp && **passwordp)) {
+ done=TRUE;
+ break;
+ }
+
+ switch(state) {
+ case NOTHING:
+ if(Curl_raw_equal("machine", tok)) {
+ /* the next tok is the machine name, this is in itself the
+ delimiter that starts the stuff entered for this machine,
+ after this we need to search for 'login' and
+ 'password'. */
+ state=HOSTFOUND;
+ }
+ break;
+ case HOSTFOUND:
+ if(Curl_raw_equal(host, tok)) {
+ /* and yes, this is our host! */
+ state=HOSTVALID;
+ retcode=0; /* we did find our host */
+ }
+ else
+ /* not our host */
+ state=NOTHING;
+ break;
+ case HOSTVALID:
+ /* we are now parsing sub-keywords concerning "our" host */
+ if(state_login) {
+ if(specific_login) {
+ state_our_login = Curl_raw_equal(*loginp, tok);
+ }
+ else {
+ free(*loginp);
+ *loginp = strdup(tok);
+ if(!*loginp) {
+ retcode = -1; /* allocation failed */
+ goto out;
+ }
+ }
+ state_login=0;
+ }
+ else if(state_password) {
+ if(state_our_login || !specific_login) {
+ free(*passwordp);
+ *passwordp = strdup(tok);
+ if(!*passwordp) {
+ retcode = -1; /* allocation failed */
+ goto out;
+ }
+ }
+ state_password=0;
+ }
+ else if(Curl_raw_equal("login", tok))
+ state_login=1;
+ else if(Curl_raw_equal("password", tok))
+ state_password=1;
+ else if(Curl_raw_equal("machine", tok)) {
+ /* ok, there's machine here go => */
+ state = HOSTFOUND;
+ state_our_login = FALSE;
+ }
+ break;
+ } /* switch (state) */
+
+ tok = strtok_r(NULL, " \t\n", &tok_buf);
+ } /* while(tok) */
+ } /* while fgets() */
+
+ out:
+ fclose(file);
+ }
+
+ return retcode;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/netrc.h b/external/libcurl_android/jni/libcurl/lib/netrc.h
new file mode 100755
index 00000000..a1456011
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/netrc.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_NETRC_H
+#define HEADER_CURL_NETRC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
+int Curl_parsenetrc(const char *host,
+ char **loginp,
+ char **passwordp,
+ char *filename);
+ /* Assume: (*passwordp)[0]=0, host[0] != 0.
+ * If (*loginp)[0] = 0, search for login and password within a machine
+ * section in the netrc.
+ * If (*loginp)[0] != 0, search for password within machine and login.
+ */
+
+#endif /* HEADER_CURL_NETRC_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/non-ascii.c b/external/libcurl_android/jni/libcurl/lib/non-ascii.c
new file mode 100755
index 00000000..91d6a54f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/non-ascii.c
@@ -0,0 +1,343 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef CURL_DOES_CONVERSIONS
+
+#include <curl/curl.h>
+
+#include "non-ascii.h"
+#include "formdata.h"
+#include "sendf.h"
+#include "urldata.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef HAVE_ICONV
+#include <iconv.h>
+/* set default codesets for iconv */
+#ifndef CURL_ICONV_CODESET_OF_NETWORK
+#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
+#endif
+#ifndef CURL_ICONV_CODESET_FOR_UTF8
+#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
+#endif
+#define ICONV_ERROR (size_t)-1
+#endif /* HAVE_ICONV */
+
+/*
+ * Curl_convert_clone() returns a malloced copy of the source string (if
+ * returning CURLE_OK), with the data converted to network format.
+ */
+CURLcode Curl_convert_clone(struct SessionHandle *data,
+ const char *indata,
+ size_t insize,
+ char **outbuf)
+{
+ char *convbuf;
+ CURLcode result;
+
+ convbuf = malloc(insize);
+ if(!convbuf)
+ return CURLE_OUT_OF_MEMORY;
+
+ memcpy(convbuf, indata, insize);
+ result = Curl_convert_to_network(data, convbuf, insize);
+ if(result) {
+ free(convbuf);
+ return result;
+ }
+
+ *outbuf = convbuf; /* return the converted buffer */
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_convert_to_network() is an internal function for performing ASCII
+ * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ */
+CURLcode Curl_convert_to_network(struct SessionHandle *data,
+ char *buffer, size_t length)
+{
+ CURLcode rc;
+
+ if(data->set.convtonetwork) {
+ /* use translation callback */
+ rc = data->set.convtonetwork(buffer, length);
+ if(rc != CURLE_OK) {
+ failf(data,
+ "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
+ (int)rc, curl_easy_strerror(rc));
+ }
+ return rc;
+ }
+ else {
+#ifdef HAVE_ICONV
+ /* do the translation ourselves */
+ char *input_ptr, *output_ptr;
+ size_t in_bytes, out_bytes, rc;
+ int error;
+
+ /* open an iconv conversion descriptor if necessary */
+ if(data->outbound_cd == (iconv_t)-1) {
+ data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
+ CURL_ICONV_CODESET_OF_HOST);
+ if(data->outbound_cd == (iconv_t)-1) {
+ error = ERRNO;
+ failf(data,
+ "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
+ CURL_ICONV_CODESET_OF_NETWORK,
+ CURL_ICONV_CODESET_OF_HOST,
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+ }
+ /* call iconv */
+ input_ptr = output_ptr = buffer;
+ in_bytes = out_bytes = length;
+ rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
+ &output_ptr, &out_bytes);
+ if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ error = ERRNO;
+ failf(data,
+ "The Curl_convert_to_network iconv call failed with errno %i: %s",
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+#else
+ failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
+ return CURLE_CONV_REQD;
+#endif /* HAVE_ICONV */
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_convert_from_network() is an internal function for performing ASCII
+ * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ */
+CURLcode Curl_convert_from_network(struct SessionHandle *data,
+ char *buffer, size_t length)
+{
+ CURLcode rc;
+
+ if(data->set.convfromnetwork) {
+ /* use translation callback */
+ rc = data->set.convfromnetwork(buffer, length);
+ if(rc != CURLE_OK) {
+ failf(data,
+ "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
+ (int)rc, curl_easy_strerror(rc));
+ }
+ return rc;
+ }
+ else {
+#ifdef HAVE_ICONV
+ /* do the translation ourselves */
+ char *input_ptr, *output_ptr;
+ size_t in_bytes, out_bytes, rc;
+ int error;
+
+ /* open an iconv conversion descriptor if necessary */
+ if(data->inbound_cd == (iconv_t)-1) {
+ data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_OF_NETWORK);
+ if(data->inbound_cd == (iconv_t)-1) {
+ error = ERRNO;
+ failf(data,
+ "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
+ CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_OF_NETWORK,
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+ }
+ /* call iconv */
+ input_ptr = output_ptr = buffer;
+ in_bytes = out_bytes = length;
+ rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
+ &output_ptr, &out_bytes);
+ if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ error = ERRNO;
+ failf(data,
+ "Curl_convert_from_network iconv call failed with errno %i: %s",
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+#else
+ failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
+ return CURLE_CONV_REQD;
+#endif /* HAVE_ICONV */
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_convert_from_utf8() is an internal function for performing UTF-8
+ * conversions on non-ASCII platforms.
+ */
+CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
+ char *buffer, size_t length)
+{
+ CURLcode rc;
+
+ if(data->set.convfromutf8) {
+ /* use translation callback */
+ rc = data->set.convfromutf8(buffer, length);
+ if(rc != CURLE_OK) {
+ failf(data,
+ "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
+ (int)rc, curl_easy_strerror(rc));
+ }
+ return rc;
+ }
+ else {
+#ifdef HAVE_ICONV
+ /* do the translation ourselves */
+ const char *input_ptr;
+ char *output_ptr;
+ size_t in_bytes, out_bytes, rc;
+ int error;
+
+ /* open an iconv conversion descriptor if necessary */
+ if(data->utf8_cd == (iconv_t)-1) {
+ data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_FOR_UTF8);
+ if(data->utf8_cd == (iconv_t)-1) {
+ error = ERRNO;
+ failf(data,
+ "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
+ CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_FOR_UTF8,
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+ }
+ /* call iconv */
+ input_ptr = output_ptr = buffer;
+ in_bytes = out_bytes = length;
+ rc = iconv(data->utf8_cd, &input_ptr, &in_bytes,
+ &output_ptr, &out_bytes);
+ if((rc == ICONV_ERROR) || (in_bytes != 0)) {
+ error = ERRNO;
+ failf(data,
+ "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
+ error, strerror(error));
+ return CURLE_CONV_FAILED;
+ }
+ if(output_ptr < input_ptr) {
+ /* null terminate the now shorter output string */
+ *output_ptr = 0x00;
+ }
+#else
+ failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
+ return CURLE_CONV_REQD;
+#endif /* HAVE_ICONV */
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Init conversion stuff for a SessionHandle
+ */
+void Curl_convert_init(struct SessionHandle *data)
+{
+#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
+ /* conversion descriptors for iconv calls */
+ data->outbound_cd = (iconv_t)-1;
+ data->inbound_cd = (iconv_t)-1;
+ data->utf8_cd = (iconv_t)-1;
+#else
+ (void)data;
+#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
+}
+
+/*
+ * Setup conversion stuff for a SessionHandle
+ */
+void Curl_convert_setup(struct SessionHandle *data)
+{
+ data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_OF_NETWORK);
+ data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
+ CURL_ICONV_CODESET_OF_HOST);
+ data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_FOR_UTF8);
+}
+
+/*
+ * Close conversion stuff for a SessionHandle
+ */
+
+void Curl_convert_close(struct SessionHandle *data)
+{
+#ifdef HAVE_ICONV
+ /* close iconv conversion descriptors */
+ if(data->inbound_cd != (iconv_t)-1) {
+ iconv_close(data->inbound_cd);
+ }
+ if(data->outbound_cd != (iconv_t)-1) {
+ iconv_close(data->outbound_cd);
+ }
+ if(data->utf8_cd != (iconv_t)-1) {
+ iconv_close(data->utf8_cd);
+ }
+#else
+ (void)data;
+#endif /* HAVE_ICONV */
+}
+
+/*
+ * Curl_convert_form() is used from http.c, this converts any form items that
+ need to be sent in the network encoding. Returns CURLE_OK on success.
+ */
+CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form)
+{
+ struct FormData *next;
+ CURLcode rc;
+
+ if(!form)
+ return CURLE_OK;
+
+ if(!data)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ do {
+ next=form->next; /* the following form line */
+ if(form->type == FORM_DATA) {
+ rc = Curl_convert_to_network(data, form->line, form->length);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(rc != CURLE_OK)
+ return rc;
+ }
+ } while((form = next) != NULL); /* continue */
+ return CURLE_OK;
+}
+
+#endif /* CURL_DOES_CONVERSIONS */
diff --git a/external/libcurl_android/jni/libcurl/lib/non-ascii.h b/external/libcurl_android/jni/libcurl/lib/non-ascii.h
new file mode 100755
index 00000000..8b4b7c22
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/non-ascii.h
@@ -0,0 +1,63 @@
+#ifndef HEADER_CURL_NON_ASCII_H
+#define HEADER_CURL_NON_ASCII_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef CURL_DOES_CONVERSIONS
+
+#include "urldata.h"
+
+/*
+ * Curl_convert_clone() returns a malloced copy of the source string (if
+ * returning CURLE_OK), with the data converted to network format.
+ *
+ * If no conversion was needed *outbuf may be NULL.
+ */
+CURLcode Curl_convert_clone(struct SessionHandle *data,
+ const char *indata,
+ size_t insize,
+ char **outbuf);
+
+void Curl_convert_init(struct SessionHandle *data);
+void Curl_convert_setup(struct SessionHandle *data);
+void Curl_convert_close(struct SessionHandle *data);
+
+CURLcode Curl_convert_to_network(struct SessionHandle *data,
+ char *buffer, size_t length);
+CURLcode Curl_convert_from_network(struct SessionHandle *data,
+ char *buffer, size_t length);
+CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
+ char *buffer, size_t length);
+CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form);
+#else
+#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK)
+#define Curl_convert_init(x) Curl_nop_stmt
+#define Curl_convert_setup(x) Curl_nop_stmt
+#define Curl_convert_close(x) Curl_nop_stmt
+#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK)
+#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK)
+#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK)
+#define Curl_convert_form(a,b) CURLE_OK
+#endif
+
+#endif /* HEADER_CURL_NON_ASCII_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/nonblock.c b/external/libcurl_android/jni/libcurl/lib/nonblock.c
new file mode 100755
index 00000000..1447c877
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/nonblock.c
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
+#include <sys/filio.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#include "nonblock.h"
+
+/*
+ * curlx_nonblock() set the given socket to either blocking or non-blocking
+ * mode based on the 'nonblock' boolean argument. This function is highly
+ * portable.
+ */
+int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
+ int nonblock /* TRUE or FALSE */)
+{
+#if defined(USE_BLOCKING_SOCKETS)
+
+ return 0; /* returns success */
+
+#elif defined(HAVE_FCNTL_O_NONBLOCK)
+
+ /* most recent unix versions */
+ int flags;
+ flags = sfcntl(sockfd, F_GETFL, 0);
+ if(nonblock)
+ return sfcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+ else
+ return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
+
+#elif defined(HAVE_IOCTL_FIONBIO)
+
+ /* older unix versions */
+ int flags = nonblock ? 1 : 0;
+ return ioctl(sockfd, FIONBIO, &flags);
+
+#elif defined(HAVE_IOCTLSOCKET_FIONBIO)
+
+ /* Windows */
+ unsigned long flags = nonblock ? 1UL : 0UL;
+ return ioctlsocket(sockfd, FIONBIO, &flags);
+
+#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
+
+ /* Amiga */
+ long flags = nonblock ? 1L : 0L;
+ return IoctlSocket(sockfd, FIONBIO, flags);
+
+#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)
+
+ /* BeOS */
+ long b = nonblock ? 1L : 0L;
+ return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
+
+#else
+# error "no non-blocking method was found/used/set"
+#endif
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/nonblock.h b/external/libcurl_android/jni/libcurl/lib/nonblock.h
new file mode 100755
index 00000000..b540ae46
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/nonblock.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_NONBLOCK_H
+#define HEADER_CURL_NONBLOCK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h> /* for curl_socket_t */
+
+int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
+ int nonblock /* TRUE or FALSE */);
+
+#endif /* HEADER_CURL_NONBLOCK_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/nwlib.c b/external/libcurl_android/jni/libcurl/lib/nwlib.c
new file mode 100755
index 00000000..252bf11e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/nwlib.c
@@ -0,0 +1,329 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef NETWARE /* Novell NetWare */
+
+#ifdef __NOVELL_LIBC__
+/* For native LibC-based NLM we need to register as a real lib. */
+#include <library.h>
+#include <netware.h>
+#include <screen.h>
+#include <nks/thread.h>
+#include <nks/synch.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef struct
+{
+ int _errno;
+ void *twentybytes;
+} libthreaddata_t;
+
+typedef struct
+{
+ int x;
+ int y;
+ int z;
+ void *tenbytes;
+ NXKey_t perthreadkey; /* if -1, no key obtained... */
+ NXMutex_t *lock;
+} libdata_t;
+
+int gLibId = -1;
+void *gLibHandle = (void *) NULL;
+rtag_t gAllocTag = (rtag_t) NULL;
+NXMutex_t *gLibLock = (NXMutex_t *) NULL;
+
+/* internal library function prototypes... */
+int DisposeLibraryData( void * );
+void DisposeThreadData( void * );
+int GetOrSetUpData( int id, libdata_t **data, libthreaddata_t **threaddata );
+
+
+int _NonAppStart( void *NLMHandle,
+ void *errorScreen,
+ const char *cmdLine,
+ const char *loadDirPath,
+ size_t uninitializedDataLength,
+ void *NLMFileHandle,
+ int (*readRoutineP)( int conn,
+ void *fileHandle, size_t offset,
+ size_t nbytes,
+ size_t *bytesRead,
+ void *buffer ),
+ size_t customDataOffset,
+ size_t customDataSize,
+ int messageCount,
+ const char **messages )
+{
+ NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
+
+#ifndef __GNUC__
+#pragma unused(cmdLine)
+#pragma unused(loadDirPath)
+#pragma unused(uninitializedDataLength)
+#pragma unused(NLMFileHandle)
+#pragma unused(readRoutineP)
+#pragma unused(customDataOffset)
+#pragma unused(customDataSize)
+#pragma unused(messageCount)
+#pragma unused(messages)
+#endif
+
+ /*
+ * Here we process our command line, post errors (to the error screen),
+ * perform initializations and anything else we need to do before being able
+ * to accept calls into us. If we succeed, we return non-zero and the NetWare
+ * Loader will leave us up, otherwise we fail to load and get dumped.
+ */
+ gAllocTag = AllocateResourceTag(NLMHandle,
+ "<library-name> memory allocations",
+ AllocSignature);
+
+ if(!gAllocTag) {
+ OutputToScreen(errorScreen, "Unable to allocate resource tag for "
+ "library memory allocations.\n");
+ return -1;
+ }
+
+ gLibId = register_library(DisposeLibraryData);
+
+ if(gLibId < -1) {
+ OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
+ return -1;
+ }
+
+ gLibHandle = NLMHandle;
+
+ gLibLock = NXMutexAlloc(0, 0, &liblock);
+
+ if(!gLibLock) {
+ OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Here we clean up any resources we allocated. Resource tags is a big part
+ * of what we created, but NetWare doesn't ask us to free those.
+ */
+void _NonAppStop( void )
+{
+ (void) unregister_library(gLibId);
+ NXMutexFree(gLibLock);
+}
+
+/*
+ * This function cannot be the first in the file for if the file is linked
+ * first, then the check-unload function's offset will be nlmname.nlm+0
+ * which is how to tell that there isn't one. When the check function is
+ * first in the linked objects, it is ambiguous. For this reason, we will
+ * put it inside this file after the stop function.
+ *
+ * Here we check to see if it's alright to ourselves to be unloaded. If not,
+ * we return a non-zero value. Right now, there isn't any reason not to allow
+ * it.
+ */
+int _NonAppCheckUnload( void )
+{
+ return 0;
+}
+
+int GetOrSetUpData(int id, libdata_t **appData,
+ libthreaddata_t **threadData )
+{
+ int err;
+ libdata_t *app_data;
+ libthreaddata_t *thread_data;
+ NXKey_t key;
+ NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0);
+
+ err = 0;
+ thread_data = (libthreaddata_t *) NULL;
+
+ /*
+ * Attempt to get our data for the application calling us. This is where we
+ * store whatever application-specific information we need to carry in
+ * support of calling applications.
+ */
+ app_data = (libdata_t *) get_app_data(id);
+
+ if(!app_data) {
+ /*
+ * This application hasn't called us before; set up application AND
+ * per-thread data. Of course, just in case a thread from this same
+ * application is calling us simultaneously, we better lock our application
+ * data-creation mutex. We also need to recheck for data after we acquire
+ * the lock because WE might be that other thread that was too late to
+ * create the data and the first thread in will have created it.
+ */
+ NXLock(gLibLock);
+
+ if(!(app_data = (libdata_t *) get_app_data(id))) {
+ app_data = malloc(sizeof(libdata_t));
+
+ if(app_data) {
+ memset(app_data, 0, sizeof(libdata_t));
+
+ app_data->tenbytes = malloc(10);
+ app_data->lock = NXMutexAlloc(0, 0, &liblock);
+
+ if(!app_data->tenbytes || !app_data->lock) {
+ if(app_data->lock)
+ NXMutexFree(app_data->lock);
+
+ free(app_data);
+ app_data = (libdata_t *) NULL;
+ err = ENOMEM;
+ }
+
+ if(app_data) {
+ /*
+ * Here we burn in the application data that we were trying to get
+ * by calling get_app_data(). Next time we call the first function,
+ * we'll get this data we're just now setting. We also go on here to
+ * establish the per-thread data for the calling thread, something
+ * we'll have to do on each application thread the first time
+ * it calls us.
+ */
+ err = set_app_data(gLibId, app_data);
+
+ if(err) {
+ free(app_data);
+ app_data = (libdata_t *) NULL;
+ err = ENOMEM;
+ }
+ else {
+ /* create key for thread-specific data... */
+ err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key);
+
+ if(err) /* (no more keys left?) */
+ key = -1;
+
+ app_data->perthreadkey = key;
+ }
+ }
+ }
+ }
+
+ NXUnlock(gLibLock);
+ }
+
+ if(app_data) {
+ key = app_data->perthreadkey;
+
+ if(key != -1 /* couldn't create a key? no thread data */
+ && !(err = NXKeyGetValue(key, (void **) &thread_data))
+ && !thread_data) {
+ /*
+ * Allocate the per-thread data for the calling thread. Regardless of
+ * whether there was already application data or not, this may be the
+ * first call by a new thread. The fact that we allocation 20 bytes on
+ * a pointer is not very important, this just helps to demonstrate that
+ * we can have arbitrarily complex per-thread data.
+ */
+ thread_data = malloc(sizeof(libthreaddata_t));
+
+ if(thread_data) {
+ thread_data->_errno = 0;
+ thread_data->twentybytes = malloc(20);
+
+ if(!thread_data->twentybytes) {
+ free(thread_data);
+ thread_data = (libthreaddata_t *) NULL;
+ err = ENOMEM;
+ }
+
+ if((err = NXKeySetValue(key, thread_data))) {
+ free(thread_data->twentybytes);
+ free(thread_data);
+ thread_data = (libthreaddata_t *) NULL;
+ }
+ }
+ }
+ }
+
+ if(appData)
+ *appData = app_data;
+
+ if(threadData)
+ *threadData = thread_data;
+
+ return err;
+}
+
+int DisposeLibraryData( void *data )
+{
+ if(data) {
+ void *tenbytes = ((libdata_t *) data)->tenbytes;
+
+ if(tenbytes)
+ free(tenbytes);
+
+ free(data);
+ }
+
+ return 0;
+}
+
+void DisposeThreadData( void *data )
+{
+ if(data) {
+ void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
+
+ if(twentybytes)
+ free(twentybytes);
+
+ free(data);
+ }
+}
+
+#else /* __NOVELL_LIBC__ */
+/* For native CLib-based NLM seems we can do a bit more simple. */
+#include <nwthread.h>
+
+int main ( void )
+{
+ /* initialize any globals here... */
+
+ /* do this if any global initializing was done
+ SynchronizeStart();
+ */
+ ExitThread (TSR_THREAD, 0);
+ return 0;
+}
+
+#endif /* __NOVELL_LIBC__ */
+
+#else /* NETWARE */
+
+#ifdef __POCC__
+# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */
+#endif
+
+#endif /* NETWARE */
diff --git a/external/libcurl_android/jni/libcurl/lib/nwos.c b/external/libcurl_android/jni/libcurl/lib/nwos.c
new file mode 100755
index 00000000..23ff2a71
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/nwos.c
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef NETWARE /* Novell NetWare */
+
+#ifdef __NOVELL_LIBC__
+/* For native LibC-based NLM we need to do nothing. */
+int netware_init ( void )
+{
+ return 0;
+}
+
+#else /* __NOVELL_LIBC__ */
+
+/* For native CLib-based NLM we need to initialize the LONG namespace. */
+#include <nwnspace.h>
+#include <nwthread.h>
+#include <nwadv.h>
+/* Make the CLIB Ctx stuff link */
+#include <netdb.h>
+NETDB_DEFINE_CONTEXT
+/* Make the CLIB Inet stuff link */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+NETINET_DEFINE_CONTEXT
+
+int netware_init ( void )
+{
+ int rc = 0;
+ unsigned int myHandle = GetNLMHandle();
+ /* import UnAugmentAsterisk dynamically for NW4.x compatibility */
+ void (*pUnAugmentAsterisk)(int) = (void(*)(int))
+ ImportSymbol(myHandle, "UnAugmentAsterisk");
+ /* import UseAccurateCaseForPaths dynamically for NW3.x compatibility */
+ void (*pUseAccurateCaseForPaths)(int) = (void(*)(int))
+ ImportSymbol(myHandle, "UseAccurateCaseForPaths");
+ if(pUnAugmentAsterisk)
+ pUnAugmentAsterisk(1);
+ if(pUseAccurateCaseForPaths)
+ pUseAccurateCaseForPaths(1);
+ UnimportSymbol(myHandle, "UnAugmentAsterisk");
+ UnimportSymbol(myHandle, "UseAccurateCaseForPaths");
+ /* set long name space */
+ if((SetCurrentNameSpace(4) == 255)) {
+ rc = 1;
+ }
+ if((SetTargetNameSpace(4) == 255)) {
+ rc = rc + 2;
+ }
+ return rc;
+}
+
+/* dummy function to satisfy newer prelude */
+int __init_environment ( void )
+{
+ return 0;
+}
+
+/* dummy function to satisfy newer prelude */
+int __deinit_environment ( void )
+{
+ return 0;
+}
+
+#endif /* __NOVELL_LIBC__ */
+
+#endif /* NETWARE */
diff --git a/external/libcurl_android/jni/libcurl/lib/objnames.inc b/external/libcurl_android/jni/libcurl/lib/objnames.inc
new file mode 100755
index 00000000..8778492b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/objnames.inc
@@ -0,0 +1,107 @@
+# ***************************************************************************
+# * _ _ ____ _
+# * Project ___| | | | _ \| |
+# * / __| | | | |_) | |
+# * | (__| |_| | _ <| |___
+# * \___|\___/|_| \_\_____|
+# *
+# * Copyright (C) 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+# *
+# * This software is licensed as described in the file COPYING, which
+# * you should have received as part of this distribution. The terms
+# * are also available at http://curl.haxx.se/docs/copyright.html.
+# *
+# * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# * copies of the Software, and permit persons to whom the Software is
+# * furnished to do so, under the terms of the COPYING file.
+# *
+# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# * KIND, either express or implied.
+# *
+# ***************************************************************************
+
+#
+# This file is sourced from curl/packages/OS400/initscript.sh and
+# other Bourne shell scripts. Keep it as portable as possible.
+#
+
+#
+# curl_10char_object_name
+#
+# This shell function accepts a single string argument with unspecified
+# length representing a (*.c) source file name and returns a string which
+# is a transformation of given argument.
+#
+# The intended purpose of this function is to transliterate a (*.c) source
+# file name that may be longer than 10 characters, or not, into a string
+# with at most 10 characters which may be used as an OS/400 object name.
+#
+# This function might not be universally usefull, nor we care about it.
+#
+# It is intended to be used with libcurl's (*.c) source file names, so
+# dependency on libcurl's source file naming scheme is acceptable and
+# good enough for its intended use. Specifically it makes use of the fact
+# that libcurl's (*.c) source file names which may be longer than 10 chars
+# are conformed with underscore '_' separated substrings, or separated by
+# other character which does not belong to the [0-9], [a-z] or [A-Z] sets.
+#
+# This allows repeatable and automatic short object name generation with
+# no need for a hardcoded mapping table.
+#
+# Transformation is done in the following way:
+#
+# 1) Leading directory components are removed.
+# 2) Leftmost dot character and any other char following it are removed.
+# 3) Lowercase characters are transliterated to uppercase.
+# 4) Characters not in [A-Z] or [0-9] are transliterated to underscore '_'.
+# 5) Every sequence of one or more underscores is replaced with a single one.
+# 6) Five leftmost substrings which end in an underscore character are
+# replaced by the first character of each substring, while retaining
+# the rest of the string.
+# 7) Finally the result is truncated to 10 characters.
+#
+# Resulting object name may be shorter than 10 characters.
+#
+# Test case 1221 does unit testng of this function and also verifies
+# that it is possible to generate distinct short object names for all
+# curl and libcurl *.c source file names.
+#
+
+curl_10char_object_name() {
+ echo "${1}" | \
+ sed -e 's:.*/::' \
+ -e 's:[.].*::' \
+ -e 'y:abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:' \
+ -e 's:[^ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_]:_:g' \
+ -e 's:__*:_:g' \
+ -e 's:\([^_]\)[^_]*_\(.*\):\1\2:' \
+ -e 's:\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3:' \
+ -e 's:\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4:' \
+ -e 's:\([^_]\)\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4\5:' \
+ -e 's:\([^_]\)\([^_]\)\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4\5\6:' \
+ -e 's:^\(..........\).*:\1:'
+}
+
+#
+# curl_8char_object_name
+#
+# Same as curl_10char_object_name() description and details above, except
+# that object name is limited to 8 charcters maximum.
+#
+
+curl_8char_object_name() {
+ echo "${1}" | \
+ sed -e 's:.*/::' \
+ -e 's:[.].*::' \
+ -e 'y:abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:' \
+ -e 's:[^ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_]:_:g' \
+ -e 's:__*:_:g' \
+ -e 's:\([^_]\)[^_]*_\(.*\):\1\2:' \
+ -e 's:\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3:' \
+ -e 's:\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4:' \
+ -e 's:\([^_]\)\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4\5:' \
+ -e 's:\([^_]\)\([^_]\)\([^_]\)\([^_]\)\([^_]\)[^_]*_\(.*\):\1\2\3\4\5\6:' \
+ -e 's:^\(........\).*:\1:'
+}
+
+# end of objectname.inc
diff --git a/external/libcurl_android/jni/libcurl/lib/openldap.c b/external/libcurl_android/jni/libcurl/lib/openldap.c
new file mode 100755
index 00000000..df8d9388
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/openldap.c
@@ -0,0 +1,640 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, 2013, Howard Chu, <hyc@openldap.org>
+ * Copyright (C) 2011 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)
+
+/*
+ * Notice that USE_OPENLDAP is only a source code selection switch. When
+ * libcurl is built with USE_OPENLDAP defined the libcurl source code that
+ * gets compiled is the code from openldap.c, otherwise the code that gets
+ * compiled is the code from ldap.c.
+ *
+ * When USE_OPENLDAP is defined a recent version of the OpenLDAP library
+ * might be required for compilation and runtime. In order to use ancient
+ * OpenLDAP library versions, USE_OPENLDAP shall not be defined.
+ */
+
+#include <ldap.h>
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "sendf.h"
+#include "vtls/vtls.h"
+#include "transfer.h"
+#include "curl_ldap.h"
+#include "curl_memory.h"
+#include "curl_base64.h"
+#include "connect.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "memdebug.h"
+
+#ifndef _LDAP_PVT_H
+extern int ldap_pvt_url_scheme2proto(const char *);
+extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
+ LDAP **ld);
+#endif
+
+static CURLcode ldap_setup(struct connectdata *conn);
+static CURLcode ldap_do(struct connectdata *conn, bool *done);
+static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
+static CURLcode ldap_connect(struct connectdata *conn, bool *done);
+static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
+static CURLcode ldap_disconnect(struct connectdata *conn, bool dead);
+
+static Curl_recv ldap_recv;
+
+/*
+ * LDAP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldap = {
+ "LDAP", /* scheme */
+ ldap_setup, /* setup_connection */
+ ldap_do, /* do_it */
+ ldap_done, /* done */
+ ZERO_NULL, /* do_more */
+ ldap_connect, /* connect_it */
+ ldap_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ldap_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_LDAP, /* defport */
+ CURLPROTO_LDAP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * LDAPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_ldaps = {
+ "LDAPS", /* scheme */
+ ldap_setup, /* setup_connection */
+ ldap_do, /* do_it */
+ ldap_done, /* done */
+ ZERO_NULL, /* do_more */
+ ldap_connect, /* connect_it */
+ ldap_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ldap_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_LDAPS, /* defport */
+ CURLPROTO_LDAP, /* protocol */
+ PROTOPT_SSL /* flags */
+};
+#endif
+
+static const char *url_errs[] = {
+ "success",
+ "out of memory",
+ "bad parameter",
+ "unrecognized scheme",
+ "unbalanced delimiter",
+ "bad URL",
+ "bad host or port",
+ "bad or missing attributes",
+ "bad or missing scope",
+ "bad or missing filter",
+ "bad or missing extensions"
+};
+
+typedef struct ldapconninfo {
+ LDAP *ld;
+ Curl_recv *recv; /* for stacking SSL handler */
+ Curl_send *send;
+ int proto;
+ int msgid;
+ bool ssldone;
+ bool sslinst;
+ bool didbind;
+} ldapconninfo;
+
+typedef struct ldapreqinfo {
+ int msgid;
+ int nument;
+} ldapreqinfo;
+
+static CURLcode ldap_setup(struct connectdata *conn)
+{
+ ldapconninfo *li;
+ LDAPURLDesc *lud;
+ struct SessionHandle *data=conn->data;
+ int rc, proto;
+ CURLcode status;
+
+ rc = ldap_url_parse(data->change.url, &lud);
+ if(rc != LDAP_URL_SUCCESS) {
+ const char *msg = "url parsing problem";
+ status = CURLE_URL_MALFORMAT;
+ if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
+ if(rc == LDAP_URL_ERR_MEM)
+ status = CURLE_OUT_OF_MEMORY;
+ msg = url_errs[rc];
+ }
+ failf(conn->data, "LDAP local: %s", msg);
+ return status;
+ }
+ proto = ldap_pvt_url_scheme2proto(lud->lud_scheme);
+ ldap_free_urldesc(lud);
+
+ li = calloc(1, sizeof(ldapconninfo));
+ if(!li)
+ return CURLE_OUT_OF_MEMORY;
+ li->proto = proto;
+ conn->proto.generic = li;
+ connkeep(conn, "OpenLDAP default");
+ /* TODO:
+ * - provide option to choose SASL Binds instead of Simple
+ */
+ return CURLE_OK;
+}
+
+#ifdef USE_SSL
+static Sockbuf_IO ldapsb_tls;
+#endif
+
+static CURLcode ldap_connect(struct connectdata *conn, bool *done)
+{
+ ldapconninfo *li = conn->proto.generic;
+ struct SessionHandle *data=conn->data;
+ int rc, proto = LDAP_VERSION3;
+ char hosturl[1024], *ptr;
+ (void)done;
+
+ strcpy(hosturl, "ldap");
+ ptr = hosturl+4;
+ if(conn->handler->flags & PROTOPT_SSL)
+ *ptr++ = 's';
+ snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
+ conn->host.name, conn->remote_port);
+
+ rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld);
+ if(rc) {
+ failf(data, "LDAP local: Cannot connect to %s, %s",
+ hosturl, ldap_err2string(rc));
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
+
+#ifdef USE_SSL
+ if(conn->handler->flags & PROTOPT_SSL) {
+ CURLcode res;
+ res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
+ if(res)
+ return res;
+ }
+#endif
+
+ return CURLE_OK;
+}
+
+static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
+{
+ ldapconninfo *li = conn->proto.generic;
+ struct SessionHandle *data=conn->data;
+ LDAPMessage *result = NULL;
+ struct timeval tv = {0,1}, *tvp;
+ int rc, err;
+ char *info = NULL;
+
+#ifdef USE_SSL
+ if(conn->handler->flags & PROTOPT_SSL) {
+ /* Is the SSL handshake complete yet? */
+ if(!li->ssldone) {
+ CURLcode res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ &li->ssldone);
+ if(res || !li->ssldone)
+ return res;
+ }
+ /* Have we installed the libcurl SSL handlers into the sockbuf yet? */
+ if(!li->sslinst) {
+ Sockbuf *sb;
+ ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
+ ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn);
+ li->sslinst = TRUE;
+ li->recv = conn->recv[FIRSTSOCKET];
+ li->send = conn->send[FIRSTSOCKET];
+ }
+ }
+#endif
+
+ tvp = &tv;
+
+retry:
+ if(!li->didbind) {
+ char *binddn;
+ struct berval passwd;
+
+ if(conn->bits.user_passwd) {
+ binddn = conn->user;
+ passwd.bv_val = conn->passwd;
+ passwd.bv_len = strlen(passwd.bv_val);
+ }
+ else {
+ binddn = NULL;
+ passwd.bv_val = NULL;
+ passwd.bv_len = 0;
+ }
+ rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
+ NULL, NULL, &li->msgid);
+ if(rc)
+ return CURLE_LDAP_CANNOT_BIND;
+ li->didbind = TRUE;
+ if(tvp)
+ return CURLE_OK;
+ }
+
+ rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &result);
+ if(rc < 0) {
+ failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc));
+ return CURLE_LDAP_CANNOT_BIND;
+ }
+ if(rc == 0) {
+ /* timed out */
+ return CURLE_OK;
+ }
+ rc = ldap_parse_result(li->ld, result, &err, NULL, &info, NULL, NULL, 1);
+ if(rc) {
+ failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc));
+ return CURLE_LDAP_CANNOT_BIND;
+ }
+ /* Try to fallback to LDAPv2? */
+ if(err == LDAP_PROTOCOL_ERROR) {
+ int proto;
+ ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
+ if(proto == LDAP_VERSION3) {
+ if(info) {
+ ldap_memfree(info);
+ info = NULL;
+ }
+ proto = LDAP_VERSION2;
+ ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
+ li->didbind = FALSE;
+ goto retry;
+ }
+ }
+
+ if(err) {
+ failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc),
+ info ? info : "");
+ if(info)
+ ldap_memfree(info);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ if(info)
+ ldap_memfree(info);
+ conn->recv[FIRSTSOCKET] = ldap_recv;
+ *done = TRUE;
+ return CURLE_OK;
+}
+
+static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ ldapconninfo *li = conn->proto.generic;
+ (void) dead_connection;
+
+ if(li) {
+ if(li->ld) {
+ ldap_unbind_ext(li->ld, NULL, NULL);
+ li->ld = NULL;
+ }
+ conn->proto.generic = NULL;
+ free(li);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ldap_do(struct connectdata *conn, bool *done)
+{
+ ldapconninfo *li = conn->proto.generic;
+ ldapreqinfo *lr;
+ CURLcode status = CURLE_OK;
+ int rc = 0;
+ LDAPURLDesc *ludp = NULL;
+ int msgid;
+ struct SessionHandle *data=conn->data;
+
+ connkeep(conn, "OpenLDAP do");
+
+ infof(data, "LDAP local: %s\n", data->change.url);
+
+ rc = ldap_url_parse(data->change.url, &ludp);
+ if(rc != LDAP_URL_SUCCESS) {
+ const char *msg = "url parsing problem";
+ status = CURLE_URL_MALFORMAT;
+ if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
+ if(rc == LDAP_URL_ERR_MEM)
+ status = CURLE_OUT_OF_MEMORY;
+ msg = url_errs[rc];
+ }
+ failf(conn->data, "LDAP local: %s", msg);
+ return status;
+ }
+
+ rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope,
+ ludp->lud_filter, ludp->lud_attrs, 0,
+ NULL, NULL, NULL, 0, &msgid);
+ ldap_free_urldesc(ludp);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
+ return CURLE_LDAP_SEARCH_FAILED;
+ }
+ lr = calloc(1,sizeof(ldapreqinfo));
+ if(!lr)
+ return CURLE_OUT_OF_MEMORY;
+ lr->msgid = msgid;
+ data->req.protop = lr;
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+ *done = TRUE;
+ return CURLE_OK;
+}
+
+static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
+ bool premature)
+{
+ ldapreqinfo *lr = conn->data->req.protop;
+ (void)res;
+ (void)premature;
+
+ if(lr) {
+ /* if there was a search in progress, abandon it */
+ if(lr->msgid) {
+ ldapconninfo *li = conn->proto.generic;
+ ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
+ lr->msgid = 0;
+ }
+ conn->data->req.protop = NULL;
+ free(lr);
+ }
+ return CURLE_OK;
+}
+
+static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
+ size_t len, CURLcode *err)
+{
+ ldapconninfo *li = conn->proto.generic;
+ struct SessionHandle *data=conn->data;
+ ldapreqinfo *lr = data->req.protop;
+ int rc, ret;
+ LDAPMessage *result = NULL;
+ LDAPMessage *ent;
+ BerElement *ber = NULL;
+ struct timeval tv = {0,1};
+ (void)len;
+ (void)buf;
+ (void)sockindex;
+
+ rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &result);
+ if(rc < 0) {
+ failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc));
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ *err = CURLE_AGAIN;
+ ret = -1;
+
+ /* timed out */
+ if(result == NULL)
+ return ret;
+
+ for(ent = ldap_first_message(li->ld, result); ent;
+ ent = ldap_next_message(li->ld, ent)) {
+ struct berval bv, *bvals, **bvp = &bvals;
+ int binary = 0, msgtype;
+
+ msgtype = ldap_msgtype(ent);
+ if(msgtype == LDAP_RES_SEARCH_RESULT) {
+ int code;
+ char *info = NULL;
+ rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0);
+ if(rc) {
+ failf(data, "LDAP local: search ldap_parse_result %s",
+ ldap_err2string(rc));
+ *err = CURLE_LDAP_SEARCH_FAILED;
+ }
+ else if(code && code != LDAP_SIZELIMIT_EXCEEDED) {
+ failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc),
+ info ? info : "");
+ *err = CURLE_LDAP_SEARCH_FAILED;
+ }
+ else {
+ /* successful */
+ if(code == LDAP_SIZELIMIT_EXCEEDED)
+ infof(data, "There are more than %d entries\n", lr->nument);
+ data->req.size = data->req.bytecount;
+ *err = CURLE_OK;
+ ret = 0;
+ }
+ lr->msgid = 0;
+ ldap_memfree(info);
+ break;
+ }
+ else if(msgtype != LDAP_RES_SEARCH_ENTRY)
+ continue;
+
+ lr->nument++;
+ rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
+ if(rc < 0) {
+ /* TODO: verify that this is really how this return code should be
+ handled */
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ data->req.bytecount += bv.bv_len + 5;
+
+ for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp);
+ rc == LDAP_SUCCESS;
+ rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) {
+ int i;
+
+ if(bv.bv_val == NULL) break;
+
+ if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
+ binary = 1;
+ else
+ binary = 0;
+
+ for(i=0; bvals[i].bv_val != NULL; i++) {
+ int binval = 0;
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
+ data->req.bytecount += bv.bv_len + 2;
+
+ if(!binary) {
+ /* check for leading or trailing whitespace */
+ if(ISSPACE(bvals[i].bv_val[0]) ||
+ ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
+ binval = 1;
+ else {
+ /* check for unprintable characters */
+ unsigned int j;
+ for(j=0; j<bvals[i].bv_len; j++)
+ if(!ISPRINT(bvals[i].bv_val[j])) {
+ binval = 1;
+ break;
+ }
+ }
+ }
+ if(binary || binval) {
+ char *val_b64 = NULL;
+ size_t val_b64_sz = 0;
+ /* Binary value, encode to base64. */
+ CURLcode error = Curl_base64_encode(data,
+ bvals[i].bv_val,
+ bvals[i].bv_len,
+ &val_b64,
+ &val_b64_sz);
+ if(error) {
+ ber_memfree(bvals);
+ ber_free(ber, 0);
+ ldap_msgfree(result);
+ *err = error;
+ return -1;
+ }
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
+ data->req.bytecount += 2;
+ if(val_b64_sz > 0) {
+ Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
+ free(val_b64);
+ data->req.bytecount += val_b64_sz;
+ }
+ }
+ else {
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
+ Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
+ bvals[i].bv_len);
+ data->req.bytecount += bvals[i].bv_len + 1;
+ }
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ data->req.bytecount++;
+ }
+ ber_memfree(bvals);
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ data->req.bytecount++;
+ }
+ Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ data->req.bytecount++;
+ ber_free(ber, 0);
+ }
+ ldap_msgfree(result);
+ return ret;
+}
+
+#ifdef USE_SSL
+static int
+ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg)
+{
+ sbiod->sbiod_pvt = arg;
+ return 0;
+}
+
+static int
+ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod)
+{
+ sbiod->sbiod_pvt = NULL;
+ return 0;
+}
+
+/* We don't need to do anything because libcurl does it already */
+static int
+ldapsb_tls_close(Sockbuf_IO_Desc *sbiod)
+{
+ (void)sbiod;
+ return 0;
+}
+
+static int
+ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
+{
+ (void)arg;
+ if(opt == LBER_SB_OPT_DATA_READY) {
+ struct connectdata *conn = sbiod->sbiod_pvt;
+ return Curl_ssl_data_pending(conn, FIRSTSOCKET);
+ }
+ return 0;
+}
+
+static ber_slen_t
+ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct connectdata *conn = sbiod->sbiod_pvt;
+ ldapconninfo *li = conn->proto.generic;
+ ber_slen_t ret;
+ CURLcode err = CURLE_RECV_ERROR;
+
+ ret = li->recv(conn, FIRSTSOCKET, buf, len, &err);
+ if(ret < 0 && err == CURLE_AGAIN) {
+ SET_SOCKERRNO(EWOULDBLOCK);
+ }
+ return ret;
+}
+
+static ber_slen_t
+ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
+{
+ struct connectdata *conn = sbiod->sbiod_pvt;
+ ldapconninfo *li = conn->proto.generic;
+ ber_slen_t ret;
+ CURLcode err = CURLE_SEND_ERROR;
+
+ ret = li->send(conn, FIRSTSOCKET, buf, len, &err);
+ if(ret < 0 && err == CURLE_AGAIN) {
+ SET_SOCKERRNO(EWOULDBLOCK);
+ }
+ return ret;
+}
+
+static Sockbuf_IO ldapsb_tls =
+{
+ ldapsb_tls_setup,
+ ldapsb_tls_remove,
+ ldapsb_tls_ctrl,
+ ldapsb_tls_read,
+ ldapsb_tls_write,
+ ldapsb_tls_close
+};
+#endif /* USE_SSL */
+
+#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */
diff --git a/external/libcurl_android/jni/libcurl/lib/parsedate.c b/external/libcurl_android/jni/libcurl/lib/parsedate.c
new file mode 100755
index 00000000..ecb8dfb4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/parsedate.c
@@ -0,0 +1,583 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ A brief summary of the date string formats this parser groks:
+
+ RFC 2616 3.3.1
+
+ Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+
+ we support dates without week day name:
+
+ 06 Nov 1994 08:49:37 GMT
+ 06-Nov-94 08:49:37 GMT
+ Nov 6 08:49:37 1994
+
+ without the time zone:
+
+ 06 Nov 1994 08:49:37
+ 06-Nov-94 08:49:37
+
+ weird order:
+
+ 1994 Nov 6 08:49:37 (GNU date fails)
+ GMT 08:49:37 06-Nov-94 Sunday
+ 94 6 Nov 08:49:37 (GNU date fails)
+
+ time left out:
+
+ 1994 Nov 6
+ 06-Nov-94
+ Sun Nov 6 94
+
+ unusual separators:
+
+ 1994.Nov.6
+ Sun/Nov/6/94/GMT
+
+ commonly used time zone names:
+
+ Sun, 06 Nov 1994 08:49:37 CET
+ 06 Nov 1994 08:49:37 EST
+
+ time zones specified using RFC822 style:
+
+ Sun, 12 Sep 2004 15:05:58 -0700
+ Sat, 11 Sep 2004 21:32:11 +0200
+
+ compact numerical date strings:
+
+ 20040912 15:05:58 -0700
+ 20040911 +0200
+
+*/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <curl/curl.h>
+#include "rawstr.h"
+#include "warnless.h"
+#include "parsedate.h"
+
+const char * const Curl_wkday[] =
+{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+static const char * const weekday[] =
+{ "Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday", "Saturday", "Sunday" };
+const char * const Curl_month[]=
+{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+struct tzinfo {
+ char name[5];
+ int offset; /* +/- in minutes */
+};
+
+/*
+ * parsedate()
+ *
+ * Returns:
+ *
+ * PARSEDATE_OK - a fine conversion
+ * PARSEDATE_FAIL - failed to convert
+ * PARSEDATE_LATER - time overflow at the far end of time_t
+ * PARSEDATE_SOONER - time underflow at the low end of time_t
+ */
+
+static int parsedate(const char *date, time_t *output);
+
+#define PARSEDATE_OK 0
+#define PARSEDATE_FAIL -1
+#define PARSEDATE_LATER 1
+#define PARSEDATE_SOONER 2
+
+/* Here's a bunch of frequently used time zone names. These were supported
+ by the old getdate parser. */
+#define tDAYZONE -60 /* offset for daylight savings time */
+static const struct tzinfo tz[]= {
+ {"GMT", 0}, /* Greenwich Mean */
+ {"UTC", 0}, /* Universal (Coordinated) */
+ {"WET", 0}, /* Western European */
+ {"BST", 0 tDAYZONE}, /* British Summer */
+ {"WAT", 60}, /* West Africa */
+ {"AST", 240}, /* Atlantic Standard */
+ {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */
+ {"EST", 300}, /* Eastern Standard */
+ {"EDT", 300 tDAYZONE}, /* Eastern Daylight */
+ {"CST", 360}, /* Central Standard */
+ {"CDT", 360 tDAYZONE}, /* Central Daylight */
+ {"MST", 420}, /* Mountain Standard */
+ {"MDT", 420 tDAYZONE}, /* Mountain Daylight */
+ {"PST", 480}, /* Pacific Standard */
+ {"PDT", 480 tDAYZONE}, /* Pacific Daylight */
+ {"YST", 540}, /* Yukon Standard */
+ {"YDT", 540 tDAYZONE}, /* Yukon Daylight */
+ {"HST", 600}, /* Hawaii Standard */
+ {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */
+ {"CAT", 600}, /* Central Alaska */
+ {"AHST", 600}, /* Alaska-Hawaii Standard */
+ {"NT", 660}, /* Nome */
+ {"IDLW", 720}, /* International Date Line West */
+ {"CET", -60}, /* Central European */
+ {"MET", -60}, /* Middle European */
+ {"MEWT", -60}, /* Middle European Winter */
+ {"MEST", -60 tDAYZONE}, /* Middle European Summer */
+ {"CEST", -60 tDAYZONE}, /* Central European Summer */
+ {"MESZ", -60 tDAYZONE}, /* Middle European Summer */
+ {"FWT", -60}, /* French Winter */
+ {"FST", -60 tDAYZONE}, /* French Summer */
+ {"EET", -120}, /* Eastern Europe, USSR Zone 1 */
+ {"WAST", -420}, /* West Australian Standard */
+ {"WADT", -420 tDAYZONE}, /* West Australian Daylight */
+ {"CCT", -480}, /* China Coast, USSR Zone 7 */
+ {"JST", -540}, /* Japan Standard, USSR Zone 8 */
+ {"EAST", -600}, /* Eastern Australian Standard */
+ {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */
+ {"GST", -600}, /* Guam Standard, USSR Zone 9 */
+ {"NZT", -720}, /* New Zealand */
+ {"NZST", -720}, /* New Zealand Standard */
+ {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */
+ {"IDLE", -720}, /* International Date Line East */
+ /* Next up: Military timezone names. RFC822 allowed these, but (as noted in
+ RFC 1123) had their signs wrong. Here we use the correct signs to match
+ actual military usage.
+ */
+ {"A", +1 * 60}, /* Alpha */
+ {"B", +2 * 60}, /* Bravo */
+ {"C", +3 * 60}, /* Charlie */
+ {"D", +4 * 60}, /* Delta */
+ {"E", +5 * 60}, /* Echo */
+ {"F", +6 * 60}, /* Foxtrot */
+ {"G", +7 * 60}, /* Golf */
+ {"H", +8 * 60}, /* Hotel */
+ {"I", +9 * 60}, /* India */
+ /* "J", Juliet is not used as a timezone, to indicate the observer's local
+ time */
+ {"K", +10 * 60}, /* Kilo */
+ {"L", +11 * 60}, /* Lima */
+ {"M", +12 * 60}, /* Mike */
+ {"N", -1 * 60}, /* November */
+ {"O", -2 * 60}, /* Oscar */
+ {"P", -3 * 60}, /* Papa */
+ {"Q", -4 * 60}, /* Quebec */
+ {"R", -5 * 60}, /* Romeo */
+ {"S", -6 * 60}, /* Sierra */
+ {"T", -7 * 60}, /* Tango */
+ {"U", -8 * 60}, /* Uniform */
+ {"V", -9 * 60}, /* Victor */
+ {"W", -10 * 60}, /* Whiskey */
+ {"X", -11 * 60}, /* X-ray */
+ {"Y", -12 * 60}, /* Yankee */
+ {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */
+};
+
+/* returns:
+ -1 no day
+ 0 monday - 6 sunday
+*/
+
+static int checkday(const char *check, size_t len)
+{
+ int i;
+ const char * const *what;
+ bool found= FALSE;
+ if(len > 3)
+ what = &weekday[0];
+ else
+ what = &Curl_wkday[0];
+ for(i=0; i<7; i++) {
+ if(Curl_raw_equal(check, what[0])) {
+ found=TRUE;
+ break;
+ }
+ what++;
+ }
+ return found?i:-1;
+}
+
+static int checkmonth(const char *check)
+{
+ int i;
+ const char * const *what;
+ bool found= FALSE;
+
+ what = &Curl_month[0];
+ for(i=0; i<12; i++) {
+ if(Curl_raw_equal(check, what[0])) {
+ found=TRUE;
+ break;
+ }
+ what++;
+ }
+ return found?i:-1; /* return the offset or -1, no real offset is -1 */
+}
+
+/* return the time zone offset between GMT and the input one, in number
+ of seconds or -1 if the timezone wasn't found/legal */
+
+static int checktz(const char *check)
+{
+ unsigned int i;
+ const struct tzinfo *what;
+ bool found= FALSE;
+
+ what = tz;
+ for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) {
+ if(Curl_raw_equal(check, what->name)) {
+ found=TRUE;
+ break;
+ }
+ what++;
+ }
+ return found?what->offset*60:-1;
+}
+
+static void skip(const char **date)
+{
+ /* skip everything that aren't letters or digits */
+ while(**date && !ISALNUM(**date))
+ (*date)++;
+}
+
+enum assume {
+ DATE_MDAY,
+ DATE_YEAR,
+ DATE_TIME
+};
+
+/* this is a clone of 'struct tm' but with all fields we don't need or use
+ cut out */
+struct my_tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+};
+
+/* struct tm to time since epoch in GMT time zone.
+ * This is similar to the standard mktime function but for GMT only, and
+ * doesn't suffer from the various bugs and portability problems that
+ * some systems' implementations have.
+ */
+static time_t my_timegm(struct my_tm *tm)
+{
+ static const int month_days_cumulative [12] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ int month, year, leap_days;
+
+ if(tm->tm_year < 70)
+ /* we don't support years before 1970 as they will cause this function
+ to return a negative value */
+ return -1;
+
+ year = tm->tm_year + 1900;
+ month = tm->tm_mon;
+ if(month < 0) {
+ year += (11 - month) / 12;
+ month = 11 - (11 - month) % 12;
+ }
+ else if(month >= 12) {
+ year -= month / 12;
+ month = month % 12;
+ }
+
+ leap_days = year - (tm->tm_mon <= 1);
+ leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400)
+ - (1969 / 4) + (1969 / 100) - (1969 / 400));
+
+ return ((((time_t) (year - 1970) * 365
+ + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24
+ + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
+}
+
+/*
+ * parsedate()
+ *
+ * Returns:
+ *
+ * PARSEDATE_OK - a fine conversion
+ * PARSEDATE_FAIL - failed to convert
+ * PARSEDATE_LATER - time overflow at the far end of time_t
+ * PARSEDATE_SOONER - time underflow at the low end of time_t
+ */
+
+static int parsedate(const char *date, time_t *output)
+{
+ time_t t = 0;
+ int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */
+ int monnum=-1; /* month of the year number, 0-11 */
+ int mdaynum=-1; /* day of month, 1 - 31 */
+ int hournum=-1;
+ int minnum=-1;
+ int secnum=-1;
+ int yearnum=-1;
+ int tzoff=-1;
+ struct my_tm tm;
+ enum assume dignext = DATE_MDAY;
+ const char *indate = date; /* save the original pointer */
+ int part = 0; /* max 6 parts */
+
+ while(*date && (part < 6)) {
+ bool found=FALSE;
+
+ skip(&date);
+
+ if(ISALPHA(*date)) {
+ /* a name coming up */
+ char buf[32]="";
+ size_t len;
+ if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz]", buf))
+ len = strlen(buf);
+ else
+ len = 0;
+
+ if(wdaynum == -1) {
+ wdaynum = checkday(buf, len);
+ if(wdaynum != -1)
+ found = TRUE;
+ }
+ if(!found && (monnum == -1)) {
+ monnum = checkmonth(buf);
+ if(monnum != -1)
+ found = TRUE;
+ }
+
+ if(!found && (tzoff == -1)) {
+ /* this just must be a time zone string */
+ tzoff = checktz(buf);
+ if(tzoff != -1)
+ found = TRUE;
+ }
+
+ if(!found)
+ return PARSEDATE_FAIL; /* bad string */
+
+ date += len;
+ }
+ else if(ISDIGIT(*date)) {
+ /* a digit */
+ int val;
+ char *end;
+ if((secnum == -1) &&
+ (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) {
+ /* time stamp! */
+ date += 8;
+ }
+ else if((secnum == -1) &&
+ (2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) {
+ /* time stamp without seconds */
+ date += 5;
+ secnum = 0;
+ }
+ else {
+ long lval;
+ int error;
+ int old_errno;
+
+ old_errno = ERRNO;
+ SET_ERRNO(0);
+ lval = strtol(date, &end, 10);
+ error = ERRNO;
+ if(error != old_errno)
+ SET_ERRNO(old_errno);
+
+ if(error)
+ return PARSEDATE_FAIL;
+
+#if LONG_MAX != INT_MAX
+ if((lval > (long)INT_MAX) || (lval < (long)INT_MIN))
+ return PARSEDATE_FAIL;
+#endif
+
+ val = curlx_sltosi(lval);
+
+ if((tzoff == -1) &&
+ ((end - date) == 4) &&
+ (val <= 1400) &&
+ (indate< date) &&
+ ((date[-1] == '+' || date[-1] == '-'))) {
+ /* four digits and a value less than or equal to 1400 (to take into
+ account all sorts of funny time zone diffs) and it is preceded
+ with a plus or minus. This is a time zone indication. 1400 is
+ picked since +1300 is frequently used and +1400 is mentioned as
+ an edge number in the document "ISO C 200X Proposal: Timezone
+ Functions" at http://david.tribble.com/text/c0xtimezone.html If
+ anyone has a more authoritative source for the exact maximum time
+ zone offsets, please speak up! */
+ found = TRUE;
+ tzoff = (val/100 * 60 + val%100)*60;
+
+ /* the + and - prefix indicates the local time compared to GMT,
+ this we need ther reversed math to get what we want */
+ tzoff = date[-1]=='+'?-tzoff:tzoff;
+ }
+
+ if(((end - date) == 8) &&
+ (yearnum == -1) &&
+ (monnum == -1) &&
+ (mdaynum == -1)) {
+ /* 8 digits, no year, month or day yet. This is YYYYMMDD */
+ found = TRUE;
+ yearnum = val/10000;
+ monnum = (val%10000)/100-1; /* month is 0 - 11 */
+ mdaynum = val%100;
+ }
+
+ if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) {
+ if((val > 0) && (val<32)) {
+ mdaynum = val;
+ found = TRUE;
+ }
+ dignext = DATE_YEAR;
+ }
+
+ if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) {
+ yearnum = val;
+ found = TRUE;
+ if(yearnum < 1900) {
+ if(yearnum > 70)
+ yearnum += 1900;
+ else
+ yearnum += 2000;
+ }
+ if(mdaynum == -1)
+ dignext = DATE_MDAY;
+ }
+
+ if(!found)
+ return PARSEDATE_FAIL;
+
+ date = end;
+ }
+ }
+
+ part++;
+ }
+
+ if(-1 == secnum)
+ secnum = minnum = hournum = 0; /* no time, make it zero */
+
+ if((-1 == mdaynum) ||
+ (-1 == monnum) ||
+ (-1 == yearnum))
+ /* lacks vital info, fail */
+ return PARSEDATE_FAIL;
+
+#if SIZEOF_TIME_T < 5
+ /* 32 bit time_t can only hold dates to the beginning of 2038 */
+ if(yearnum > 2037) {
+ *output = 0x7fffffff;
+ return PARSEDATE_LATER;
+ }
+#endif
+
+ if(yearnum < 1970) {
+ *output = 0;
+ return PARSEDATE_SOONER;
+ }
+
+ if((mdaynum > 31) || (monnum > 11) ||
+ (hournum > 23) || (minnum > 59) || (secnum > 60))
+ return PARSEDATE_FAIL; /* clearly an illegal date */
+
+ tm.tm_sec = secnum;
+ tm.tm_min = minnum;
+ tm.tm_hour = hournum;
+ tm.tm_mday = mdaynum;
+ tm.tm_mon = monnum;
+ tm.tm_year = yearnum - 1900;
+
+ /* my_timegm() returns a time_t. time_t is often 32 bits, even on many
+ architectures that feature 64 bit 'long'.
+
+ Some systems have 64 bit time_t and deal with years beyond 2038. However,
+ even on some of the systems with 64 bit time_t mktime() returns -1 for
+ dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
+ */
+ t = my_timegm(&tm);
+
+ /* time zone adjust (cast t to int to compare to negative one) */
+ if(-1 != (int)t) {
+
+ /* Add the time zone diff between local time zone and GMT. */
+ long delta = (long)(tzoff!=-1?tzoff:0);
+
+ if((delta>0) && (t > LONG_MAX - delta)) {
+ *output = 0x7fffffff;
+ return PARSEDATE_LATER; /* time_t overflow */
+ }
+
+ t += delta;
+ }
+
+ *output = t;
+
+ return PARSEDATE_OK;
+}
+
+time_t curl_getdate(const char *p, const time_t *now)
+{
+ time_t parsed;
+ int rc = parsedate(p, &parsed);
+ (void)now; /* legacy argument from the past that we ignore */
+
+ switch(rc) {
+ case PARSEDATE_OK:
+ case PARSEDATE_LATER:
+ case PARSEDATE_SOONER:
+ return parsed;
+ }
+ /* everything else is fail */
+ return -1;
+}
+
+/*
+ * Curl_gmtime() is a gmtime() replacement for portability. Do not use the
+ * gmtime_r() or gmtime() functions anywhere else but here.
+ *
+ */
+
+CURLcode Curl_gmtime(time_t intime, struct tm *store)
+{
+ const struct tm *tm;
+#ifdef HAVE_GMTIME_R
+ /* thread-safe version */
+ tm = (struct tm *)gmtime_r(&intime, store);
+#else
+ tm = gmtime(&intime);
+ if(tm)
+ *store = *tm; /* copy the pointed struct to the local copy */
+#endif
+
+ if(!tm)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLE_OK;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/parsedate.h b/external/libcurl_android/jni/libcurl/lib/parsedate.h
new file mode 100755
index 00000000..ade0f4f6
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/parsedate.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_PARSEDATE_H
+#define HEADER_CURL_PARSEDATE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+extern const char * const Curl_wkday[7];
+extern const char * const Curl_month[12];
+
+CURLcode Curl_gmtime(time_t intime, struct tm *store);
+
+#endif /* HEADER_CURL_PARSEDATE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/pingpong.c b/external/libcurl_android/jni/libcurl/lib/pingpong.c
new file mode 100755
index 00000000..c7e89d0a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/pingpong.c
@@ -0,0 +1,517 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * 'pingpong' is for generic back-and-forth support functions used by FTP,
+ * IMAP, POP3, SMTP and whatever more that likes them.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "urldata.h"
+#include "sendf.h"
+#include "select.h"
+#include "progress.h"
+#include "speedcheck.h"
+#include "pingpong.h"
+#include "multiif.h"
+#include "non-ascii.h"
+#include "vtls/vtls.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef USE_PINGPONG
+
+/* Returns timeout in ms. 0 or negative number means the timeout has already
+ triggered */
+long Curl_pp_state_timeout(struct pingpong *pp)
+{
+ struct connectdata *conn = pp->conn;
+ struct SessionHandle *data=conn->data;
+ long timeout_ms; /* in milliseconds */
+ long timeout2_ms; /* in milliseconds */
+ long response_time= (data->set.server_response_timeout)?
+ data->set.server_response_timeout: pp->response_time;
+
+ /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine
+ remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is
+ supposed to govern the response for any given server response, not for
+ the time from connect to the given server response. */
+
+ /* Without a requested timeout, we only wait 'response_time' seconds for the
+ full response to arrive before we bail out */
+ timeout_ms = response_time -
+ Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */
+
+ if(data->set.timeout) {
+ /* if timeout is requested, find out how much remaining time we have */
+ timeout2_ms = data->set.timeout - /* timeout time */
+ Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
+
+ /* pick the lowest number */
+ timeout_ms = CURLMIN(timeout_ms, timeout2_ms);
+ }
+
+ return timeout_ms;
+}
+
+/*
+ * Curl_pp_statemach()
+ */
+CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
+{
+ struct connectdata *conn = pp->conn;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ int rc;
+ long interval_ms;
+ long timeout_ms = Curl_pp_state_timeout(pp);
+ struct SessionHandle *data=conn->data;
+ CURLcode result = CURLE_OK;
+
+ if(timeout_ms <=0 ) {
+ failf(data, "server response timeout");
+ return CURLE_OPERATION_TIMEDOUT; /* already too little time */
+ }
+
+ if(block) {
+ interval_ms = 1000; /* use 1 second timeout intervals */
+ if(timeout_ms < interval_ms)
+ interval_ms = timeout_ms;
+ }
+ else
+ interval_ms = 0; /* immediate */
+
+ if(Curl_pp_moredata(pp))
+ /* We are receiving and there is data in the cache so just read it */
+ rc = 1;
+ else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
+ /* We are receiving and there is data ready in the SSL library */
+ rc = 1;
+ else
+ rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
+ pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
+ interval_ms);
+
+ if(block) {
+ /* if we didn't wait, we don't have to spend time on this now */
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(data, Curl_tvnow());
+
+ if(result)
+ return result;
+ }
+
+ if(rc == -1) {
+ failf(data, "select/poll error");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else if(rc)
+ result = pp->statemach_act(conn);
+
+ return result;
+}
+
+/* initialize stuff to prepare for reading a fresh new response */
+void Curl_pp_init(struct pingpong *pp)
+{
+ struct connectdata *conn = pp->conn;
+ pp->nread_resp = 0;
+ pp->linestart_resp = conn->data->state.buffer;
+ pp->pending_resp = TRUE;
+ pp->response = Curl_tvnow(); /* start response time-out now! */
+}
+
+
+
+/***********************************************************************
+ *
+ * Curl_pp_vsendf()
+ *
+ * Send the formated string as a command to a pingpong server. Note that
+ * the string should not have any CRLF appended, as this function will
+ * append the necessary things itself.
+ *
+ * made to never block
+ */
+CURLcode Curl_pp_vsendf(struct pingpong *pp,
+ const char *fmt,
+ va_list args)
+{
+ ssize_t bytes_written;
+ size_t write_len;
+ char *fmt_crlf;
+ char *s;
+ CURLcode error;
+ struct connectdata *conn = pp->conn;
+ struct SessionHandle *data = conn->data;
+
+#ifdef HAVE_GSSAPI
+ enum protection_level data_sec = conn->data_prot;
+#endif
+
+ DEBUGASSERT(pp->sendleft == 0);
+ DEBUGASSERT(pp->sendsize == 0);
+ DEBUGASSERT(pp->sendthis == NULL);
+
+ fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */
+ if(!fmt_crlf)
+ return CURLE_OUT_OF_MEMORY;
+
+ s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */
+ free(fmt_crlf);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY;
+
+ bytes_written = 0;
+ write_len = strlen(s);
+
+ Curl_pp_init(pp);
+
+ error = Curl_convert_to_network(data, s, write_len);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(error) {
+ free(s);
+ return error;
+ }
+
+#ifdef HAVE_GSSAPI
+ conn->data_prot = PROT_CMD;
+#endif
+ error = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
+ &bytes_written);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
+ conn->data_prot = data_sec;
+#endif
+
+ if(error) {
+ free(s);
+ return error;
+ }
+
+ if(conn->data->set.verbose)
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT,
+ s, (size_t)bytes_written, conn);
+
+ if(bytes_written != (ssize_t)write_len) {
+ /* the whole chunk was not sent, keep it around and adjust sizes */
+ pp->sendthis = s;
+ pp->sendsize = write_len;
+ pp->sendleft = write_len - bytes_written;
+ }
+ else {
+ free(s);
+ pp->sendthis = NULL;
+ pp->sendleft = pp->sendsize = 0;
+ pp->response = Curl_tvnow();
+ }
+
+ return CURLE_OK;
+}
+
+
+/***********************************************************************
+ *
+ * Curl_pp_sendf()
+ *
+ * Send the formated string as a command to a pingpong server. Note that
+ * the string should not have any CRLF appended, as this function will
+ * append the necessary things itself.
+ *
+ * made to never block
+ */
+CURLcode Curl_pp_sendf(struct pingpong *pp,
+ const char *fmt, ...)
+{
+ CURLcode res;
+ va_list ap;
+ va_start(ap, fmt);
+
+ res = Curl_pp_vsendf(pp, fmt, ap);
+
+ va_end(ap);
+
+ return res;
+}
+
+/*
+ * Curl_pp_readresp()
+ *
+ * Reads a piece of a server response.
+ */
+CURLcode Curl_pp_readresp(curl_socket_t sockfd,
+ struct pingpong *pp,
+ int *code, /* return the server code if done */
+ size_t *size) /* size of the response */
+{
+ ssize_t perline; /* count bytes per line */
+ bool keepon=TRUE;
+ ssize_t gotbytes;
+ char *ptr;
+ struct connectdata *conn = pp->conn;
+ struct SessionHandle *data = conn->data;
+ char * const buf = data->state.buffer;
+ CURLcode result = CURLE_OK;
+
+ *code = 0; /* 0 for errors or not done */
+ *size = 0;
+
+ ptr=buf + pp->nread_resp;
+
+ /* number of bytes in the current line, so far */
+ perline = (ssize_t)(ptr-pp->linestart_resp);
+
+ keepon=TRUE;
+
+ while((pp->nread_resp<BUFSIZE) && (keepon && !result)) {
+
+ if(pp->cache) {
+ /* we had data in the "cache", copy that instead of doing an actual
+ * read
+ *
+ * pp->cache_size is cast to ssize_t here. This should be safe, because
+ * it would have been populated with something of size int to begin
+ * with, even though its datatype may be larger than an int.
+ */
+ DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1));
+ memcpy(ptr, pp->cache, pp->cache_size);
+ gotbytes = (ssize_t)pp->cache_size;
+ free(pp->cache); /* free the cache */
+ pp->cache = NULL; /* clear the pointer */
+ pp->cache_size = 0; /* zero the size just in case */
+ }
+ else {
+ int res;
+#ifdef HAVE_GSSAPI
+ enum protection_level prot = conn->data_prot;
+ conn->data_prot = PROT_CLEAR;
+#endif
+ DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
+ res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
+ &gotbytes);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
+ conn->data_prot = prot;
+#endif
+ if(res == CURLE_AGAIN)
+ return CURLE_OK; /* return */
+
+ if((res == CURLE_OK) && (gotbytes > 0))
+ /* convert from the network encoding */
+ res = Curl_convert_from_network(data, ptr, gotbytes);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+
+ if(CURLE_OK != res) {
+ result = (CURLcode)res; /* Set outer result variable to this error. */
+ keepon = FALSE;
+ }
+ }
+
+ if(!keepon)
+ ;
+ else if(gotbytes <= 0) {
+ keepon = FALSE;
+ result = CURLE_RECV_ERROR;
+ failf(data, "response reading failed");
+ }
+ else {
+ /* we got a whole chunk of data, which can be anything from one
+ * byte to a set of lines and possible just a piece of the last
+ * line */
+ ssize_t i;
+ ssize_t clipamount = 0;
+ bool restart = FALSE;
+
+ data->req.headerbytecount += (long)gotbytes;
+
+ pp->nread_resp += gotbytes;
+ for(i = 0; i < gotbytes; ptr++, i++) {
+ perline++;
+ if(*ptr=='\n') {
+ /* a newline is CRLF in pp-talk, so the CR is ignored as
+ the line isn't really terminated until the LF comes */
+
+ /* output debug output if that is requested */
+#ifdef HAVE_GSSAPI
+ if(!conn->sec_complete)
+#endif
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ pp->linestart_resp, (size_t)perline, conn);
+
+ /*
+ * We pass all response-lines to the callback function registered
+ * for "headers". The response lines can be seen as a kind of
+ * headers.
+ */
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ pp->linestart_resp, perline);
+ if(result)
+ return result;
+
+ if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
+ /* This is the end of the last line, copy the last line to the
+ start of the buffer and zero terminate, for old times sake */
+ size_t n = ptr - pp->linestart_resp;
+ memmove(buf, pp->linestart_resp, n);
+ buf[n]=0; /* zero terminate */
+ keepon=FALSE;
+ pp->linestart_resp = ptr+1; /* advance pointer */
+ i++; /* skip this before getting out */
+
+ *size = pp->nread_resp; /* size of the response */
+ pp->nread_resp = 0; /* restart */
+ break;
+ }
+ perline=0; /* line starts over here */
+ pp->linestart_resp = ptr+1;
+ }
+ }
+
+ if(!keepon && (i != gotbytes)) {
+ /* We found the end of the response lines, but we didn't parse the
+ full chunk of data we have read from the server. We therefore need
+ to store the rest of the data to be checked on the next invoke as
+ it may actually contain another end of response already! */
+ clipamount = gotbytes - i;
+ restart = TRUE;
+ DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
+ "server response left\n",
+ (int)clipamount));
+ }
+ else if(keepon) {
+
+ if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
+ /* We got an excessive line without newlines and we need to deal
+ with it. We keep the first bytes of the line then we throw
+ away the rest. */
+ infof(data, "Excessive server response line length received, "
+ "%zd bytes. Stripping\n", gotbytes);
+ restart = TRUE;
+
+ /* we keep 40 bytes since all our pingpong protocols are only
+ interested in the first piece */
+ clipamount = 40;
+ }
+ else if(pp->nread_resp > BUFSIZE/2) {
+ /* We got a large chunk of data and there's potentially still
+ trailing data to take care of, so we put any such part in the
+ "cache", clear the buffer to make space and restart. */
+ clipamount = perline;
+ restart = TRUE;
+ }
+ }
+ else if(i == gotbytes)
+ restart = TRUE;
+
+ if(clipamount) {
+ pp->cache_size = clipamount;
+ pp->cache = malloc(pp->cache_size);
+ if(pp->cache)
+ memcpy(pp->cache, pp->linestart_resp, pp->cache_size);
+ else
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(restart) {
+ /* now reset a few variables to start over nicely from the start of
+ the big buffer */
+ pp->nread_resp = 0; /* start over from scratch in the buffer */
+ ptr = pp->linestart_resp = buf;
+ perline = 0;
+ }
+
+ } /* there was data */
+
+ } /* while there's buffer left and loop is requested */
+
+ pp->pending_resp = FALSE;
+
+ return result;
+}
+
+int Curl_pp_getsock(struct pingpong *pp,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ struct connectdata *conn = pp->conn;
+
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ socks[0] = conn->sock[FIRSTSOCKET];
+
+ if(pp->sendleft) {
+ /* write mode */
+ return GETSOCK_WRITESOCK(0);
+ }
+
+ /* read mode */
+ return GETSOCK_READSOCK(0);
+}
+
+CURLcode Curl_pp_flushsend(struct pingpong *pp)
+{
+ /* we have a piece of a command still left to send */
+ struct connectdata *conn = pp->conn;
+ ssize_t written;
+ CURLcode result = CURLE_OK;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+
+ result = Curl_write(conn, sock, pp->sendthis + pp->sendsize -
+ pp->sendleft, pp->sendleft, &written);
+ if(result)
+ return result;
+
+ if(written != (ssize_t)pp->sendleft) {
+ /* only a fraction was sent */
+ pp->sendleft -= written;
+ }
+ else {
+ free(pp->sendthis);
+ pp->sendthis=NULL;
+ pp->sendleft = pp->sendsize = 0;
+ pp->response = Curl_tvnow();
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_pp_disconnect(struct pingpong *pp)
+{
+ if(pp->cache) {
+ free(pp->cache);
+ pp->cache = NULL;
+ }
+ return CURLE_OK;
+}
+
+bool Curl_pp_moredata(struct pingpong *pp)
+{
+ return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ?
+ TRUE : FALSE;
+}
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/pingpong.h b/external/libcurl_android/jni/libcurl/lib/pingpong.h
new file mode 100755
index 00000000..b925ab98
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/pingpong.h
@@ -0,0 +1,150 @@
+#ifndef HEADER_CURL_PINGPONG_H
+#define HEADER_CURL_PINGPONG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \
+ !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP)
+#define USE_PINGPONG
+#endif
+
+/* forward-declaration, this is defined in urldata.h */
+struct connectdata;
+
+typedef enum {
+ FTPTRANSFER_BODY, /* yes do transfer a body */
+ FTPTRANSFER_INFO, /* do still go through to get info/headers */
+ FTPTRANSFER_NONE, /* don't get anything and don't get info */
+ FTPTRANSFER_LAST /* end of list marker, never used */
+} curl_pp_transfer;
+
+/*
+ * 'pingpong' is the generic struct used for protocols doing server<->client
+ * conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc.
+ *
+ * It holds response cache and non-blocking sending data.
+ */
+struct pingpong {
+ char *cache; /* data cache between getresponse()-calls */
+ size_t cache_size; /* size of cache in bytes */
+ size_t nread_resp; /* number of bytes currently read of a server response */
+ char *linestart_resp; /* line start pointer for the server response
+ reader function */
+ bool pending_resp; /* set TRUE when a server response is pending or in
+ progress, and is cleared once the last response is
+ read */
+ char *sendthis; /* allocated pointer to a buffer that is to be sent to the
+ server */
+ size_t sendleft; /* number of bytes left to send from the sendthis buffer */
+ size_t sendsize; /* total size of the sendthis buffer */
+ struct timeval response; /* set to Curl_tvnow() when a command has been sent
+ off, used to time-out response reading */
+ long response_time; /* When no timeout is given, this is the amount of
+ milliseconds we await for a server response. */
+
+ struct connectdata *conn; /* points to the connectdata struct that this
+ belongs to */
+
+ /* Function pointers the protocols MUST implement and provide for the
+ pingpong layer to function */
+
+ CURLcode (*statemach_act)(struct connectdata *conn);
+
+ bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len,
+ int *code);
+};
+
+/*
+ * Curl_pp_statemach()
+ *
+ * called repeatedly until done. Set 'wait' to make it wait a while on the
+ * socket if there's no traffic.
+ */
+CURLcode Curl_pp_statemach(struct pingpong *pp, bool block);
+
+/* initialize stuff to prepare for reading a fresh new response */
+void Curl_pp_init(struct pingpong *pp);
+
+/* Returns timeout in ms. 0 or negative number means the timeout has already
+ triggered */
+long Curl_pp_state_timeout(struct pingpong *pp);
+
+
+/***********************************************************************
+ *
+ * Curl_pp_sendf()
+ *
+ * Send the formated string as a command to a pingpong server. Note that
+ * the string should not have any CRLF appended, as this function will
+ * append the necessary things itself.
+ *
+ * made to never block
+ */
+CURLcode Curl_pp_sendf(struct pingpong *pp,
+ const char *fmt, ...);
+
+/***********************************************************************
+ *
+ * Curl_pp_vsendf()
+ *
+ * Send the formated string as a command to a pingpong server. Note that
+ * the string should not have any CRLF appended, as this function will
+ * append the necessary things itself.
+ *
+ * made to never block
+ */
+CURLcode Curl_pp_vsendf(struct pingpong *pp,
+ const char *fmt,
+ va_list args);
+
+/*
+ * Curl_pp_readresp()
+ *
+ * Reads a piece of a server response.
+ */
+CURLcode Curl_pp_readresp(curl_socket_t sockfd,
+ struct pingpong *pp,
+ int *code, /* return the server code if done */
+ size_t *size); /* size of the response */
+
+
+CURLcode Curl_pp_flushsend(struct pingpong *pp);
+
+/* call this when a pingpong connection is disconnected */
+CURLcode Curl_pp_disconnect(struct pingpong *pp);
+
+int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks,
+ int numsocks);
+
+
+/***********************************************************************
+ *
+ * Curl_pp_moredata()
+ *
+ * Returns whether there are still more data in the cache and so a call
+ * to Curl_pp_readresp() will not block.
+ */
+bool Curl_pp_moredata(struct pingpong *pp);
+
+#endif /* HEADER_CURL_PINGPONG_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/pipeline.c b/external/libcurl_android/jni/libcurl/lib/pipeline.c
new file mode 100755
index 00000000..8d2544b8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/pipeline.c
@@ -0,0 +1,340 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2013-2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "url.h"
+#include "progress.h"
+#include "multiif.h"
+#include "pipeline.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "bundles.h"
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+struct site_blacklist_entry {
+ char *hostname;
+ unsigned short port;
+};
+
+static void site_blacklist_llist_dtor(void *user, void *element)
+{
+ struct site_blacklist_entry *entry = element;
+ (void)user;
+
+ Curl_safefree(entry->hostname);
+ Curl_safefree(entry);
+}
+
+static void server_blacklist_llist_dtor(void *user, void *element)
+{
+ char *server_name = element;
+ (void)user;
+
+ Curl_safefree(server_name);
+}
+
+bool Curl_pipeline_penalized(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ if(data) {
+ bool penalized = FALSE;
+ curl_off_t penalty_size =
+ Curl_multi_content_length_penalty_size(data->multi);
+ curl_off_t chunk_penalty_size =
+ Curl_multi_chunk_length_penalty_size(data->multi);
+ curl_off_t recv_size = -2; /* Make it easy to spot in the log */
+
+ /* Find the head of the recv pipe, if any */
+ if(conn->recv_pipe && conn->recv_pipe->head) {
+ struct SessionHandle *recv_handle = conn->recv_pipe->head->ptr;
+
+ recv_size = recv_handle->req.size;
+
+ if(penalty_size > 0 && recv_size > penalty_size)
+ penalized = TRUE;
+ }
+
+ if(chunk_penalty_size > 0 &&
+ (curl_off_t)conn->chunk.datasize > chunk_penalty_size)
+ penalized = TRUE;
+
+ infof(data, "Conn: %ld (%p) Receive pipe weight: (%"
+ CURL_FORMAT_CURL_OFF_T "/%zu), penalized: %s\n",
+ conn->connection_id, (void *)conn, recv_size,
+ conn->chunk.datasize, penalized?"TRUE":"FALSE");
+ return penalized;
+ }
+ return FALSE;
+}
+
+CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle,
+ struct connectdata *conn)
+{
+ struct curl_llist_element *sendhead = conn->send_pipe->head;
+ struct curl_llist *pipeline;
+ CURLcode rc;
+
+ pipeline = conn->send_pipe;
+
+ rc = Curl_addHandleToPipeline(handle, pipeline);
+
+ if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
+ /* this is a new one as head, expire it */
+ conn->writechannel_inuse = FALSE; /* not in use yet */
+ Curl_expire(conn->send_pipe->head->ptr, 1);
+ }
+
+#if 0 /* enable for pipeline debugging */
+ print_pipeline(conn);
+#endif
+
+ return rc;
+}
+
+/* Move this transfer from the sending list to the receiving list.
+
+ Pay special attention to the new sending list "leader" as it needs to get
+ checked to update what sockets it acts on.
+
+*/
+void Curl_move_handle_from_send_to_recv_pipe(struct SessionHandle *handle,
+ struct connectdata *conn)
+{
+ struct curl_llist_element *curr;
+
+ curr = conn->send_pipe->head;
+ while(curr) {
+ if(curr->ptr == handle) {
+ Curl_llist_move(conn->send_pipe, curr,
+ conn->recv_pipe, conn->recv_pipe->tail);
+
+ if(conn->send_pipe->head) {
+ /* Since there's a new easy handle at the start of the send pipeline,
+ set its timeout value to 1ms to make it trigger instantly */
+ conn->writechannel_inuse = FALSE; /* not used now */
+#ifdef DEBUGBUILD
+ infof(conn->data, "%p is at send pipe head B!\n",
+ (void *)conn->send_pipe->head->ptr);
+#endif
+ Curl_expire(conn->send_pipe->head->ptr, 1);
+ }
+
+ /* The receiver's list is not really interesting here since either this
+ handle is now first in the list and we'll deal with it soon, or
+ another handle is already first and thus is already taken care of */
+
+ break; /* we're done! */
+ }
+ curr = curr->next;
+ }
+}
+
+bool Curl_pipeline_site_blacklisted(struct SessionHandle *handle,
+ struct connectdata *conn)
+{
+ if(handle->multi) {
+ struct curl_llist *blacklist =
+ Curl_multi_pipelining_site_bl(handle->multi);
+
+ if(blacklist) {
+ struct curl_llist_element *curr;
+
+ curr = blacklist->head;
+ while(curr) {
+ struct site_blacklist_entry *site;
+
+ site = curr->ptr;
+ if(Curl_raw_equal(site->hostname, conn->host.name) &&
+ site->port == conn->remote_port) {
+ infof(handle, "Site %s:%d is pipeline blacklisted\n",
+ conn->host.name, conn->remote_port);
+ return TRUE;
+ }
+ curr = curr->next;
+ }
+ }
+ }
+ return FALSE;
+}
+
+CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
+ struct curl_llist **list_ptr)
+{
+ struct curl_llist *old_list = *list_ptr;
+ struct curl_llist *new_list = NULL;
+
+ if(sites) {
+ new_list = Curl_llist_alloc((curl_llist_dtor) site_blacklist_llist_dtor);
+ if(!new_list)
+ return CURLM_OUT_OF_MEMORY;
+
+ /* Parse the URLs and populate the list */
+ while(*sites) {
+ char *hostname;
+ char *port;
+ struct site_blacklist_entry *entry;
+
+ hostname = strdup(*sites);
+ if(!hostname) {
+ Curl_llist_destroy(new_list, NULL);
+ return CURLM_OUT_OF_MEMORY;
+ }
+
+ entry = malloc(sizeof(struct site_blacklist_entry));
+ if(!entry) {
+ free(hostname);
+ Curl_llist_destroy(new_list, NULL);
+ return CURLM_OUT_OF_MEMORY;
+ }
+
+ port = strchr(hostname, ':');
+ if(port) {
+ *port = '\0';
+ port++;
+ entry->port = (unsigned short)strtol(port, NULL, 10);
+ }
+ else {
+ /* Default port number for HTTP */
+ entry->port = 80;
+ }
+
+ entry->hostname = hostname;
+
+ if(!Curl_llist_insert_next(new_list, new_list->tail, entry)) {
+ site_blacklist_llist_dtor(NULL, entry);
+ Curl_llist_destroy(new_list, NULL);
+ return CURLM_OUT_OF_MEMORY;
+ }
+
+ sites++;
+ }
+ }
+
+ /* Free the old list */
+ if(old_list) {
+ Curl_llist_destroy(old_list, NULL);
+ }
+
+ /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
+ *list_ptr = new_list;
+
+ return CURLM_OK;
+}
+
+bool Curl_pipeline_server_blacklisted(struct SessionHandle *handle,
+ char *server_name)
+{
+ if(handle->multi) {
+ struct curl_llist *blacklist =
+ Curl_multi_pipelining_server_bl(handle->multi);
+
+ if(blacklist) {
+ struct curl_llist_element *curr;
+
+ curr = blacklist->head;
+ while(curr) {
+ char *bl_server_name;
+
+ bl_server_name = curr->ptr;
+ if(Curl_raw_nequal(bl_server_name, server_name,
+ strlen(bl_server_name))) {
+ infof(handle, "Server %s is blacklisted\n", server_name);
+ return TRUE;
+ }
+ curr = curr->next;
+ }
+ }
+
+ infof(handle, "Server %s is not blacklisted\n", server_name);
+ }
+ return FALSE;
+}
+
+CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
+ struct curl_llist **list_ptr)
+{
+ struct curl_llist *old_list = *list_ptr;
+ struct curl_llist *new_list = NULL;
+
+ if(servers) {
+ new_list = Curl_llist_alloc((curl_llist_dtor) server_blacklist_llist_dtor);
+ if(!new_list)
+ return CURLM_OUT_OF_MEMORY;
+
+ /* Parse the URLs and populate the list */
+ while(*servers) {
+ char *server_name;
+
+ server_name = strdup(*servers);
+ if(!server_name)
+ return CURLM_OUT_OF_MEMORY;
+
+ if(!Curl_llist_insert_next(new_list, new_list->tail, server_name))
+ return CURLM_OUT_OF_MEMORY;
+
+ servers++;
+ }
+ }
+
+ /* Free the old list */
+ if(old_list) {
+ Curl_llist_destroy(old_list, NULL);
+ }
+
+ /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
+ *list_ptr = new_list;
+
+ return CURLM_OK;
+}
+
+#if 0
+void print_pipeline(struct connectdata *conn)
+{
+ struct curl_llist_element *curr;
+ struct connectbundle *cb_ptr;
+ struct SessionHandle *data = conn->data;
+
+ cb_ptr = conn->bundle;
+
+ if(cb_ptr) {
+ curr = cb_ptr->conn_list->head;
+ while(curr) {
+ conn = curr->ptr;
+ infof(data, "- Conn %ld (%p) send_pipe: %zu, recv_pipe: %zu\n",
+ conn->connection_id,
+ (void *)conn,
+ conn->send_pipe->size,
+ conn->recv_pipe->size);
+ curr = curr->next;
+ }
+ }
+}
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/pipeline.h b/external/libcurl_android/jni/libcurl/lib/pipeline.h
new file mode 100755
index 00000000..96c4c33e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/pipeline.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_PIPELINE_H
+#define HEADER_CURL_PIPELINE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+CURLcode Curl_add_handle_to_pipeline(struct SessionHandle *handle,
+ struct connectdata *conn);
+void Curl_move_handle_from_send_to_recv_pipe(struct SessionHandle *handle,
+ struct connectdata *conn);
+bool Curl_pipeline_penalized(struct SessionHandle *data,
+ struct connectdata *conn);
+
+bool Curl_pipeline_site_blacklisted(struct SessionHandle *handle,
+ struct connectdata *conn);
+
+CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
+ struct curl_llist **list_ptr);
+
+bool Curl_pipeline_server_blacklisted(struct SessionHandle *handle,
+ char *server_name);
+
+CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
+ struct curl_llist **list_ptr);
+
+#endif /* HEADER_CURL_PIPELINE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/pop3.c b/external/libcurl_android/jni/libcurl/lib/pop3.c
new file mode 100755
index 00000000..dc64f810
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/pop3.c
@@ -0,0 +1,2339 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC1734 POP3 Authentication
+ * RFC1939 POP3 protocol
+ * RFC2195 CRAM-MD5 authentication
+ * RFC2384 POP URL Scheme
+ * RFC2449 POP3 Extension Mechanism
+ * RFC2595 Using TLS with IMAP, POP3 and ACAP
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4616 PLAIN authentication
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ * RFC5034 POP3 SASL Authentication Mechanism
+ * RFC6749 OAuth 2.0 Authorization Framework
+ * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_POP3
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "if2ip.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "socks.h"
+#include "pop3.h"
+
+#include "strtoofft.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "select.h"
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "curl_sasl.h"
+#include "curl_md5.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Local API functions */
+static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
+static CURLcode pop3_do(struct connectdata *conn, bool *done);
+static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
+ bool premature);
+static CURLcode pop3_connect(struct connectdata *conn, bool *done);
+static CURLcode pop3_disconnect(struct connectdata *conn, bool dead);
+static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done);
+static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
+static CURLcode pop3_setup_connection(struct connectdata *conn);
+static CURLcode pop3_parse_url_options(struct connectdata *conn);
+static CURLcode pop3_parse_url_path(struct connectdata *conn);
+static CURLcode pop3_parse_custom_request(struct connectdata *conn);
+static CURLcode pop3_calc_sasl_details(struct connectdata *conn,
+ const char **mech,
+ char **initresp, size_t *len,
+ pop3state *state1, pop3state *state2);
+
+/*
+ * POP3 protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_pop3 = {
+ "POP3", /* scheme */
+ pop3_setup_connection, /* setup_connection */
+ pop3_do, /* do_it */
+ pop3_done, /* done */
+ ZERO_NULL, /* do_more */
+ pop3_connect, /* connect_it */
+ pop3_multi_statemach, /* connecting */
+ pop3_doing, /* doing */
+ pop3_getsock, /* proto_getsock */
+ pop3_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ pop3_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_POP3, /* defport */
+ CURLPROTO_POP3, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * POP3S protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_pop3s = {
+ "POP3S", /* scheme */
+ pop3_setup_connection, /* setup_connection */
+ pop3_do, /* do_it */
+ pop3_done, /* done */
+ ZERO_NULL, /* do_more */
+ pop3_connect, /* connect_it */
+ pop3_multi_statemach, /* connecting */
+ pop3_doing, /* doing */
+ pop3_getsock, /* proto_getsock */
+ pop3_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ pop3_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_POP3S, /* defport */
+ CURLPROTO_POP3S, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_SSL
+ | PROTOPT_NOURLQUERY /* flags */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed POP3 protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_pop3_proxy = {
+ "POP3", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_POP3, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTP-proxyed POP3S protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_pop3s_proxy = {
+ "POP3S", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_POP3S, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+#endif
+#endif
+
+#ifdef USE_SSL
+static void pop3_to_pop3s(struct connectdata *conn)
+{
+ conn->handler = &Curl_handler_pop3s;
+}
+#else
+#define pop3_to_pop3s(x) Curl_nop_stmt
+#endif
+
+/***********************************************************************
+ *
+ * pop3_endofresp()
+ *
+ * Checks for an ending POP3 status code at the start of the given string, but
+ * also detects the APOP timestamp from the server greeting and various
+ * capabilities from the CAPA response including the supported authentication
+ * types and allowed SASL mechanisms.
+ */
+static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
+ int *resp)
+{
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ /* Do we have an error response? */
+ if(len >= 4 && !memcmp("-ERR", line, 4)) {
+ *resp = '-';
+
+ return TRUE;
+ }
+
+ /* Are we processing CAPA command responses? */
+ if(pop3c->state == POP3_CAPA) {
+ /* Do we have the terminating line? */
+ if(len >= 1 && !memcmp(line, ".", 1))
+ *resp = '+';
+ else
+ *resp = '*';
+
+ return TRUE;
+ }
+
+ /* Do we have a command or continuation response? */
+ if((len >= 3 && !memcmp("+OK", line, 3)) ||
+ (len >= 1 && !memcmp("+", line, 1))) {
+ *resp = '+';
+
+ return TRUE;
+ }
+
+ return FALSE; /* Nothing for us */
+}
+
+/***********************************************************************
+ *
+ * pop3_get_message()
+ *
+ * Gets the authentication message from the response buffer.
+ */
+static void pop3_get_message(char *buffer, char** outptr)
+{
+ size_t len = 0;
+ char* message = NULL;
+
+ /* Find the start of the message */
+ for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
+ ;
+
+ /* Find the end of the message */
+ for(len = strlen(message); len--;)
+ if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+ message[len] != '\t')
+ break;
+
+ /* Terminate the message */
+ if(++len) {
+ message[len] = '\0';
+ }
+
+ *outptr = message;
+}
+
+/***********************************************************************
+ *
+ * state()
+ *
+ * This is the ONLY way to change POP3 state!
+ */
+static void state(struct connectdata *conn, pop3state newstate)
+{
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[] = {
+ "STOP",
+ "SERVERGREET",
+ "CAPA",
+ "STARTTLS",
+ "UPGRADETLS",
+ "AUTH_PLAIN",
+ "AUTH_LOGIN",
+ "AUTH_LOGIN_PASSWD",
+ "AUTH_CRAMMD5",
+ "AUTH_DIGESTMD5",
+ "AUTH_DIGESTMD5_RESP",
+ "AUTH_NTLM",
+ "AUTH_NTLM_TYPE2MSG",
+ "AUTH_GSSAPI",
+ "AUTH_GSSAPI_TOKEN",
+ "AUTH_GSSAPI_NO_DATA",
+ "AUTH_XOAUTH2",
+ "AUTH_CANCEL",
+ "AUTH_FINAL",
+ "APOP",
+ "USER",
+ "PASS",
+ "COMMAND",
+ "QUIT",
+ /* LAST */
+ };
+
+ if(pop3c->state != newstate)
+ infof(conn->data, "POP3 %p state change from %s to %s\n",
+ (void *)pop3c, names[pop3c->state], names[newstate]);
+#endif
+
+ pop3c->state = newstate;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_capa()
+ *
+ * Sends the CAPA command in order to obtain a list of server side supported
+ * capabilities.
+ */
+static CURLcode pop3_perform_capa(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ pop3c->authmechs = 0; /* No known authentication mechanisms yet */
+ pop3c->authused = 0; /* Clear the authentication mechanism used */
+ pop3c->tls_supported = FALSE; /* Clear the TLS capability */
+
+ /* Send the CAPA command */
+ result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA");
+
+ if(!result)
+ state(conn, POP3_CAPA);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_starttls()
+ *
+ * Sends the STLS command to start the upgrade to TLS.
+ */
+static CURLcode pop3_perform_starttls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the STLS command */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS");
+
+ if(!result)
+ state(conn, POP3_STARTTLS);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_upgrade_tls()
+ *
+ * Performs the upgrade to TLS.
+ */
+static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ /* Start the SSL connection */
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
+
+ if(!result) {
+ if(pop3c->state != POP3_UPGRADETLS)
+ state(conn, POP3_UPGRADETLS);
+
+ if(pop3c->ssldone) {
+ pop3_to_pop3s(conn);
+ result = pop3_perform_capa(conn);
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_user()
+ *
+ * Sends a clear text USER command to authenticate with.
+ */
+static CURLcode pop3_perform_user(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't */
+ if(!conn->bits.user_passwd) {
+ state(conn, POP3_STOP);
+
+ return result;
+ }
+
+ /* Send the USER command */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s",
+ conn->user ? conn->user : "");
+ if(!result)
+ state(conn, POP3_USER);
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+/***********************************************************************
+ *
+ * pop3_perform_apop()
+ *
+ * Sends an APOP command to authenticate with.
+ */
+static CURLcode pop3_perform_apop(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ size_t i;
+ MD5_context *ctxt;
+ unsigned char digest[MD5_DIGEST_LEN];
+ char secret[2 * MD5_DIGEST_LEN + 1];
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't */
+ if(!conn->bits.user_passwd) {
+ state(conn, POP3_STOP);
+
+ return result;
+ }
+
+ /* Create the digest */
+ ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!ctxt)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp,
+ curlx_uztoui(strlen(pop3c->apoptimestamp)));
+
+ Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd,
+ curlx_uztoui(strlen(conn->passwd)));
+
+ /* Finalise the digest */
+ Curl_MD5_final(ctxt, digest);
+
+ /* Convert the calculated 16 octet digest into a 32 byte hex string */
+ for(i = 0; i < MD5_DIGEST_LEN; i++)
+ snprintf(&secret[2 * i], 3, "%02x", digest[i]);
+
+ result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret);
+
+ if(!result)
+ state(conn, POP3_APOP);
+
+ return result;
+}
+#endif
+
+/***********************************************************************
+ *
+ * pop3_perform_auth()
+ *
+ * Sends an AUTH command allowing the client to login with the given SASL
+ * authentication mechanism.
+ */
+static CURLcode pop3_perform_auth(struct connectdata *conn,
+ const char *mech,
+ const char *initresp, size_t len,
+ pop3state state1, pop3state state2)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ if(initresp && 8 + strlen(mech) + len <= 255) { /* AUTH <mech> ...<crlf> */
+ /* Send the AUTH command with the initial response */
+ result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp);
+
+ if(!result)
+ state(conn, state2);
+ }
+ else {
+ /* Send the AUTH command */
+ result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
+
+ if(!result)
+ state(conn, state1);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_authentication()
+ *
+ * Initiates the authentication sequence, with the appropriate SASL
+ * authentication mechanism, falling back to APOP and clear text should a
+ * common mechanism not be available between the client and server.
+ */
+static CURLcode pop3_perform_authentication(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ const char *mech = NULL;
+ char *initresp = NULL;
+ size_t len = 0;
+ pop3state state1 = POP3_STOP;
+ pop3state state2 = POP3_STOP;
+
+ /* Check we have a username and password to authenticate with and end the
+ connect phase if we don't */
+ if(!conn->bits.user_passwd) {
+ state(conn, POP3_STOP);
+
+ return result;
+ }
+
+ /* Calculate the SASL login details */
+ if(pop3c->authtypes & POP3_TYPE_SASL)
+ result = pop3_calc_sasl_details(conn, &mech, &initresp, &len, &state1,
+ &state2);
+
+ if(!result) {
+ if(mech && (pop3c->preftype & POP3_TYPE_SASL)) {
+ /* Perform SASL based authentication */
+ result = pop3_perform_auth(conn, mech, initresp, len, state1, state2);
+
+ Curl_safefree(initresp);
+ }
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ else if((pop3c->authtypes & POP3_TYPE_APOP) &&
+ (pop3c->preftype & POP3_TYPE_APOP))
+ /* Perform APOP authentication */
+ result = pop3_perform_apop(conn);
+#endif
+ else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) &&
+ (pop3c->preftype & POP3_TYPE_CLEARTEXT))
+ /* Perform clear text authentication */
+ result = pop3_perform_user(conn);
+ else {
+ /* Other mechanisms not supported */
+ infof(conn->data, "No known authentication mechanisms supported!\n");
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_command()
+ *
+ * Sends a POP3 based command.
+ */
+static CURLcode pop3_perform_command(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+ const char *command = NULL;
+
+ /* Calculate the default command */
+ if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) {
+ command = "LIST";
+
+ if(pop3->id[0] != '\0')
+ /* Message specific LIST so skip the BODY transfer */
+ pop3->transfer = FTPTRANSFER_INFO;
+ }
+ else
+ command = "RETR";
+
+ /* Send the command */
+ if(pop3->id[0] != '\0')
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s",
+ (pop3->custom && pop3->custom[0] != '\0' ?
+ pop3->custom : command), pop3->id);
+ else
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s",
+ (pop3->custom && pop3->custom[0] != '\0' ?
+ pop3->custom : command));
+
+ if(!result)
+ state(conn, POP3_COMMAND);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform_quit()
+ *
+ * Performs the quit action prior to sclose() be called.
+ */
+static CURLcode pop3_perform_quit(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the QUIT command */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT");
+
+ if(!result)
+ state(conn, POP3_QUIT);
+
+ return result;
+}
+
+/* For the initial server greeting */
+static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ const char *line = data->state.buffer;
+ size_t len = strlen(line);
+ size_t i;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Got unexpected pop3-server response");
+ result = CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+ else {
+ /* Does the server support APOP authentication? */
+ if(len >= 4 && line[len - 2] == '>') {
+ /* Look for the APOP timestamp */
+ for(i = 3; i < len - 2; ++i) {
+ if(line[i] == '<') {
+ /* Calculate the length of the timestamp */
+ size_t timestamplen = len - 1 - i;
+ if(!timestamplen)
+ break;
+
+ /* Allocate some memory for the timestamp */
+ pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1);
+
+ if(!pop3c->apoptimestamp)
+ break;
+
+ /* Copy the timestamp */
+ memcpy(pop3c->apoptimestamp, line + i, timestamplen);
+ pop3c->apoptimestamp[timestamplen] = '\0';
+
+ /* Store the APOP capability */
+ pop3c->authtypes |= POP3_TYPE_APOP;
+ break;
+ }
+ }
+ }
+
+ result = pop3_perform_capa(conn);
+ }
+
+ return result;
+}
+
+/* For CAPA responses */
+static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ const char *line = data->state.buffer;
+ size_t len = strlen(line);
+ size_t wordlen;
+
+ (void)instate; /* no use for this yet */
+
+ /* Do we have a untagged response? */
+ if(pop3code == '*') {
+ /* Does the server support the STLS capability? */
+ if(len >= 4 && !memcmp(line, "STLS", 4))
+ pop3c->tls_supported = TRUE;
+
+ /* Does the server support clear text authentication? */
+ else if(len >= 4 && !memcmp(line, "USER", 4))
+ pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+
+ /* Does the server support SASL based authentication? */
+ else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
+ pop3c->authtypes |= POP3_TYPE_SASL;
+
+ /* Advance past the SASL keyword */
+ line += 5;
+ len -= 5;
+
+ /* Loop through the data line */
+ for(;;) {
+ while(len &&
+ (*line == ' ' || *line == '\t' ||
+ *line == '\r' || *line == '\n')) {
+
+ line++;
+ len--;
+ }
+
+ if(!len)
+ break;
+
+ /* Extract the word */
+ for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
+ line[wordlen] != '\t' && line[wordlen] != '\r' &&
+ line[wordlen] != '\n';)
+ wordlen++;
+
+ /* Test the word for a matching authentication mechanism */
+ if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
+ pop3c->authmechs |= SASL_MECH_LOGIN;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
+ pop3c->authmechs |= SASL_MECH_PLAIN;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
+ pop3c->authmechs |= SASL_MECH_CRAM_MD5;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
+ pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
+ pop3c->authmechs |= SASL_MECH_GSSAPI;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
+ pop3c->authmechs |= SASL_MECH_EXTERNAL;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
+ pop3c->authmechs |= SASL_MECH_NTLM;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
+ pop3c->authmechs |= SASL_MECH_XOAUTH2;
+
+ line += wordlen;
+ len -= wordlen;
+ }
+ }
+ }
+ else if(pop3code == '+') {
+ if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* We don't have a SSL/TLS connection yet, but SSL is requested */
+ if(pop3c->tls_supported)
+ /* Switch to TLS connection now */
+ result = pop3_perform_starttls(conn);
+ else if(data->set.use_ssl == CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = pop3_perform_authentication(conn);
+ else {
+ failf(data, "STLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
+ }
+ else
+ result = pop3_perform_authentication(conn);
+ }
+ else {
+ /* Clear text is supported when CAPA isn't recognised */
+ pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+
+ result = pop3_perform_authentication(conn);
+ }
+
+ return result;
+}
+
+/* For STARTTLS responses */
+static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ if(data->set.use_ssl != CURLUSESSL_TRY) {
+ failf(data, "STARTTLS denied. %c", pop3code);
+ result = CURLE_USE_SSL_FAILED;
+ }
+ else
+ result = pop3_perform_authentication(conn);
+ }
+ else
+ result = pop3_perform_upgrade_tls(conn);
+
+ return result;
+}
+
+/* For AUTH PLAIN (without initial response) responses */
+static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *plainauth = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied. %c", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the authorisation message */
+ result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
+ &plainauth, &len);
+ if(!result && plainauth) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", plainauth);
+
+ if(!result)
+ state(conn, POP3_AUTH_FINAL);
+ }
+ }
+
+ Curl_safefree(plainauth);
+
+ return result;
+}
+
+/* For AUTH LOGIN (without initial response) responses */
+static CURLcode pop3_state_auth_login_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *authuser = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the user message */
+ result = Curl_sasl_create_login_message(data, conn->user,
+ &authuser, &len);
+ if(!result && authuser) {
+ /* Send the user */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authuser);
+
+ if(!result)
+ state(conn, POP3_AUTH_LOGIN_PASSWD);
+ }
+ }
+
+ Curl_safefree(authuser);
+
+ return result;
+}
+
+/* For AUTH LOGIN user entry responses */
+static CURLcode pop3_state_auth_login_password_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *authpasswd = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the password message */
+ result = Curl_sasl_create_login_message(data, conn->passwd,
+ &authpasswd, &len);
+ if(!result && authpasswd) {
+ /* Send the password */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authpasswd);
+
+ if(!result)
+ state(conn, POP3_AUTH_FINAL);
+ }
+ }
+
+ Curl_safefree(authpasswd);
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+/* For AUTH CRAM-MD5 responses */
+static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlg = NULL;
+ char *chlg64 = NULL;
+ char *rplyb64 = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Get the challenge message */
+ pop3_get_message(data->state.buffer, &chlg64);
+
+ /* Decode the challenge message */
+ result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
+ if(result) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
+
+ if(!result)
+ state(conn, POP3_AUTH_CANCEL);
+ }
+ else {
+ /* Create the response message */
+ result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user,
+ conn->passwd, &rplyb64, &len);
+ if(!result && rplyb64) {
+ /* Send the response */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
+
+ if(!result)
+ state(conn, POP3_AUTH_FINAL);
+ }
+ }
+
+ Curl_safefree(chlg);
+ Curl_safefree(rplyb64);
+
+ return result;
+}
+
+/* For AUTH DIGEST-MD5 challenge responses */
+static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlg64 = NULL;
+ char *rplyb64 = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Get the challenge message */
+ pop3_get_message(data->state.buffer, &chlg64);
+
+ /* Create the response message */
+ result = Curl_sasl_create_digest_md5_message(data, chlg64,
+ conn->user, conn->passwd,
+ "pop", &rplyb64, &len);
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
+
+ if(!result)
+ state(conn, POP3_AUTH_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
+
+ if(!result)
+ state(conn, POP3_AUTH_DIGESTMD5_RESP);
+ }
+
+ Curl_safefree(rplyb64);
+
+ return result;
+}
+
+/* For AUTH DIGEST-MD5 challenge-response responses */
+static CURLcode pop3_state_auth_digest_resp_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Authentication failed: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Send an empty response */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "");
+
+ if(!result)
+ state(conn, POP3_AUTH_FINAL);
+ }
+
+ return result;
+}
+#endif
+
+#ifdef USE_NTLM
+/* For AUTH NTLM (without initial response) responses */
+static CURLcode pop3_state_auth_ntlm_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *type1msg = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the type-1 message */
+ result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
+ &conn->ntlm,
+ &type1msg, &len);
+ if(!result && type1msg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type1msg);
+
+ if(!result)
+ state(conn, POP3_AUTH_NTLM_TYPE2MSG);
+ }
+ }
+
+ Curl_safefree(type1msg);
+
+ return result;
+}
+
+/* For NTLM type-2 responses (sent in reponse to our type-1 message) */
+static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *type2msg = NULL;
+ char *type3msg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the type-2 message */
+ pop3_get_message(data->state.buffer, &type2msg);
+
+ /* Decode the type-2 message */
+ result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
+ if(result) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
+
+ if(!result)
+ state(conn, POP3_AUTH_CANCEL);
+ }
+ else {
+ /* Create the type-3 message */
+ result = Curl_sasl_create_ntlm_type3_message(data, conn->user,
+ conn->passwd, &conn->ntlm,
+ &type3msg, &len);
+ if(!result && type3msg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type3msg);
+
+ if(!result)
+ state(conn, POP3_AUTH_FINAL);
+ }
+ }
+ }
+
+ Curl_safefree(type3msg);
+
+ return result;
+}
+#endif
+
+#if defined(USE_WINDOWS_SSPI)
+/* For AUTH GSSAPI (without initial response) responses */
+static CURLcode pop3_state_auth_gssapi_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ size_t len = 0;
+ char *respmsg = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the initial response message */
+ result = Curl_sasl_create_gssapi_user_message(data, conn->user,
+ conn->passwd, "pop",
+ pop3c->mutual_auth,
+ NULL, &conn->krb5,
+ &respmsg, &len);
+ if(!result && respmsg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&pop3c->pp, "%s", respmsg);
+
+ if(!result)
+ state(conn, POP3_AUTH_GSSAPI_TOKEN);
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+
+/* For AUTH GSSAPI user token responses */
+static CURLcode pop3_state_auth_gssapi_token_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ char *chlgmsg = NULL;
+ char *respmsg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the challenge message */
+ pop3_get_message(data->state.buffer, &chlgmsg);
+
+ if(pop3c->mutual_auth)
+ /* Decode the user token challenge and create the optional response
+ message */
+ result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL,
+ pop3c->mutual_auth,
+ chlgmsg, &conn->krb5,
+ &respmsg, &len);
+ else
+ /* Decode the security challenge and create the response message */
+ result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
+ &conn->krb5,
+ &respmsg, &len);
+
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&pop3c->pp, "%s", "*");
+
+ if(!result)
+ state(conn, POP3_AUTH_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ if(respmsg)
+ result = Curl_pp_sendf(&pop3c->pp, "%s", respmsg);
+ else
+ result = Curl_pp_sendf(&pop3c->pp, "%s", "");
+
+ if(!result)
+ state(conn, (pop3c->mutual_auth ? POP3_AUTH_GSSAPI_NO_DATA :
+ POP3_AUTH_FINAL));
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+
+/* For AUTH GSSAPI no data responses */
+static CURLcode pop3_state_auth_gssapi_no_data_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlgmsg = NULL;
+ char *respmsg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the challenge message */
+ pop3_get_message(data->state.buffer, &chlgmsg);
+
+ /* Decode the security challenge and create the security message */
+ result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
+ &conn->krb5,
+ &respmsg, &len);
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
+
+ if(!result)
+ state(conn, POP3_AUTH_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ if(respmsg) {
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", respmsg);
+
+ if(!result)
+ state(conn, POP3_AUTH_FINAL);
+ }
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+#endif
+
+/* For AUTH XOAUTH2 (without initial response) responses */
+static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
+ int pop3code, pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *xoauth = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the authorisation message */
+ result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
+ conn->xoauth2_bearer,
+ &xoauth, &len);
+ if(!result && xoauth) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth);
+
+ if(!result)
+ state(conn, POP3_AUTH_FINAL);
+ }
+ }
+
+ Curl_safefree(xoauth);
+
+ return result;
+}
+
+/* For AUTH cancellation responses */
+static CURLcode pop3_state_auth_cancel_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ const char *mech = NULL;
+ char *initresp = NULL;
+ size_t len = 0;
+ pop3state state1 = POP3_STOP;
+ pop3state state2 = POP3_STOP;
+
+ (void)pop3code;
+ (void)instate; /* no use for this yet */
+
+ /* Remove the offending mechanism from the supported list */
+ pop3c->authmechs ^= pop3c->authused;
+
+ /* Calculate alternative SASL login details */
+ result = pop3_calc_sasl_details(conn, &mech, &initresp, &len, &state1,
+ &state2);
+
+ if(!result) {
+ /* Do we have any mechanisms left or can we fallback to another
+ authentication type? */
+ if(mech) {
+ /* Retry SASL based authentication */
+ result = pop3_perform_auth(conn, mech, initresp, len, state1, state2);
+
+ Curl_safefree(initresp);
+ }
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ else if((pop3c->authtypes & POP3_TYPE_APOP) &&
+ (pop3c->preftype & POP3_TYPE_APOP))
+ /* Perform APOP authentication */
+ result = pop3_perform_apop(conn);
+#endif
+ else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) &&
+ (pop3c->preftype & POP3_TYPE_CLEARTEXT))
+ /* Perform clear text authentication */
+ result = pop3_perform_user(conn);
+ else {
+ failf(data, "Authentication cancelled");
+
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/* For final responses in the AUTH sequence */
+static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Authentication failed: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, POP3_STOP);
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+/* For APOP responses */
+static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Authentication failed: %d", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, POP3_STOP);
+
+ return result;
+}
+#endif
+
+/* For USER responses */
+static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied. %c", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* Send the PASS command */
+ result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s",
+ conn->passwd ? conn->passwd : "");
+ if(!result)
+ state(conn, POP3_PASS);
+
+ return result;
+}
+
+/* For PASS responses */
+static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ failf(data, "Access denied. %c", pop3code);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, POP3_STOP);
+
+ return result;
+}
+
+/* For command responses */
+static CURLcode pop3_state_command_resp(struct connectdata *conn,
+ int pop3code,
+ pop3state instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pingpong *pp = &pop3c->pp;
+
+ (void)instate; /* no use for this yet */
+
+ if(pop3code != '+') {
+ state(conn, POP3_STOP);
+ return CURLE_RECV_ERROR;
+ }
+
+ /* This 'OK' line ends with a CR LF pair which is the two first bytes of the
+ EOB string so count this is two matching bytes. This is necessary to make
+ the code detect the EOB if the only data than comes now is %2e CR LF like
+ when there is no body to return. */
+ pop3c->eob = 2;
+
+ /* But since this initial CR LF pair is not part of the actual body, we set
+ the strip counter here so that these bytes won't be delivered. */
+ pop3c->strip = 2;
+
+ if(pop3->transfer == FTPTRANSFER_BODY) {
+ /* POP3 download */
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+
+ if(pp->cache) {
+ /* The header "cache" contains a bunch of data that is actually body
+ content so send it as such. Note that there may even be additional
+ "headers" after the body */
+
+ if(!data->set.opt_no_body) {
+ result = Curl_pop3_write(conn, pp->cache, pp->cache_size);
+ if(result)
+ return result;
+ }
+
+ /* Free the cache */
+ Curl_safefree(pp->cache);
+
+ /* Reset the cache size */
+ pp->cache_size = 0;
+ }
+ }
+
+ /* End of DO phase */
+ state(conn, POP3_STOP);
+
+ return result;
+}
+
+static CURLcode pop3_statemach_act(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ int pop3code;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pingpong *pp = &pop3c->pp;
+ size_t nread = 0;
+
+ /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
+ if(pop3c->state == POP3_UPGRADETLS)
+ return pop3_perform_upgrade_tls(conn);
+
+ /* Flush any data that needs to be sent */
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
+
+ do {
+ /* Read the response from the server */
+ result = Curl_pp_readresp(sock, pp, &pop3code, &nread);
+ if(result)
+ return result;
+
+ if(!pop3code)
+ break;
+
+ /* We have now received a full POP3 server response */
+ switch(pop3c->state) {
+ case POP3_SERVERGREET:
+ result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_CAPA:
+ result = pop3_state_capa_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_STARTTLS:
+ result = pop3_state_starttls_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_PLAIN:
+ result = pop3_state_auth_plain_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_LOGIN:
+ result = pop3_state_auth_login_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_LOGIN_PASSWD:
+ result = pop3_state_auth_login_password_resp(conn, pop3code,
+ pop3c->state);
+ break;
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ case POP3_AUTH_CRAMMD5:
+ result = pop3_state_auth_cram_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_DIGESTMD5:
+ result = pop3_state_auth_digest_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_DIGESTMD5_RESP:
+ result = pop3_state_auth_digest_resp_resp(conn, pop3code, pop3c->state);
+ break;
+#endif
+
+#ifdef USE_NTLM
+ case POP3_AUTH_NTLM:
+ result = pop3_state_auth_ntlm_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_NTLM_TYPE2MSG:
+ result = pop3_state_auth_ntlm_type2msg_resp(conn, pop3code,
+ pop3c->state);
+ break;
+#endif
+
+#if defined(USE_WINDOWS_SSPI)
+ case POP3_AUTH_GSSAPI:
+ result = pop3_state_auth_gssapi_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_GSSAPI_TOKEN:
+ result = pop3_state_auth_gssapi_token_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_GSSAPI_NO_DATA:
+ result = pop3_state_auth_gssapi_no_data_resp(conn, pop3code,
+ pop3c->state);
+ break;
+#endif
+
+ case POP3_AUTH_XOAUTH2:
+ result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_CANCEL:
+ result = pop3_state_auth_cancel_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_AUTH_FINAL:
+ result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state);
+ break;
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ case POP3_APOP:
+ result = pop3_state_apop_resp(conn, pop3code, pop3c->state);
+ break;
+#endif
+
+ case POP3_USER:
+ result = pop3_state_user_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_PASS:
+ result = pop3_state_pass_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_COMMAND:
+ result = pop3_state_command_resp(conn, pop3code, pop3c->state);
+ break;
+
+ case POP3_QUIT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ state(conn, POP3_STOP);
+ break;
+ }
+ } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp));
+
+ return result;
+}
+
+/* Called repeatedly until done from multi.c */
+static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
+ if(result || !pop3c->ssldone)
+ return result;
+ }
+
+ result = Curl_pp_statemach(&pop3c->pp, FALSE);
+ *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
+
+ return result;
+}
+
+static CURLcode pop3_block_statemach(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ while(pop3c->state != POP3_STOP && !result)
+ result = Curl_pp_statemach(&pop3c->pp, TRUE);
+
+ return result;
+}
+
+/* Allocate and initialize the POP3 struct for the current SessionHandle if
+ required */
+static CURLcode pop3_init(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3;
+
+ pop3 = data->req.protop = calloc(sizeof(struct POP3), 1);
+ if(!pop3)
+ result = CURLE_OUT_OF_MEMORY;
+
+ return result;
+}
+
+/* For the POP3 "protocol connect" and "doing" phases only */
+static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ return Curl_pp_getsock(&conn->proto.pop3c.pp, socks, numsocks);
+}
+
+/***********************************************************************
+ *
+ * pop3_connect()
+ *
+ * This function should do everything that is to be considered a part of the
+ * connection phase.
+ *
+ * The variable 'done' points to will be TRUE if the protocol-layer connect
+ * phase is done when this function returns, or FALSE if not.
+ */
+static CURLcode pop3_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pingpong *pp = &pop3c->pp;
+
+ *done = FALSE; /* default to not done yet */
+
+ /* We always support persistent connections in POP3 */
+ connkeep(conn, "POP3 default");
+
+ /* Set the default response time-out */
+ pp->response_time = RESP_TIMEOUT;
+ pp->statemach_act = pop3_statemach_act;
+ pp->endofresp = pop3_endofresp;
+ pp->conn = conn;
+
+ /* Set the default preferred authentication type and mechanism */
+ pop3c->preftype = POP3_TYPE_ANY;
+ pop3c->prefmech = SASL_AUTH_ANY;
+
+ /* Initialise the pingpong layer */
+ Curl_pp_init(pp);
+
+ /* Parse the URL options */
+ result = pop3_parse_url_options(conn);
+ if(result)
+ return result;
+
+ /* Start off waiting for the server greeting response */
+ state(conn, POP3_SERVERGREET);
+
+ result = pop3_multi_statemach(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_done()
+ *
+ * The DONE function. This does what needs to be done after a single DO has
+ * performed.
+ *
+ * Input argument is already checked for validity.
+ */
+static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+
+ (void)premature;
+
+ if(!pop3)
+ /* When the easy handle is removed from the multi interface while libcurl
+ is still trying to resolve the host name, the POP3 struct is not yet
+ initialized. However, the removal action calls Curl_done() which in
+ turn calls this function, so we simply return success. */
+ return CURLE_OK;
+
+ if(status) {
+ connclose(conn, "POP3 done with bad status");
+ result = status; /* use the already set error code */
+ }
+
+ /* Cleanup our per-request based variables */
+ Curl_safefree(pop3->id);
+ Curl_safefree(pop3->custom);
+
+ /* Clear the transfer mode for the next request */
+ pop3->transfer = FTPTRANSFER_BODY;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_perform()
+ *
+ * This is the actual DO function for POP3. Get a message/listing according to
+ * the options previously setup.
+ */
+static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
+ bool *dophase_done)
+{
+ /* This is POP3 and no proxy */
+ CURLcode result = CURLE_OK;
+ struct POP3 *pop3 = conn->data->req.protop;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ if(conn->data->set.opt_no_body) {
+ /* Requested no body means no transfer */
+ pop3->transfer = FTPTRANSFER_INFO;
+ }
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* Start the first command in the DO phase */
+ result = pop3_perform_command(conn);
+ if(result)
+ return result;
+
+ /* Run the state-machine */
+ result = pop3_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_do()
+ *
+ * This function is registered as 'curl_do' function. It decodes the path
+ * parts etc as a wrapper to the actual DO function (pop3_perform).
+ *
+ * The input argument is already checked for validity.
+ */
+static CURLcode pop3_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+
+ *done = FALSE; /* default to false */
+
+ /* Parse the URL path */
+ result = pop3_parse_url_path(conn);
+ if(result)
+ return result;
+
+ /* Parse the custom request */
+ result = pop3_parse_custom_request(conn);
+ if(result)
+ return result;
+
+ result = pop3_regular_transfer(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_disconnect()
+ *
+ * Disconnect from an POP3 server. Cleanup protocol-specific per-connection
+ * resources. BLOCKING.
+ */
+static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ /* We cannot send quit unconditionally. If this connection is stale or
+ bad in any way, sending quit and waiting around here will make the
+ disconnect wait in vain and cause more problems than we need to. */
+
+ /* The POP3 session may or may not have been allocated/setup at this
+ point! */
+ if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart)
+ if(!pop3_perform_quit(conn))
+ (void)pop3_block_statemach(conn); /* ignore errors on QUIT */
+
+ /* Disconnect from the server */
+ Curl_pp_disconnect(&pop3c->pp);
+
+ /* Cleanup the SASL module */
+ Curl_sasl_cleanup(conn, pop3c->authused);
+
+ /* Cleanup our connection based variables */
+ Curl_safefree(pop3c->apoptimestamp);
+
+ return CURLE_OK;
+}
+
+/* Call this when the DO phase has completed */
+static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected)
+{
+ (void)conn;
+ (void)connected;
+
+ return CURLE_OK;
+}
+
+/* Called from multi.c while DOing */
+static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result = pop3_multi_statemach(conn, dophase_done);
+
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
+ result = pop3_dophase_done(conn, FALSE /* not connected */);
+
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_regular_transfer()
+ *
+ * The input argument is already checked for validity.
+ *
+ * Performs all commands done before a regular transfer between a local and a
+ * remote host.
+ */
+static CURLcode pop3_regular_transfer(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
+ struct SessionHandle *data = conn->data;
+
+ /* Make sure size is unknown at this point */
+ data->req.size = -1;
+
+ /* Set the progress data */
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ /* Carry out the perform */
+ result = pop3_perform(conn, &connected, dophase_done);
+
+ /* Perform post DO phase operations if necessary */
+ if(!result && *dophase_done)
+ result = pop3_dophase_done(conn, connected);
+
+ return result;
+}
+
+static CURLcode pop3_setup_connection(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+
+ /* Initialise the POP3 layer */
+ CURLcode result = pop3_init(conn);
+ if(result)
+ return result;
+
+ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+ /* Unless we have asked to tunnel POP3 operations through the proxy, we
+ switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+ if(conn->handler == &Curl_handler_pop3)
+ conn->handler = &Curl_handler_pop3_proxy;
+ else {
+#ifdef USE_SSL
+ conn->handler = &Curl_handler_pop3s_proxy;
+#else
+ failf(data, "POP3S not supported!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ /* set it up as an HTTP connection instead */
+ return conn->handler->setup_connection(conn);
+#else
+ failf(data, "POP3 over http proxy requires HTTP support built-in!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ data->state.path++; /* don't include the initial slash */
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * pop3_parse_url_options()
+ *
+ * Parse the URL login options.
+ */
+static CURLcode pop3_parse_url_options(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ const char *options = conn->options;
+ const char *ptr = options;
+ bool reset = TRUE;
+
+ while(ptr && *ptr) {
+ const char *key = ptr;
+
+ while(*ptr && *ptr != '=')
+ ptr++;
+
+ if(strnequal(key, "AUTH", 4)) {
+ size_t len = 0;
+ const char *value = ++ptr;
+
+ if(reset) {
+ reset = FALSE;
+ pop3c->preftype = POP3_TYPE_NONE;
+ pop3c->prefmech = SASL_AUTH_NONE;
+ }
+
+ while(*ptr && *ptr != ';') {
+ ptr++;
+ len++;
+ }
+
+ if(strnequal(value, "*", len)) {
+ pop3c->preftype = POP3_TYPE_ANY;
+ pop3c->prefmech = SASL_AUTH_ANY;
+ }
+ else if(strnequal(value, "+APOP", len)) {
+ pop3c->preftype = POP3_TYPE_APOP;
+ pop3c->prefmech = SASL_AUTH_NONE;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_LOGIN, len)) {
+ pop3c->preftype = POP3_TYPE_SASL;
+ pop3c->prefmech |= SASL_MECH_LOGIN;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_PLAIN, len)) {
+ pop3c->preftype = POP3_TYPE_SASL;
+ pop3c->prefmech |= SASL_MECH_PLAIN;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_CRAM_MD5, len)) {
+ pop3c->preftype = POP3_TYPE_SASL;
+ pop3c->prefmech |= SASL_MECH_CRAM_MD5;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_DIGEST_MD5, len)) {
+ pop3c->preftype = POP3_TYPE_SASL;
+ pop3c->prefmech |= SASL_MECH_DIGEST_MD5;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_GSSAPI, len)) {
+ pop3c->preftype = POP3_TYPE_SASL;
+ pop3c->prefmech |= SASL_MECH_GSSAPI;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_NTLM, len)) {
+ pop3c->preftype = POP3_TYPE_SASL;
+ pop3c->prefmech |= SASL_MECH_NTLM;
+ }
+ else if(strnequal(value, SASL_MECH_STRING_XOAUTH2, len)) {
+ pop3c->preftype = POP3_TYPE_SASL;
+ pop3c->prefmech |= SASL_MECH_XOAUTH2;
+ }
+
+ if(*ptr == ';')
+ ptr++;
+ }
+ else
+ result = CURLE_URL_MALFORMAT;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_parse_url_path()
+ *
+ * Parse the URL path into separate path components.
+ */
+static CURLcode pop3_parse_url_path(struct connectdata *conn)
+{
+ /* The POP3 struct is already initialised in pop3_connect() */
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+ const char *path = data->state.path;
+
+ /* URL decode the path for the message ID */
+ return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
+}
+
+/***********************************************************************
+ *
+ * pop3_parse_custom_request()
+ *
+ * Parse the custom request.
+ */
+static CURLcode pop3_parse_custom_request(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct POP3 *pop3 = data->req.protop;
+ const char *custom = data->set.str[STRING_CUSTOMREQUEST];
+
+ /* URL decode the custom request */
+ if(custom)
+ result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * pop3_calc_sasl_details()
+ *
+ * Calculate the required login details for SASL authentication.
+ */
+static CURLcode pop3_calc_sasl_details(struct connectdata *conn,
+ const char **mech,
+ char **initresp, size_t *len,
+ pop3state *state1, pop3state *state2)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ /* Calculate the supported authentication mechanism, by decreasing order of
+ security, as well as the initial response where appropriate */
+#if defined(USE_WINDOWS_SSPI)
+ if((pop3c->authmechs & SASL_MECH_GSSAPI) &&
+ (pop3c->prefmech & SASL_MECH_GSSAPI)) {
+ pop3c->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
+
+ *mech = SASL_MECH_STRING_GSSAPI;
+ *state1 = POP3_AUTH_GSSAPI;
+ *state2 = POP3_AUTH_GSSAPI_TOKEN;
+ pop3c->authused = SASL_MECH_GSSAPI;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_gssapi_user_message(data, conn->user,
+ conn->passwd, "pop",
+ pop3c->mutual_auth,
+ NULL, &conn->krb5,
+ initresp, len);
+ }
+ else
+#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
+ (pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
+ *mech = SASL_MECH_STRING_DIGEST_MD5;
+ *state1 = POP3_AUTH_DIGESTMD5;
+ pop3c->authused = SASL_MECH_DIGEST_MD5;
+ }
+ else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
+ (pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
+ *mech = SASL_MECH_STRING_CRAM_MD5;
+ *state1 = POP3_AUTH_CRAMMD5;
+ pop3c->authused = SASL_MECH_CRAM_MD5;
+ }
+ else
+#endif
+#ifdef USE_NTLM
+ if((pop3c->authmechs & SASL_MECH_NTLM) &&
+ (pop3c->prefmech & SASL_MECH_NTLM)) {
+ *mech = SASL_MECH_STRING_NTLM;
+ *state1 = POP3_AUTH_NTLM;
+ *state2 = POP3_AUTH_NTLM_TYPE2MSG;
+ pop3c->authused = SASL_MECH_NTLM;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
+ &conn->ntlm,
+ initresp, len);
+ }
+ else
+#endif
+ if(((pop3c->authmechs & SASL_MECH_XOAUTH2) &&
+ (pop3c->prefmech & SASL_MECH_XOAUTH2) &&
+ (pop3c->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
+ *mech = SASL_MECH_STRING_XOAUTH2;
+ *state1 = POP3_AUTH_XOAUTH2;
+ *state2 = POP3_AUTH_FINAL;
+ pop3c->authused = SASL_MECH_XOAUTH2;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_xoauth2_message(data, conn->user,
+ conn->xoauth2_bearer,
+ initresp, len);
+ }
+ else if((pop3c->authmechs & SASL_MECH_LOGIN) &&
+ (pop3c->prefmech & SASL_MECH_LOGIN)) {
+ *mech = SASL_MECH_STRING_LOGIN;
+ *state1 = POP3_AUTH_LOGIN;
+ *state2 = POP3_AUTH_LOGIN_PASSWD;
+ pop3c->authused = SASL_MECH_LOGIN;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_login_message(data, conn->user, initresp, len);
+ }
+ else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
+ (pop3c->prefmech & SASL_MECH_PLAIN)) {
+ *mech = SASL_MECH_STRING_PLAIN;
+ *state1 = POP3_AUTH_PLAIN;
+ *state2 = POP3_AUTH_FINAL;
+ pop3c->authused = SASL_MECH_PLAIN;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
+ initresp, len);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * Curl_pop3_write()
+ *
+ * This function scans the body after the end-of-body and writes everything
+ * until the end is found.
+ */
+CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
+{
+ /* This code could be made into a special function in the handler struct */
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SingleRequest *k = &data->req;
+
+ struct pop3_conn *pop3c = &conn->proto.pop3c;
+ bool strip_dot = FALSE;
+ size_t last = 0;
+ size_t i;
+
+ /* Search through the buffer looking for the end-of-body marker which is
+ 5 bytes (0d 0a 2e 0d 0a). Note that a line starting with a dot matches
+ the eob so the server will have prefixed it with an extra dot which we
+ need to strip out. Additionally the marker could of course be spread out
+ over 5 different data chunks. */
+ for(i = 0; i < nread; i++) {
+ size_t prev = pop3c->eob;
+
+ switch(str[i]) {
+ case 0x0d:
+ if(pop3c->eob == 0) {
+ pop3c->eob++;
+
+ if(i) {
+ /* Write out the body part that didn't match */
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
+ i - last);
+
+ if(result)
+ return result;
+
+ last = i;
+ }
+ }
+ else if(pop3c->eob == 3)
+ pop3c->eob++;
+ else
+ /* If the character match wasn't at position 0 or 3 then restart the
+ pattern matching */
+ pop3c->eob = 1;
+ break;
+
+ case 0x0a:
+ if(pop3c->eob == 1 || pop3c->eob == 4)
+ pop3c->eob++;
+ else
+ /* If the character match wasn't at position 1 or 4 then start the
+ search again */
+ pop3c->eob = 0;
+ break;
+
+ case 0x2e:
+ if(pop3c->eob == 2)
+ pop3c->eob++;
+ else if(pop3c->eob == 3) {
+ /* We have an extra dot after the CRLF which we need to strip off */
+ strip_dot = TRUE;
+ pop3c->eob = 0;
+ }
+ else
+ /* If the character match wasn't at position 2 then start the search
+ again */
+ pop3c->eob = 0;
+ break;
+
+ default:
+ pop3c->eob = 0;
+ break;
+ }
+
+ /* Did we have a partial match which has subsequently failed? */
+ if(prev && prev >= pop3c->eob) {
+ /* Strip can only be non-zero for the very first mismatch after CRLF
+ and then both prev and strip are equal and nothing will be output
+ below */
+ while(prev && pop3c->strip) {
+ prev--;
+ pop3c->strip--;
+ }
+
+ if(prev) {
+ /* If the partial match was the CRLF and dot then only write the CRLF
+ as the server would have inserted the dot */
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB,
+ strip_dot ? prev - 1 : prev);
+
+ if(result)
+ return result;
+
+ last = i;
+ strip_dot = FALSE;
+ }
+ }
+ }
+
+ if(pop3c->eob == POP3_EOB_LEN) {
+ /* We have a full match so the transfer is done, however we must transfer
+ the CRLF at the start of the EOB as this is considered to be part of the
+ message as per RFC-1939, sect. 3 */
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2);
+
+ k->keepon &= ~KEEP_RECV;
+ pop3c->eob = 0;
+
+ return result;
+ }
+
+ if(pop3c->eob)
+ /* While EOB is matching nothing should be output */
+ return CURLE_OK;
+
+ if(nread - last) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
+ nread - last);
+ }
+
+ return result;
+}
+
+#endif /* CURL_DISABLE_POP3 */
diff --git a/external/libcurl_android/jni/libcurl/lib/pop3.h b/external/libcurl_android/jni/libcurl/lib/pop3.h
new file mode 100755
index 00000000..729a55ad
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/pop3.h
@@ -0,0 +1,110 @@
+#ifndef HEADER_CURL_POP3_H
+#define HEADER_CURL_POP3_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "pingpong.h"
+
+/****************************************************************************
+ * POP3 unique setup
+ ***************************************************************************/
+typedef enum {
+ POP3_STOP, /* do nothing state, stops the state machine */
+ POP3_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ POP3_CAPA,
+ POP3_STARTTLS,
+ POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ POP3_AUTH_PLAIN,
+ POP3_AUTH_LOGIN,
+ POP3_AUTH_LOGIN_PASSWD,
+ POP3_AUTH_CRAMMD5,
+ POP3_AUTH_DIGESTMD5,
+ POP3_AUTH_DIGESTMD5_RESP,
+ POP3_AUTH_NTLM,
+ POP3_AUTH_NTLM_TYPE2MSG,
+ POP3_AUTH_GSSAPI,
+ POP3_AUTH_GSSAPI_TOKEN,
+ POP3_AUTH_GSSAPI_NO_DATA,
+ POP3_AUTH_XOAUTH2,
+ POP3_AUTH_CANCEL,
+ POP3_AUTH_FINAL,
+ POP3_APOP,
+ POP3_USER,
+ POP3_PASS,
+ POP3_COMMAND,
+ POP3_QUIT,
+ POP3_LAST /* never used */
+} pop3state;
+
+/* This POP3 struct is used in the SessionHandle. All POP3 data that is
+ connection-oriented must be in pop3_conn to properly deal with the fact that
+ perhaps the SessionHandle is changed between the times the connection is
+ used. */
+struct POP3 {
+ curl_pp_transfer transfer;
+ char *id; /* Message ID */
+ char *custom; /* Custom Request */
+};
+
+/* pop3_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct pop3_conn {
+ struct pingpong pp;
+ pop3state state; /* Always use pop3.c:state() to change state! */
+ bool ssldone; /* Is connect() over SSL done? */
+ size_t eob; /* Number of bytes of the EOB (End Of Body) that
+ have been received so far */
+ size_t strip; /* Number of bytes from the start to ignore as
+ non-body */
+ unsigned int authtypes; /* Accepted authentication types */
+ unsigned int authmechs; /* Accepted SASL authentication mechanisms */
+ unsigned int preftype; /* Preferred authentication type */
+ unsigned int prefmech; /* Preferred SASL authentication mechanism */
+ unsigned int authused; /* SASL auth mechanism used for the connection */
+ char *apoptimestamp; /* APOP timestamp from the server greeting */
+ bool tls_supported; /* StartTLS capability supported by server */
+ bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
+};
+
+extern const struct Curl_handler Curl_handler_pop3;
+extern const struct Curl_handler Curl_handler_pop3s;
+
+/* Authentication type flags */
+#define POP3_TYPE_CLEARTEXT (1 << 0)
+#define POP3_TYPE_APOP (1 << 1)
+#define POP3_TYPE_SASL (1 << 2)
+
+/* Authentication type values */
+#define POP3_TYPE_NONE 0
+#define POP3_TYPE_ANY ~0U
+
+/* This is the 5-bytes End-Of-Body marker for POP3 */
+#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
+#define POP3_EOB_LEN 5
+
+/* This function scans the body after the end-of-body and writes everything
+ * until the end is found */
+CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread);
+
+#endif /* HEADER_CURL_POP3_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/progress.c b/external/libcurl_android/jni/libcurl/lib/progress.c
new file mode 100755
index 00000000..f147ce71
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/progress.c
@@ -0,0 +1,494 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "urldata.h"
+#include "sendf.h"
+#include "progress.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
+ byte) */
+static void time2str(char *r, curl_off_t seconds)
+{
+ curl_off_t d, h, m, s;
+ if(seconds <= 0) {
+ strcpy(r, "--:--:--");
+ return;
+ }
+ h = seconds / CURL_OFF_T_C(3600);
+ if(h <= CURL_OFF_T_C(99)) {
+ m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
+ s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
+ snprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
+ ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
+ }
+ else {
+ /* this equals to more than 99 hours, switch to a more suitable output
+ format to fit within the limits. */
+ d = seconds / CURL_OFF_T_C(86400);
+ h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
+ if(d <= CURL_OFF_T_C(999))
+ snprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
+ "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h);
+ else
+ snprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d);
+ }
+}
+
+/* The point of this function would be to return a string of the input data,
+ but never longer than 5 columns (+ one zero byte).
+ Add suffix k, M, G when suitable... */
+static char *max5data(curl_off_t bytes, char *max5)
+{
+#define ONE_KILOBYTE CURL_OFF_T_C(1024)
+#define ONE_MEGABYTE (CURL_OFF_T_C(1024) * ONE_KILOBYTE)
+#define ONE_GIGABYTE (CURL_OFF_T_C(1024) * ONE_MEGABYTE)
+#define ONE_TERABYTE (CURL_OFF_T_C(1024) * ONE_GIGABYTE)
+#define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE)
+
+ if(bytes < CURL_OFF_T_C(100000))
+ snprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE)
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE);
+
+ else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE)
+ /* 'XX.XM' is good as long as we're less than 100 megs */
+ snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+ CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
+ (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
+
+#if (CURL_SIZEOF_CURL_OFF_T > 4)
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
+ /* 'XXXXM' is good until we're at 10000MB or above */
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+
+ else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE)
+ /* 10000 MB - 100 GB, we show it as XX.XG */
+ snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+ CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE,
+ (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) );
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE)
+ /* up to 10000GB, display without decimal: XXXXG */
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE);
+
+ else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE)
+ /* up to 10000TB, display without decimal: XXXXT */
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE);
+
+ else
+ /* up to 10000PB, display without decimal: XXXXP */
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
+
+ /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number
+ can hold, but our data type is signed so 8192PB will be the maximum. */
+
+#else
+
+ else
+ snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+
+#endif
+
+ return max5;
+}
+
+/*
+
+ New proposed interface, 9th of February 2000:
+
+ pgrsStartNow() - sets start time
+ pgrsSetDownloadSize(x) - known expected download size
+ pgrsSetUploadSize(x) - known expected upload size
+ pgrsSetDownloadCounter() - amount of data currently downloaded
+ pgrsSetUploadCounter() - amount of data currently uploaded
+ pgrsUpdate() - show progress
+ pgrsDone() - transfer complete
+
+*/
+
+int Curl_pgrsDone(struct connectdata *conn)
+{
+ int rc;
+ struct SessionHandle *data = conn->data;
+ data->progress.lastshow=0;
+ rc = Curl_pgrsUpdate(conn); /* the final (forced) update */
+ if(rc)
+ return rc;
+
+ if(!(data->progress.flags & PGRS_HIDE) &&
+ !data->progress.callback)
+ /* only output if we don't use a progress callback and we're not
+ * hidden */
+ fprintf(data->set.err, "\n");
+
+ data->progress.speeder_c = 0; /* reset the progress meter display */
+ return 0;
+}
+
+/* reset all times except redirect, and reset the known transfer sizes */
+void Curl_pgrsResetTimesSizes(struct SessionHandle *data)
+{
+ data->progress.t_nslookup = 0.0;
+ data->progress.t_connect = 0.0;
+ data->progress.t_pretransfer = 0.0;
+ data->progress.t_starttransfer = 0.0;
+
+ Curl_pgrsSetDownloadSize(data, -1);
+ Curl_pgrsSetUploadSize(data, -1);
+}
+
+void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
+{
+ struct timeval now = Curl_tvnow();
+
+ switch(timer) {
+ default:
+ case TIMER_NONE:
+ /* mistake filter */
+ break;
+ case TIMER_STARTOP:
+ /* This is set at the start of a transfer */
+ data->progress.t_startop = now;
+ break;
+ case TIMER_STARTSINGLE:
+ /* This is set at the start of each single fetch */
+ data->progress.t_startsingle = now;
+ break;
+
+ case TIMER_STARTACCEPT:
+ data->progress.t_acceptdata = Curl_tvnow();
+ break;
+
+ case TIMER_NAMELOOKUP:
+ data->progress.t_nslookup =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_CONNECT:
+ data->progress.t_connect =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_APPCONNECT:
+ data->progress.t_appconnect =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_PRETRANSFER:
+ data->progress.t_pretransfer =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_STARTTRANSFER:
+ data->progress.t_starttransfer =
+ Curl_tvdiff_secs(now, data->progress.t_startsingle);
+ break;
+ case TIMER_POSTRANSFER:
+ /* this is the normal end-of-transfer thing */
+ break;
+ case TIMER_REDIRECT:
+ data->progress.t_redirect = Curl_tvdiff_secs(now, data->progress.start);
+ break;
+ }
+}
+
+void Curl_pgrsStartNow(struct SessionHandle *data)
+{
+ data->progress.speeder_c = 0; /* reset the progress meter display */
+ data->progress.start = Curl_tvnow();
+ /* clear all bits except HIDE and HEADERS_OUT */
+ data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
+}
+
+void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size)
+{
+ data->progress.downloaded = size;
+}
+
+void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size)
+{
+ data->progress.uploaded = size;
+}
+
+void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size)
+{
+ if(size >= 0) {
+ data->progress.size_dl = size;
+ data->progress.flags |= PGRS_DL_SIZE_KNOWN;
+ }
+ else {
+ data->progress.size_dl = 0;
+ data->progress.flags &= ~PGRS_DL_SIZE_KNOWN;
+ }
+}
+
+void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size)
+{
+ if(size >= 0) {
+ data->progress.size_ul = size;
+ data->progress.flags |= PGRS_UL_SIZE_KNOWN;
+ }
+ else {
+ data->progress.size_ul = 0;
+ data->progress.flags &= ~PGRS_UL_SIZE_KNOWN;
+ }
+}
+
+/*
+ * Curl_pgrsUpdate() returns 0 for success or the value returned by the
+ * progress callback!
+ */
+int Curl_pgrsUpdate(struct connectdata *conn)
+{
+ struct timeval now;
+ int result;
+ char max5[6][10];
+ curl_off_t dlpercen=0;
+ curl_off_t ulpercen=0;
+ curl_off_t total_percen=0;
+ curl_off_t total_transfer;
+ curl_off_t total_expected_transfer;
+ curl_off_t timespent;
+ struct SessionHandle *data = conn->data;
+ int nowindex = data->progress.speeder_c% CURR_TIME;
+ int checkindex;
+ int countindex; /* amount of seconds stored in the speeder array */
+ char time_left[10];
+ char time_total[10];
+ char time_spent[10];
+ curl_off_t ulestimate=0;
+ curl_off_t dlestimate=0;
+ curl_off_t total_estimate;
+ bool shownow=FALSE;
+
+ now = Curl_tvnow(); /* what time is it */
+
+ /* The time spent so far (from the start) */
+ data->progress.timespent =
+ (double)(now.tv_sec - data->progress.start.tv_sec) +
+ (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0;
+ timespent = (curl_off_t)data->progress.timespent;
+
+ /* The average download speed this far */
+ data->progress.dlspeed = (curl_off_t)
+ ((double)data->progress.downloaded/
+ (data->progress.timespent>0?data->progress.timespent:1));
+
+ /* The average upload speed this far */
+ data->progress.ulspeed = (curl_off_t)
+ ((double)data->progress.uploaded/
+ (data->progress.timespent>0?data->progress.timespent:1));
+
+ /* Calculations done at most once a second, unless end is reached */
+ if(data->progress.lastshow != (long)now.tv_sec) {
+ shownow = TRUE;
+
+ data->progress.lastshow = now.tv_sec;
+
+ /* Let's do the "current speed" thing, which should use the fastest
+ of the dl/ul speeds. Store the faster speed at entry 'nowindex'. */
+ data->progress.speeder[ nowindex ] =
+ data->progress.downloaded>data->progress.uploaded?
+ data->progress.downloaded:data->progress.uploaded;
+
+ /* remember the exact time for this moment */
+ data->progress.speeder_time [ nowindex ] = now;
+
+ /* 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]);
+ if(0 == span_ms)
+ span_ms=1; /* at least one millisecond MUST have passed */
+
+ /* Calculate the average speed the last 'span_ms' milliseconds */
+ {
+ curl_off_t amount = data->progress.speeder[nowindex]-
+ data->progress.speeder[checkindex];
+
+ if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */)
+ /* the 'amount' value is bigger than would fit in 32 bits if
+ multiplied with 1000, so we use the double math for this */
+ data->progress.current_speed = (curl_off_t)
+ ((double)amount/((double)span_ms/1000.0));
+ else
+ /* the 'amount' value is small enough to fit within 32 bits even
+ when multiplied with 1000 */
+ data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms;
+ }
+ }
+ 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;
+
+ } /* Calculations end */
+
+ if(!(data->progress.flags & PGRS_HIDE)) {
+ /* progress meter has not been shut off */
+
+ if(data->set.fxferinfo) {
+ /* There's a callback set, call that */
+ result= data->set.fxferinfo(data->set.progress_client,
+ data->progress.size_dl,
+ data->progress.downloaded,
+ data->progress.size_ul,
+ data->progress.uploaded);
+ if(result)
+ failf(data, "Callback aborted");
+ return result;
+ }
+ else if(data->set.fprogress) {
+ /* The older deprecated callback is set, call that */
+ result= data->set.fprogress(data->set.progress_client,
+ (double)data->progress.size_dl,
+ (double)data->progress.downloaded,
+ (double)data->progress.size_ul,
+ (double)data->progress.uploaded);
+ if(result)
+ failf(data, "Callback aborted");
+ return result;
+ }
+
+ if(!shownow)
+ /* only show the internal progress meter once per second */
+ return 0;
+
+ /* If there's no external callback set, use internal code to show
+ progress */
+
+ if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
+ if(data->state.resume_from) {
+ fprintf(data->set.err,
+ "** Resuming transfer from byte position %"
+ CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
+ }
+ fprintf(data->set.err,
+ " %% Total %% Received %% Xferd Average Speed "
+ "Time Time Time Current\n"
+ " Dload Upload "
+ "Total Spent Left Speed\n");
+ data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */
+ }
+
+ /* Figure out the estimated time of arrival for the upload */
+ if((data->progress.flags & PGRS_UL_SIZE_KNOWN) &&
+ (data->progress.ulspeed > CURL_OFF_T_C(0))) {
+ ulestimate = data->progress.size_ul / data->progress.ulspeed;
+
+ if(data->progress.size_ul > CURL_OFF_T_C(10000))
+ ulpercen = data->progress.uploaded /
+ (data->progress.size_ul/CURL_OFF_T_C(100));
+ else if(data->progress.size_ul > CURL_OFF_T_C(0))
+ ulpercen = (data->progress.uploaded*100) /
+ data->progress.size_ul;
+ }
+
+ /* ... and the download */
+ if((data->progress.flags & PGRS_DL_SIZE_KNOWN) &&
+ (data->progress.dlspeed > CURL_OFF_T_C(0))) {
+ dlestimate = data->progress.size_dl / data->progress.dlspeed;
+
+ if(data->progress.size_dl > CURL_OFF_T_C(10000))
+ dlpercen = data->progress.downloaded /
+ (data->progress.size_dl/CURL_OFF_T_C(100));
+ else if(data->progress.size_dl > CURL_OFF_T_C(0))
+ dlpercen = (data->progress.downloaded*100) /
+ data->progress.size_dl;
+ }
+
+ /* Now figure out which of them is slower and use that one for the
+ total estimate! */
+ total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
+
+ /* create the three time strings */
+ time2str(time_left, total_estimate > 0?(total_estimate - timespent):0);
+ time2str(time_total, total_estimate);
+ time2str(time_spent, timespent);
+
+ /* Get the total amount of data expected to get transferred */
+ total_expected_transfer =
+ (data->progress.flags & PGRS_UL_SIZE_KNOWN?
+ data->progress.size_ul:data->progress.uploaded)+
+ (data->progress.flags & PGRS_DL_SIZE_KNOWN?
+ data->progress.size_dl:data->progress.downloaded);
+
+ /* We have transferred this much so far */
+ total_transfer = data->progress.downloaded + data->progress.uploaded;
+
+ /* Get the percentage of data transferred so far */
+ if(total_expected_transfer > CURL_OFF_T_C(10000))
+ total_percen = total_transfer /
+ (total_expected_transfer/CURL_OFF_T_C(100));
+ else if(total_expected_transfer > CURL_OFF_T_C(0))
+ total_percen = (total_transfer*100) / total_expected_transfer;
+
+ fprintf(data->set.err,
+ "\r"
+ "%3" CURL_FORMAT_CURL_OFF_T " %s "
+ "%3" CURL_FORMAT_CURL_OFF_T " %s "
+ "%3" CURL_FORMAT_CURL_OFF_T " %s %s %s %s %s %s %s",
+ total_percen, /* 3 letters */ /* total % */
+ max5data(total_expected_transfer, max5[2]), /* total size */
+ dlpercen, /* 3 letters */ /* rcvd % */
+ max5data(data->progress.downloaded, max5[0]), /* rcvd size */
+ ulpercen, /* 3 letters */ /* xfer % */
+ max5data(data->progress.uploaded, max5[1]), /* xfer size */
+ max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */
+ max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */
+ time_total, /* 8 letters */ /* total time */
+ time_spent, /* 8 letters */ /* time spent */
+ time_left, /* 8 letters */ /* time left */
+ max5data(data->progress.current_speed, max5[5]) /* current speed */
+ );
+
+ /* we flush the output stream to make it appear as soon as possible */
+ fflush(data->set.err);
+
+ } /* !(data->progress.flags & PGRS_HIDE) */
+
+ return 0;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/progress.h b/external/libcurl_android/jni/libcurl/lib/progress.h
new file mode 100755
index 00000000..a1e6f1a2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/progress.h
@@ -0,0 +1,73 @@
+#ifndef HEADER_CURL_PROGRESS_H
+#define HEADER_CURL_PROGRESS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "timeval.h"
+
+
+typedef enum {
+ TIMER_NONE,
+ TIMER_STARTOP,
+ TIMER_STARTSINGLE,
+ TIMER_NAMELOOKUP,
+ TIMER_CONNECT,
+ TIMER_APPCONNECT,
+ TIMER_PRETRANSFER,
+ TIMER_STARTTRANSFER,
+ TIMER_POSTRANSFER,
+ TIMER_STARTACCEPT,
+ TIMER_REDIRECT,
+ TIMER_LAST /* must be last */
+} timerid;
+
+int Curl_pgrsDone(struct connectdata *);
+void Curl_pgrsStartNow(struct SessionHandle *data);
+void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size);
+void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size);
+void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size);
+void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size);
+int Curl_pgrsUpdate(struct connectdata *);
+void Curl_pgrsResetTimesSizes(struct SessionHandle *data);
+void Curl_pgrsTime(struct SessionHandle *data, timerid timer);
+
+
+/* Don't show progress for sizes smaller than: */
+#define LEAST_SIZE_PROGRESS BUFSIZE
+
+#define PROGRESS_DOWNLOAD (1<<0)
+#define PROGRESS_UPLOAD (1<<1)
+#define PROGRESS_DOWN_AND_UP (PROGRESS_UPLOAD | PROGRESS_DOWNLOAD)
+
+#define PGRS_SHOW_DL (1<<0)
+#define PGRS_SHOW_UL (1<<1)
+#define PGRS_DONE_DL (1<<2)
+#define PGRS_DONE_UL (1<<3)
+#define PGRS_HIDE (1<<4)
+#define PGRS_UL_SIZE_KNOWN (1<<5)
+#define PGRS_DL_SIZE_KNOWN (1<<6)
+
+#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */
+
+
+#endif /* HEADER_CURL_PROGRESS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/rawstr.c b/external/libcurl_android/jni/libcurl/lib/rawstr.c
new file mode 100755
index 00000000..e27dac4a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/rawstr.c
@@ -0,0 +1,142 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "rawstr.h"
+
+/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
+ its behavior is altered by the current locale. */
+char Curl_raw_toupper(char in)
+{
+ switch (in) {
+ case 'a':
+ return 'A';
+ case 'b':
+ return 'B';
+ case 'c':
+ return 'C';
+ case 'd':
+ return 'D';
+ case 'e':
+ return 'E';
+ case 'f':
+ return 'F';
+ case 'g':
+ return 'G';
+ case 'h':
+ return 'H';
+ case 'i':
+ return 'I';
+ case 'j':
+ return 'J';
+ case 'k':
+ return 'K';
+ case 'l':
+ return 'L';
+ case 'm':
+ return 'M';
+ case 'n':
+ return 'N';
+ case 'o':
+ return 'O';
+ case 'p':
+ return 'P';
+ case 'q':
+ return 'Q';
+ case 'r':
+ return 'R';
+ case 's':
+ return 'S';
+ case 't':
+ return 'T';
+ case 'u':
+ return 'U';
+ case 'v':
+ return 'V';
+ case 'w':
+ return 'W';
+ case 'x':
+ return 'X';
+ case 'y':
+ return 'Y';
+ case 'z':
+ return 'Z';
+ }
+ return in;
+}
+
+/*
+ * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
+ * to be locale independent and only compare strings we know are safe for
+ * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
+ * some further explanation to why this function is necessary.
+ *
+ * The function is capable of comparing a-z case insensitively even for
+ * non-ascii.
+ */
+
+int Curl_raw_equal(const char *first, const char *second)
+{
+ while(*first && *second) {
+ if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
+ /* get out of the loop as soon as they don't match */
+ break;
+ first++;
+ second++;
+ }
+ /* we do the comparison here (possibly again), just to make sure that if the
+ loop above is skipped because one of the strings reached zero, we must not
+ return this as a successful match */
+ return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
+}
+
+int Curl_raw_nequal(const char *first, const char *second, size_t max)
+{
+ while(*first && *second && max) {
+ if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
+ break;
+ }
+ max--;
+ first++;
+ second++;
+ }
+ if(0 == max)
+ return 1; /* they are equal this far */
+
+ return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
+}
+
+/* Copy an upper case version of the string from src to dest. The
+ * strings may overlap. No more than n characters of the string are copied
+ * (including any NUL) and the destination string will NOT be
+ * NUL-terminated if that limit is reached.
+ */
+void Curl_strntoupper(char *dest, const char *src, size_t n)
+{
+ if(n < 1)
+ return;
+
+ do {
+ *dest++ = Curl_raw_toupper(*src);
+ } while(*src++ && --n);
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/rawstr.h b/external/libcurl_android/jni/libcurl/lib/rawstr.h
new file mode 100755
index 00000000..b491460d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/rawstr.h
@@ -0,0 +1,47 @@
+#ifndef HEADER_CURL_RAWSTR_H
+#define HEADER_CURL_RAWSTR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+/*
+ * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
+ * to be locale independent and only compare strings we know are safe for
+ * this.
+ *
+ * The function is capable of comparing a-z case insensitively even for
+ * non-ascii.
+ */
+int Curl_raw_equal(const char *first, const char *second);
+int Curl_raw_nequal(const char *first, const char *second, size_t max);
+
+char Curl_raw_toupper(char in);
+
+/* checkprefix() is a shorter version of the above, used when the first
+ argument is zero-byte terminated */
+#define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a))
+
+void Curl_strntoupper(char *dest, const char *src, size_t n);
+
+#endif /* HEADER_CURL_RAWSTR_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/rtsp.c b/external/libcurl_android/jni/libcurl/lib/rtsp.c
new file mode 100755
index 00000000..029738d9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/rtsp.c
@@ -0,0 +1,809 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_RTSP
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+#include "multiif.h"
+#include "http.h"
+#include "url.h"
+#include "progress.h"
+#include "rtsp.h"
+#include "rawstr.h"
+#include "curl_memory.h"
+#include "select.h"
+#include "connect.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * TODO (general)
+ * -incoming server requests
+ * -server CSeq counter
+ * -digest authentication
+ * -connect thru proxy
+ * -pipelining?
+ */
+
+
+#define RTP_PKT_CHANNEL(p) ((int)((unsigned char)((p)[1])))
+
+#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \
+ ((int)((unsigned char)((p)[3]))))
+
+/* protocol-specific functions set up to be called by the main engine */
+static CURLcode rtsp_do(struct connectdata *conn, bool *done);
+static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature);
+static CURLcode rtsp_connect(struct connectdata *conn, bool *done);
+static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead);
+
+static int rtsp_getsock_do(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+/*
+ * Parse and write out any available RTP data.
+ *
+ * nread: amount of data left after k->str. will be modified if RTP
+ * data is parsed and k->str is moved up
+ * readmore: whether or not the RTP parser needs more data right away
+ */
+static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data,
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *readmore);
+
+static CURLcode rtsp_setup_connection(struct connectdata *conn);
+
+
+/* this returns the socket to wait for in the DO and DOING state for the multi
+ interface and then we're always _sending_ a request and thus we wait for
+ the single socket to become writable only */
+static int rtsp_getsock_do(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ /* write mode */
+ (void)numsocks; /* unused, we trust it to be at least 1 */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_WRITESOCK(0);
+}
+
+static
+CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
+
+
+/*
+ * RTSP handler interface.
+ */
+const struct Curl_handler Curl_handler_rtsp = {
+ "RTSP", /* scheme */
+ rtsp_setup_connection, /* setup_connection */
+ rtsp_do, /* do_it */
+ rtsp_done, /* done */
+ ZERO_NULL, /* do_more */
+ rtsp_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ rtsp_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ rtsp_disconnect, /* disconnect */
+ rtsp_rtp_readwrite, /* readwrite */
+ PORT_RTSP, /* defport */
+ CURLPROTO_RTSP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+
+static CURLcode rtsp_setup_connection(struct connectdata *conn)
+{
+ struct RTSP *rtsp;
+
+ conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP));
+ if(!rtsp)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+
+/*
+ * The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not
+ * want to block the application forever while receiving a stream. Therefore,
+ * we cannot assume that an RTSP socket is dead just because it is readable.
+ *
+ * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket
+ * and distinguish between closed and data.
+ */
+bool Curl_rtsp_connisdead(struct connectdata *check)
+{
+ int sval;
+ bool ret_val = TRUE;
+
+ sval = Curl_socket_ready(check->sock[FIRSTSOCKET], CURL_SOCKET_BAD, 0);
+ if(sval == 0) {
+ /* timeout */
+ ret_val = FALSE;
+ }
+ else if(sval & CURL_CSELECT_ERR) {
+ /* socket is in an error state */
+ ret_val = TRUE;
+ }
+ else if((sval & CURL_CSELECT_IN) && check->data) {
+ /* readable with no error. could be closed or could be alive but we can
+ only check if we have a proper SessionHandle for the connection */
+ curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check);
+ if(connectinfo != CURL_SOCKET_BAD)
+ ret_val = FALSE;
+ }
+
+ return ret_val;
+}
+
+static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode httpStatus;
+ struct SessionHandle *data = conn->data;
+
+ httpStatus = Curl_http_connect(conn, done);
+
+ /* Initialize the CSeq if not already done */
+ if(data->state.rtsp_next_client_CSeq == 0)
+ data->state.rtsp_next_client_CSeq = 1;
+ if(data->state.rtsp_next_server_CSeq == 0)
+ data->state.rtsp_next_server_CSeq = 1;
+
+ conn->proto.rtspc.rtp_channel = -1;
+
+ return httpStatus;
+}
+
+static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead)
+{
+ (void) dead;
+ Curl_safefree(conn->proto.rtspc.rtp_buf);
+ return CURLE_OK;
+}
+
+
+static CURLcode rtsp_done(struct connectdata *conn,
+ CURLcode status, bool premature)
+{
+ struct SessionHandle *data = conn->data;
+ struct RTSP *rtsp = data->req.protop;
+ CURLcode httpStatus;
+ long CSeq_sent;
+ long CSeq_recv;
+
+ /* Bypass HTTP empty-reply checks on receive */
+ if(data->set.rtspreq == RTSPREQ_RECEIVE)
+ premature = TRUE;
+
+ httpStatus = Curl_http_done(conn, status, premature);
+
+ if(rtsp) {
+ /* Check the sequence numbers */
+ CSeq_sent = rtsp->CSeq_sent;
+ CSeq_recv = rtsp->CSeq_recv;
+ if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) {
+ failf(data,
+ "The CSeq of this request %ld did not match the response %ld",
+ CSeq_sent, CSeq_recv);
+ return CURLE_RTSP_CSEQ_ERROR;
+ }
+ else if(data->set.rtspreq == RTSPREQ_RECEIVE &&
+ (conn->proto.rtspc.rtp_channel == -1)) {
+ infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
+ /* TODO CPC: Server -> Client logic here */
+ }
+ }
+
+ return httpStatus;
+}
+
+static CURLcode rtsp_do(struct connectdata *conn, bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode result=CURLE_OK;
+ Curl_RtspReq rtspreq = data->set.rtspreq;
+ struct RTSP *rtsp = data->req.protop;
+ struct HTTP *http;
+ Curl_send_buffer *req_buffer;
+ curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
+ curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
+
+ const char *p_request = NULL;
+ const char *p_session_id = NULL;
+ const char *p_accept = NULL;
+ const char *p_accept_encoding = NULL;
+ const char *p_range = NULL;
+ const char *p_referrer = NULL;
+ const char *p_stream_uri = NULL;
+ const char *p_transport = NULL;
+ const char *p_uagent = NULL;
+
+ *done = TRUE;
+
+ http = &(rtsp->http_wrapper);
+ /* Assert that no one has changed the RTSP struct in an evil way */
+ DEBUGASSERT((void *)http == (void *)rtsp);
+
+ rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
+ rtsp->CSeq_recv = 0;
+
+ /* Setup the 'p_request' pointer to the proper p_request string
+ * Since all RTSP requests are included here, there is no need to
+ * support custom requests like HTTP.
+ **/
+ DEBUGASSERT((rtspreq > RTSPREQ_NONE && rtspreq < RTSPREQ_LAST));
+ data->set.opt_no_body = TRUE; /* most requests don't contain a body */
+ switch(rtspreq) {
+ case RTSPREQ_NONE:
+ failf(data, "Got invalid RTSP request: RTSPREQ_NONE");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ case RTSPREQ_OPTIONS:
+ p_request = "OPTIONS";
+ break;
+ case RTSPREQ_DESCRIBE:
+ p_request = "DESCRIBE";
+ data->set.opt_no_body = FALSE;
+ break;
+ case RTSPREQ_ANNOUNCE:
+ p_request = "ANNOUNCE";
+ break;
+ case RTSPREQ_SETUP:
+ p_request = "SETUP";
+ break;
+ case RTSPREQ_PLAY:
+ p_request = "PLAY";
+ break;
+ case RTSPREQ_PAUSE:
+ p_request = "PAUSE";
+ break;
+ case RTSPREQ_TEARDOWN:
+ p_request = "TEARDOWN";
+ break;
+ case RTSPREQ_GET_PARAMETER:
+ /* GET_PARAMETER's no_body status is determined later */
+ p_request = "GET_PARAMETER";
+ data->set.opt_no_body = FALSE;
+ break;
+ case RTSPREQ_SET_PARAMETER:
+ p_request = "SET_PARAMETER";
+ break;
+ case RTSPREQ_RECORD:
+ p_request = "RECORD";
+ break;
+ case RTSPREQ_RECEIVE:
+ p_request = "";
+ /* Treat interleaved RTP as body*/
+ data->set.opt_no_body = FALSE;
+ break;
+ case RTSPREQ_LAST:
+ failf(data, "Got invalid RTSP request: RTSPREQ_LAST");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ if(rtspreq == RTSPREQ_RECEIVE) {
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
+ &http->readbytecount, -1, NULL);
+
+ return result;
+ }
+
+ p_session_id = data->set.str[STRING_RTSP_SESSION_ID];
+ if(!p_session_id &&
+ (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) {
+ failf(data, "Refusing to issue an RTSP request [%s] without a session ID.",
+ p_request ? p_request : "");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ /* TODO: auth? */
+ /* TODO: proxy? */
+
+ /* Stream URI. Default to server '*' if not specified */
+ if(data->set.str[STRING_RTSP_STREAM_URI]) {
+ p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI];
+ }
+ else {
+ p_stream_uri = "*";
+ }
+
+ /* Transport Header for SETUP requests */
+ p_transport = Curl_checkheaders(conn, "Transport:");
+ if(rtspreq == RTSPREQ_SETUP && !p_transport) {
+ /* New Transport: setting? */
+ if(data->set.str[STRING_RTSP_TRANSPORT]) {
+ Curl_safefree(conn->allocptr.rtsp_transport);
+
+ conn->allocptr.rtsp_transport =
+ aprintf("Transport: %s\r\n",
+ data->set.str[STRING_RTSP_TRANSPORT]);
+ if(!conn->allocptr.rtsp_transport)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ failf(data,
+ "Refusing to issue an RTSP SETUP without a Transport: header.");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ p_transport = conn->allocptr.rtsp_transport;
+ }
+
+ /* Accept Headers for DESCRIBE requests */
+ if(rtspreq == RTSPREQ_DESCRIBE) {
+ /* Accept Header */
+ p_accept = Curl_checkheaders(conn, "Accept:")?
+ NULL:"Accept: application/sdp\r\n";
+
+ /* Accept-Encoding header */
+ if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ data->set.str[STRING_ENCODING]) {
+ Curl_safefree(conn->allocptr.accept_encoding);
+ conn->allocptr.accept_encoding =
+ aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
+
+ if(!conn->allocptr.accept_encoding)
+ return CURLE_OUT_OF_MEMORY;
+
+ p_accept_encoding = conn->allocptr.accept_encoding;
+ }
+ }
+
+ /* The User-Agent string might have been allocated in url.c already, because
+ it might have been used in the proxy connect, but if we have got a header
+ with the user-agent string specified, we erase the previously made string
+ here. */
+ if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
+ Curl_safefree(conn->allocptr.uagent);
+ conn->allocptr.uagent = NULL;
+ }
+ else if(!Curl_checkheaders(conn, "User-Agent:") &&
+ data->set.str[STRING_USERAGENT]) {
+ p_uagent = conn->allocptr.uagent;
+ }
+
+ /* Referrer */
+ Curl_safefree(conn->allocptr.ref);
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
+ conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ else
+ conn->allocptr.ref = NULL;
+
+ p_referrer = conn->allocptr.ref;
+
+ /*
+ * Range Header
+ * Only applies to PLAY, PAUSE, RECORD
+ *
+ * Go ahead and use the Range stuff supplied for HTTP
+ */
+ if(data->state.use_range &&
+ (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
+
+ /* Check to see if there is a range set in the custom headers */
+ if(!Curl_checkheaders(conn, "Range:") && data->state.range) {
+ Curl_safefree(conn->allocptr.rangeline);
+ conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
+ p_range = conn->allocptr.rangeline;
+ }
+ }
+
+ /*
+ * Sanity check the custom headers
+ */
+ if(Curl_checkheaders(conn, "CSeq:")) {
+ failf(data, "CSeq cannot be set as a custom header.");
+ return CURLE_RTSP_CSEQ_ERROR;
+ }
+ if(Curl_checkheaders(conn, "Session:")) {
+ failf(data, "Session ID cannot be set as a custom header.");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ /* Initialize a dynamic send buffer */
+ req_buffer = Curl_add_buffer_init();
+
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ result =
+ Curl_add_bufferf(req_buffer,
+ "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
+ "CSeq: %ld\r\n", /* CSeq */
+ (p_request ? p_request : ""), p_stream_uri,
+ rtsp->CSeq_sent);
+ if(result)
+ return result;
+
+ /*
+ * Rather than do a normal alloc line, keep the session_id unformatted
+ * to make comparison easier
+ */
+ if(p_session_id) {
+ result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id);
+ if(result)
+ return result;
+ }
+
+ /*
+ * Shared HTTP-like options
+ */
+ result = Curl_add_bufferf(req_buffer,
+ "%s" /* transport */
+ "%s" /* accept */
+ "%s" /* accept-encoding */
+ "%s" /* range */
+ "%s" /* referrer */
+ "%s" /* user-agent */
+ ,
+ p_transport ? p_transport : "",
+ p_accept ? p_accept : "",
+ p_accept_encoding ? p_accept_encoding : "",
+ p_range ? p_range : "",
+ p_referrer ? p_referrer : "",
+ p_uagent ? p_uagent : "");
+ if(result)
+ return result;
+
+ if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
+ result = Curl_add_timecondition(data, req_buffer);
+ if(result)
+ return result;
+ }
+
+ result = Curl_add_custom_headers(conn, FALSE, req_buffer);
+ if(result)
+ return result;
+
+ if(rtspreq == RTSPREQ_ANNOUNCE ||
+ rtspreq == RTSPREQ_SET_PARAMETER ||
+ rtspreq == RTSPREQ_GET_PARAMETER) {
+
+ if(data->set.upload) {
+ putsize = data->state.infilesize;
+ data->set.httpreq = HTTPREQ_PUT;
+
+ }
+ else {
+ postsize = (data->set.postfieldsize != -1)?
+ data->set.postfieldsize:
+ (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
+ data->set.httpreq = HTTPREQ_POST;
+ }
+
+ if(putsize > 0 || postsize > 0) {
+ /* As stated in the http comments, it is probably not wise to
+ * actually set a custom Content-Length in the headers */
+ if(!Curl_checkheaders(conn, "Content-Length:")) {
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
+ (data->set.upload ? putsize : postsize));
+ if(result)
+ return result;
+ }
+
+ if(rtspreq == RTSPREQ_SET_PARAMETER ||
+ rtspreq == RTSPREQ_GET_PARAMETER) {
+ if(!Curl_checkheaders(conn, "Content-Type:")) {
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Type: text/parameters\r\n");
+ if(result)
+ return result;
+ }
+ }
+
+ if(rtspreq == RTSPREQ_ANNOUNCE) {
+ if(!Curl_checkheaders(conn, "Content-Type:")) {
+ result = Curl_add_bufferf(req_buffer,
+ "Content-Type: application/sdp\r\n");
+ if(result)
+ return result;
+ }
+ }
+
+ data->state.expect100header = FALSE; /* RTSP posts are simple/small */
+ }
+ else if(rtspreq == RTSPREQ_GET_PARAMETER) {
+ /* Check for an empty GET_PARAMETER (heartbeat) request */
+ data->set.httpreq = HTTPREQ_HEAD;
+ data->set.opt_no_body = TRUE;
+ }
+ }
+
+ /* RTSP never allows chunked transfer */
+ data->req.forbidchunk = TRUE;
+ /* Finish the request buffer */
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ if(result)
+ return result;
+
+ if(postsize > 0) {
+ result = Curl_add_buffer(req_buffer, data->set.postfields,
+ (size_t)postsize);
+ if(result)
+ return result;
+ }
+
+ /* issue the request */
+ result = Curl_add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
+ if(result) {
+ failf(data, "Failed sending RTSP request");
+ return result;
+ }
+
+ Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
+ putsize?FIRSTSOCKET:-1,
+ putsize?&http->writebytecount:NULL);
+
+ /* Increment the CSeq on success */
+ data->state.rtsp_next_client_CSeq++;
+
+ if(http->writebytecount) {
+ /* if a request-body has been sent off, we make sure this progress is
+ noted properly */
+ Curl_pgrsSetUploadCounter(data, http->writebytecount);
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ }
+
+ return result;
+}
+
+
+static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data,
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *readmore) {
+ struct SingleRequest *k = &data->req;
+ struct rtsp_conn *rtspc = &(conn->proto.rtspc);
+
+ char *rtp; /* moving pointer to rtp data */
+ ssize_t rtp_dataleft; /* how much data left to parse in this round */
+ char *scratch;
+ CURLcode result;
+
+ if(rtspc->rtp_buf) {
+ /* There was some leftover data the last time. Merge buffers */
+ char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread);
+ if(!newptr) {
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ rtspc->rtp_buf = newptr;
+ memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread);
+ rtspc->rtp_bufsize += *nread;
+ rtp = rtspc->rtp_buf;
+ rtp_dataleft = rtspc->rtp_bufsize;
+ }
+ else {
+ /* Just parse the request buffer directly */
+ rtp = k->str;
+ rtp_dataleft = *nread;
+ }
+
+ while((rtp_dataleft > 0) &&
+ (rtp[0] == '$')) {
+ if(rtp_dataleft > 4) {
+ int rtp_length;
+
+ /* Parse the header */
+ /* The channel identifier immediately follows and is 1 byte */
+ rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp);
+
+ /* The length is two bytes */
+ rtp_length = RTP_PKT_LENGTH(rtp);
+
+ if(rtp_dataleft < rtp_length + 4) {
+ /* Need more - incomplete payload*/
+ *readmore = TRUE;
+ break;
+ }
+ else {
+ /* We have the full RTP interleaved packet
+ * Write out the header including the leading '$' */
+ DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n",
+ rtspc->rtp_channel, rtp_length));
+ result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
+ if(result) {
+ failf(data, "Got an error writing an RTP packet");
+ *readmore = FALSE;
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+ return result;
+ }
+
+ /* Move forward in the buffer */
+ rtp_dataleft -= rtp_length + 4;
+ rtp += rtp_length + 4;
+
+ if(data->set.rtspreq == RTSPREQ_RECEIVE) {
+ /* If we are in a passive receive, give control back
+ * to the app as often as we can.
+ */
+ k->keepon &= ~KEEP_RECV;
+ }
+ }
+ }
+ else {
+ /* Need more - incomplete header */
+ *readmore = TRUE;
+ break;
+ }
+ }
+
+ if(rtp_dataleft != 0 && rtp[0] == '$') {
+ DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft,
+ *readmore ? "(READMORE)" : ""));
+
+ /* Store the incomplete RTP packet for a "rewind" */
+ scratch = malloc(rtp_dataleft);
+ if(!scratch) {
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(scratch, rtp, rtp_dataleft);
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = scratch;
+ rtspc->rtp_bufsize = rtp_dataleft;
+
+ /* As far as the transfer is concerned, this data is consumed */
+ *nread = 0;
+ return CURLE_OK;
+ }
+ else {
+ /* Fix up k->str to point just after the last RTP packet */
+ k->str += *nread - rtp_dataleft;
+
+ /* either all of the data has been read or...
+ * rtp now points at the next byte to parse
+ */
+ if(rtp_dataleft > 0)
+ DEBUGASSERT(k->str[0] == rtp[0]);
+
+ DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */
+
+ *nread = rtp_dataleft;
+ }
+
+ /* If we get here, we have finished with the leftover/merge buffer */
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+
+ return CURLE_OK;
+}
+
+static
+CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
+{
+ struct SessionHandle *data = conn->data;
+ size_t wrote;
+ curl_write_callback writeit;
+
+ if(len == 0) {
+ failf (data, "Cannot write a 0 size RTP packet.");
+ return CURLE_WRITE_ERROR;
+ }
+
+ writeit = data->set.fwrite_rtp?data->set.fwrite_rtp:data->set.fwrite_func;
+ wrote = writeit(ptr, 1, len, data->set.rtp_out);
+
+ if(CURL_WRITEFUNC_PAUSE == wrote) {
+ failf (data, "Cannot pause RTP");
+ return CURLE_WRITE_ERROR;
+ }
+
+ if(wrote != len) {
+ failf (data, "Failed writing RTP data");
+ return CURLE_WRITE_ERROR;
+ }
+
+ return CURLE_OK;
+}
+
+CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
+ char *header)
+{
+ struct SessionHandle *data = conn->data;
+ long CSeq = 0;
+
+ if(checkprefix("CSeq:", header)) {
+ /* Store the received CSeq. Match is verified in rtsp_done */
+ int nc = sscanf(&header[4], ": %ld", &CSeq);
+ if(nc == 1) {
+ struct RTSP *rtsp = data->req.protop;
+ rtsp->CSeq_recv = CSeq; /* mark the request */
+ data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
+ }
+ else {
+ failf(data, "Unable to read the CSeq header: [%s]", header);
+ return CURLE_RTSP_CSEQ_ERROR;
+ }
+ }
+ else if(checkprefix("Session:", header)) {
+ char *start;
+
+ /* Find the first non-space letter */
+ start = header + 8;
+ while(*start && ISSPACE(*start))
+ start++;
+
+ if(!*start) {
+ failf(data, "Got a blank Session ID");
+ }
+ else if(data->set.str[STRING_RTSP_SESSION_ID]) {
+ /* If the Session ID is set, then compare */
+ if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID],
+ strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) {
+ failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
+ start, data->set.str[STRING_RTSP_SESSION_ID]);
+ return CURLE_RTSP_SESSION_ERROR;
+ }
+ }
+ else {
+ /* If the Session ID is not set, and we find it in a response, then
+ set it */
+
+ /* The session ID can be an alphanumeric or a 'safe' character
+ *
+ * RFC 2326 15.1 Base Syntax:
+ * safe = "\$" | "-" | "_" | "." | "+"
+ * */
+ char *end = start;
+ while(*end &&
+ (ISALNUM(*end) || *end == '-' || *end == '_' || *end == '.' ||
+ *end == '+' ||
+ (*end == '\\' && *(end + 1) && *(end + 1) == '$' && (++end, 1))))
+ end++;
+
+ /* Copy the id substring into a new buffer */
+ data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1);
+ if(data->set.str[STRING_RTSP_SESSION_ID] == NULL)
+ return CURLE_OUT_OF_MEMORY;
+ memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start);
+ (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0';
+ }
+ }
+ return CURLE_OK;
+}
+
+#endif /* CURL_DISABLE_RTSP */
diff --git a/external/libcurl_android/jni/libcurl/lib/rtsp.h b/external/libcurl_android/jni/libcurl/lib/rtsp.h
new file mode 100755
index 00000000..3ffa70cc
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/rtsp.h
@@ -0,0 +1,69 @@
+#ifndef HEADER_CURL_RTSP_H
+#define HEADER_CURL_RTSP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_RTSP
+
+extern const struct Curl_handler Curl_handler_rtsp;
+
+bool Curl_rtsp_connisdead(struct connectdata *check);
+CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header);
+
+#else
+/* disabled */
+#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN
+#define Curl_rtsp_connisdead(x) TRUE
+
+#endif /* CURL_DISABLE_RTSP */
+
+/*
+ * RTSP Connection data
+ *
+ * Currently, only used for tracking incomplete RTP data reads
+ */
+struct rtsp_conn {
+ char *rtp_buf;
+ ssize_t rtp_bufsize;
+ int rtp_channel;
+};
+
+/****************************************************************************
+ * RTSP unique setup
+ ***************************************************************************/
+struct RTSP {
+ /*
+ * http_wrapper MUST be the first element of this structure for the wrap
+ * logic to work. In this way, we get a cheap polymorphism because
+ * &(data->state.proto.rtsp) == &(data->state.proto.http) per the C spec
+ *
+ * HTTP functions can safely treat this as an HTTP struct, but RTSP aware
+ * functions can also index into the later elements.
+ */
+ struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */
+
+ long CSeq_sent; /* CSeq of this request */
+ long CSeq_recv; /* CSeq received */
+};
+
+
+#endif /* HEADER_CURL_RTSP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/security.c b/external/libcurl_android/jni/libcurl/lib/security.c
new file mode 100755
index 00000000..508c7b41
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/security.c
@@ -0,0 +1,601 @@
+/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
+ * use in Curl. His latest changes were done 2000-09-18.
+ *
+ * It has since been patched and modified a lot by Daniel Stenberg
+ * <daniel@haxx.se> to make it better applied to curl conditions, and to make
+ * it not use globals, pollute name space and more. This source code awaits a
+ * rewrite to work around the paragraph 2 in the BSD licenses as explained
+ * below.
+ *
+ * Copyright (c) 1998, 1999, 2013 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ *
+ * Copyright (C) 2001 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_FTP
+#ifdef HAVE_GSSAPI
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "urldata.h"
+#include "curl_base64.h"
+#include "curl_memory.h"
+#include "curl_sec.h"
+#include "ftp.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "warnless.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static const struct {
+ enum protection_level level;
+ const char *name;
+} level_names[] = {
+ { PROT_CLEAR, "clear" },
+ { PROT_SAFE, "safe" },
+ { PROT_CONFIDENTIAL, "confidential" },
+ { PROT_PRIVATE, "private" }
+};
+
+static enum protection_level
+name_to_level(const char *name)
+{
+ int i;
+ for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
+ if(checkprefix(name, level_names[i].name))
+ return level_names[i].level;
+ return PROT_NONE;
+}
+
+/* Convert a protocol |level| to its char representation.
+ We take an int to catch programming mistakes. */
+static char level_to_char(int level) {
+ switch(level) {
+ case PROT_CLEAR:
+ return 'C';
+ case PROT_SAFE:
+ return 'S';
+ case PROT_CONFIDENTIAL:
+ return 'E';
+ case PROT_PRIVATE:
+ return 'P';
+ case PROT_CMD:
+ /* Fall through */
+ default:
+ /* Those 2 cases should not be reached! */
+ break;
+ }
+ DEBUGASSERT(0);
+ /* Default to the most secure alternative. */
+ return 'P';
+}
+
+static const struct Curl_sec_client_mech * const mechs[] = {
+#ifdef HAVE_GSSAPI
+ &Curl_krb5_client_mech,
+#endif
+ NULL
+};
+
+/* Send an FTP command defined by |message| and the optional arguments. The
+ function returns the ftp_code. If an error occurs, -1 is returned. */
+static int ftp_send_command(struct connectdata *conn, const char *message, ...)
+{
+ int ftp_code;
+ ssize_t nread;
+ va_list args;
+ char print_buffer[50];
+
+ va_start(args, message);
+ vsnprintf(print_buffer, sizeof(print_buffer), message, args);
+ va_end(args);
+
+ if(Curl_ftpsendf(conn, print_buffer) != CURLE_OK) {
+ ftp_code = -1;
+ }
+ else {
+ if(Curl_GetFTPResponse(&nread, conn, &ftp_code) != CURLE_OK)
+ ftp_code = -1;
+ }
+
+ (void)nread; /* Unused */
+ return ftp_code;
+}
+
+/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode
+ saying whether an error occurred or CURLE_OK if |len| was read. */
+static CURLcode
+socket_read(curl_socket_t fd, void *to, size_t len)
+{
+ char *to_p = to;
+ CURLcode code;
+ ssize_t nread;
+
+ while(len > 0) {
+ code = Curl_read_plain(fd, to_p, len, &nread);
+ if(code == CURLE_OK) {
+ len -= nread;
+ to_p += nread;
+ }
+ else {
+ /* FIXME: We are doing a busy wait */
+ if(code == CURLE_AGAIN)
+ continue;
+ return code;
+ }
+ }
+ return CURLE_OK;
+}
+
+
+/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a
+ CURLcode saying whether an error occurred or CURLE_OK if |len| was
+ written. */
+static CURLcode
+socket_write(struct connectdata *conn, curl_socket_t fd, const void *to,
+ size_t len)
+{
+ const char *to_p = to;
+ CURLcode code;
+ ssize_t written;
+
+ while(len > 0) {
+ code = Curl_write_plain(conn, fd, to_p, len, &written);
+ if(code == CURLE_OK) {
+ len -= written;
+ to_p += written;
+ }
+ else {
+ /* FIXME: We are doing a busy wait */
+ if(code == CURLE_AGAIN)
+ continue;
+ return code;
+ }
+ }
+ return CURLE_OK;
+}
+
+static CURLcode read_data(struct connectdata *conn,
+ curl_socket_t fd,
+ struct krb5buffer *buf)
+{
+ int len;
+ void* tmp;
+ CURLcode ret;
+
+ ret = socket_read(fd, &len, sizeof(len));
+ if(ret != CURLE_OK)
+ return ret;
+
+ len = ntohl(len);
+ tmp = realloc(buf->data, len);
+ if(tmp == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ buf->data = tmp;
+ ret = socket_read(fd, buf->data, len);
+ if(ret != CURLE_OK)
+ return ret;
+ buf->size = conn->mech->decode(conn->app_data, buf->data, len,
+ conn->data_prot, conn);
+ buf->index = 0;
+ return CURLE_OK;
+}
+
+static size_t
+buffer_read(struct krb5buffer *buf, void *data, size_t len)
+{
+ if(buf->size - buf->index < len)
+ len = buf->size - buf->index;
+ memcpy(data, (char*)buf->data + buf->index, len);
+ buf->index += len;
+ return len;
+}
+
+/* Matches Curl_recv signature */
+static ssize_t sec_recv(struct connectdata *conn, int sockindex,
+ char *buffer, size_t len, CURLcode *err)
+{
+ size_t bytes_read;
+ size_t total_read = 0;
+ curl_socket_t fd = conn->sock[sockindex];
+
+ *err = CURLE_OK;
+
+ /* Handle clear text response. */
+ if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
+ return read(fd, buffer, len);
+
+ if(conn->in_buffer.eof_flag) {
+ conn->in_buffer.eof_flag = 0;
+ return 0;
+ }
+
+ bytes_read = buffer_read(&conn->in_buffer, buffer, len);
+ len -= bytes_read;
+ total_read += bytes_read;
+ buffer += bytes_read;
+
+ while(len > 0) {
+ if(read_data(conn, fd, &conn->in_buffer) != CURLE_OK)
+ return -1;
+ if(conn->in_buffer.size == 0) {
+ if(bytes_read > 0)
+ conn->in_buffer.eof_flag = 1;
+ return bytes_read;
+ }
+ bytes_read = buffer_read(&conn->in_buffer, buffer, len);
+ len -= bytes_read;
+ total_read += bytes_read;
+ buffer += bytes_read;
+ }
+ /* FIXME: Check for overflow */
+ return total_read;
+}
+
+/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
+ and negociating with the server. |from| can be NULL. */
+/* FIXME: We don't check for errors nor report any! */
+static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
+ const char *from, int length)
+{
+ int bytes, htonl_bytes; /* 32-bit integers for htonl */
+ char *buffer = NULL;
+ char *cmd_buffer;
+ size_t cmd_size = 0;
+ CURLcode error;
+ enum protection_level prot_level = conn->data_prot;
+ bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE;
+
+ DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
+
+ if(iscmd) {
+ if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5))
+ prot_level = PROT_PRIVATE;
+ else
+ prot_level = conn->command_prot;
+ }
+ bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
+ (void**)&buffer, conn);
+ if(!buffer || bytes <= 0)
+ return; /* error */
+
+ if(iscmd) {
+ error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes),
+ &cmd_buffer, &cmd_size);
+ if(error) {
+ free(buffer);
+ return; /* error */
+ }
+ if(cmd_size > 0) {
+ static const char *enc = "ENC ";
+ static const char *mic = "MIC ";
+ if(prot_level == PROT_PRIVATE)
+ socket_write(conn, fd, enc, 4);
+ else
+ socket_write(conn, fd, mic, 4);
+
+ socket_write(conn, fd, cmd_buffer, cmd_size);
+ socket_write(conn, fd, "\r\n", 2);
+ infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
+ cmd_buffer);
+ free(cmd_buffer);
+ }
+ }
+ else {
+ htonl_bytes = htonl(bytes);
+ socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes));
+ socket_write(conn, fd, buffer, curlx_sitouz(bytes));
+ }
+ free(buffer);
+}
+
+static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd,
+ const char *buffer, size_t length)
+{
+ /* FIXME: Check for overflow */
+ ssize_t tx = 0, len = conn->buffer_size;
+
+ len -= conn->mech->overhead(conn->app_data, conn->data_prot,
+ curlx_sztosi(len));
+ if(len <= 0)
+ len = length;
+ while(length) {
+ if(len >= 0 || length < (size_t)len) {
+ /* FIXME: Check for overflow. */
+ len = length;
+ }
+ do_sec_send(conn, fd, buffer, curlx_sztosi(len));
+ length -= len;
+ buffer += len;
+ tx += len;
+ }
+ return tx;
+}
+
+/* Matches Curl_send signature */
+static ssize_t sec_send(struct connectdata *conn, int sockindex,
+ const void *buffer, size_t len, CURLcode *err)
+{
+ curl_socket_t fd = conn->sock[sockindex];
+ *err = CURLE_OK;
+ return sec_write(conn, fd, buffer, len);
+}
+
+int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
+ enum protection_level level)
+{
+ /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an
+ int */
+ int decoded_len;
+ char *buf;
+ int ret_code;
+ size_t decoded_sz = 0;
+ CURLcode error;
+
+ DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
+
+ error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
+ if(error || decoded_sz == 0)
+ return -1;
+
+ if(decoded_sz > (size_t)INT_MAX) {
+ free(buf);
+ return -1;
+ }
+ decoded_len = curlx_uztosi(decoded_sz);
+
+ decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len,
+ level, conn);
+ if(decoded_len <= 0) {
+ free(buf);
+ return -1;
+ }
+
+ if(conn->data->set.verbose) {
+ buf[decoded_len] = '\n';
+ Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1, conn);
+ }
+
+ buf[decoded_len] = '\0';
+ DEBUGASSERT(decoded_len > 3);
+ if(buf[3] == '-')
+ ret_code = 0;
+ else {
+ /* Check for error? */
+ sscanf(buf, "%d", &ret_code);
+ }
+
+ if(buf[decoded_len - 1] == '\n')
+ buf[decoded_len - 1] = '\0';
+ /* FIXME: Is |buffer| length always greater than |decoded_len|? */
+ strcpy(buffer, buf);
+ free(buf);
+ return ret_code;
+}
+
+/* FIXME: The error code returned here is never checked. */
+static int sec_set_protection_level(struct connectdata *conn)
+{
+ int code;
+ char* pbsz;
+ static unsigned int buffer_size = 1 << 20; /* 1048576 */
+ enum protection_level level = conn->request_data_prot;
+
+ DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
+
+ if(!conn->sec_complete) {
+ infof(conn->data, "Trying to change the protection level after the"
+ "completion of the data exchange.\n");
+ return -1;
+ }
+
+ /* Bail out if we try to set up the same level */
+ if(conn->data_prot == level)
+ return 0;
+
+ if(level) {
+ code = ftp_send_command(conn, "PBSZ %u", buffer_size);
+ if(code < 0)
+ return -1;
+
+ if(code/100 != 2) {
+ failf(conn->data, "Failed to set the protection's buffer size.");
+ return -1;
+ }
+ conn->buffer_size = buffer_size;
+
+ pbsz = strstr(conn->data->state.buffer, "PBSZ=");
+ if(pbsz) {
+ /* FIXME: Checks for errors in sscanf? */
+ sscanf(pbsz, "PBSZ=%u", &buffer_size);
+ if(buffer_size < conn->buffer_size)
+ conn->buffer_size = buffer_size;
+ }
+ }
+
+ /* Now try to negiociate the protection level. */
+ code = ftp_send_command(conn, "PROT %c", level_to_char(level));
+
+ if(code < 0)
+ return -1;
+
+ if(code/100 != 2) {
+ failf(conn->data, "Failed to set the protection level.");
+ return -1;
+ }
+
+ conn->data_prot = level;
+ if(level == PROT_PRIVATE)
+ conn->command_prot = level;
+
+ return 0;
+}
+
+int
+Curl_sec_request_prot(struct connectdata *conn, const char *level)
+{
+ enum protection_level l = name_to_level(level);
+ if(l == PROT_NONE)
+ return -1;
+ DEBUGASSERT(l > PROT_NONE && l < PROT_LAST);
+ conn->request_data_prot = l;
+ return 0;
+}
+
+static CURLcode choose_mech(struct connectdata *conn)
+{
+ int ret;
+ struct SessionHandle *data = conn->data;
+ const struct Curl_sec_client_mech * const *mech;
+ void *tmp_allocation;
+ const char *mech_name;
+
+ for(mech = mechs; (*mech); ++mech) {
+ mech_name = (*mech)->name;
+ /* We have no mechanism with a NULL name but keep this check */
+ DEBUGASSERT(mech_name != NULL);
+ if(mech_name == NULL) {
+ infof(data, "Skipping mechanism with empty name (%p)\n", (void *)mech);
+ continue;
+ }
+ tmp_allocation = realloc(conn->app_data, (*mech)->size);
+ if(tmp_allocation == NULL) {
+ failf(data, "Failed realloc of size %u", (*mech)->size);
+ mech = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ conn->app_data = tmp_allocation;
+
+ if((*mech)->init) {
+ ret = (*mech)->init(conn->app_data);
+ if(ret != 0) {
+ infof(data, "Failed initialization for %s. Skipping it.\n", mech_name);
+ continue;
+ }
+ }
+
+ infof(data, "Trying mechanism %s...\n", mech_name);
+ ret = ftp_send_command(conn, "AUTH %s", mech_name);
+ if(ret < 0)
+ /* FIXME: This error is too generic but it is OK for now. */
+ return CURLE_COULDNT_CONNECT;
+
+ if(ret/100 != 3) {
+ switch(ret) {
+ case 504:
+ infof(data, "Mechanism %s is not supported by the server (server "
+ "returned ftp code: 504).\n", mech_name);
+ break;
+ case 534:
+ infof(data, "Mechanism %s was rejected by the server (server returned "
+ "ftp code: 534).\n", mech_name);
+ break;
+ default:
+ if(ret/100 == 5) {
+ infof(data, "server does not support the security extensions\n");
+ return CURLE_USE_SSL_FAILED;
+ }
+ break;
+ }
+ continue;
+ }
+
+ /* Authenticate */
+ ret = (*mech)->auth(conn->app_data, conn);
+
+ if(ret == AUTH_CONTINUE)
+ continue;
+ else if(ret != AUTH_OK) {
+ /* Mechanism has dumped the error to stderr, don't error here. */
+ return -1;
+ }
+ DEBUGASSERT(ret == AUTH_OK);
+
+ conn->mech = *mech;
+ conn->sec_complete = 1;
+ conn->recv[FIRSTSOCKET] = sec_recv;
+ conn->send[FIRSTSOCKET] = sec_send;
+ conn->recv[SECONDARYSOCKET] = sec_recv;
+ conn->send[SECONDARYSOCKET] = sec_send;
+ conn->command_prot = PROT_SAFE;
+ /* Set the requested protection level */
+ /* BLOCKING */
+ (void)sec_set_protection_level(conn);
+ break;
+ }
+
+ return mech != NULL ? CURLE_OK : CURLE_FAILED_INIT;
+}
+
+CURLcode
+Curl_sec_login(struct connectdata *conn)
+{
+ return choose_mech(conn);
+}
+
+
+void
+Curl_sec_end(struct connectdata *conn)
+{
+ if(conn->mech != NULL && conn->mech->end)
+ conn->mech->end(conn->app_data);
+ if(conn->app_data) {
+ free(conn->app_data);
+ conn->app_data = NULL;
+ }
+ if(conn->in_buffer.data) {
+ free(conn->in_buffer.data);
+ conn->in_buffer.data = NULL;
+ conn->in_buffer.size = 0;
+ conn->in_buffer.index = 0;
+ /* FIXME: Is this really needed? */
+ conn->in_buffer.eof_flag = 0;
+ }
+ conn->sec_complete = 0;
+ conn->data_prot = PROT_CLEAR;
+ conn->mech = NULL;
+}
+
+#endif /* HAVE_GSSAPI */
+
+#endif /* CURL_DISABLE_FTP */
diff --git a/external/libcurl_android/jni/libcurl/lib/select.c b/external/libcurl_android/jni/libcurl/lib/select.c
new file mode 100755
index 00000000..bb9b8b0d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/select.c
@@ -0,0 +1,574 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
+#error "We can't compile without select() or poll() support."
+#endif
+
+#if defined(__BEOS__) && !defined(__HAIKU__)
+/* BeOS has FD_SET defined in socket.h */
+#include <socket.h>
+#endif
+
+#ifdef MSDOS
+#include <dos.h> /* delay() */
+#endif
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "connect.h"
+#include "select.h"
+#include "warnless.h"
+
+/* Convenience local macros */
+
+#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
+
+int Curl_ack_eintr = 0;
+#define error_not_EINTR (Curl_ack_eintr || error != EINTR)
+
+/*
+ * Internal function used for waiting a specific amount of ms
+ * in Curl_socket_ready() and Curl_poll() when no file descriptor
+ * is provided to wait on, just being used to delay execution.
+ * WinSock select() and poll() timeout mechanisms need a valid
+ * socket descriptor in a not null file descriptor set to work.
+ * Waiting indefinitely with this function is not allowed, a
+ * zero or negative timeout value will return immediately.
+ * Timeout resolution, accuracy, as well as maximum supported
+ * value is system dependent, neither factor is a citical issue
+ * for the intended use of this function in the library.
+ *
+ * Return values:
+ * -1 = system call error, invalid timeout value, or interrupted
+ * 0 = specified timeout has elapsed
+ */
+int Curl_wait_ms(int timeout_ms)
+{
+#if !defined(MSDOS) && !defined(USE_WINSOCK)
+#ifndef HAVE_POLL_FINE
+ struct timeval pending_tv;
+#endif
+ struct timeval initial_tv;
+ int pending_ms;
+ int error;
+#endif
+ int r = 0;
+
+ if(!timeout_ms)
+ return 0;
+ if(timeout_ms < 0) {
+ SET_SOCKERRNO(EINVAL);
+ return -1;
+ }
+#if defined(MSDOS)
+ delay(timeout_ms);
+#elif defined(USE_WINSOCK)
+ Sleep(timeout_ms);
+#else
+ pending_ms = timeout_ms;
+ initial_tv = curlx_tvnow();
+ do {
+#if defined(HAVE_POLL_FINE)
+ r = poll(NULL, 0, pending_ms);
+#else
+ pending_tv.tv_sec = pending_ms / 1000;
+ pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+ r = select(0, NULL, NULL, NULL, &pending_tv);
+#endif /* HAVE_POLL_FINE */
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ pending_ms = timeout_ms - elapsed_ms;
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ } while(r == -1);
+#endif /* USE_WINSOCK */
+ if(r)
+ r = -1;
+ return r;
+}
+
+/*
+ * Wait for read or write events on a set of file descriptors. It uses poll()
+ * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
+ * otherwise select() is used. An error is returned if select() is being used
+ * and a file descriptor is too large for FD_SETSIZE.
+ *
+ * A negative timeout value makes this function wait indefinitely,
+ * unles no valid file descriptor is given, when this happens the
+ * negative timeout is ignored and the function times out immediately.
+ *
+ * Return values:
+ * -1 = system call error or fd >= FD_SETSIZE
+ * 0 = timeout
+ * [bitmask] = action as described below
+ *
+ * CURL_CSELECT_IN - first socket is readable
+ * CURL_CSELECT_IN2 - second socket is readable
+ * CURL_CSELECT_OUT - write socket is writable
+ * CURL_CSELECT_ERR - an error condition occurred
+ */
+int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
+ curl_socket_t readfd1,
+ curl_socket_t writefd, /* socket to write to */
+ long timeout_ms) /* milliseconds to wait */
+{
+#ifdef HAVE_POLL_FINE
+ struct pollfd pfd[3];
+ int num;
+#else
+ struct timeval pending_tv;
+ struct timeval *ptimeout;
+ fd_set fds_read;
+ fd_set fds_write;
+ fd_set fds_err;
+ curl_socket_t maxfd;
+#endif
+ struct timeval initial_tv = {0,0};
+ int pending_ms = 0;
+ int error;
+ int r;
+ int ret;
+
+ if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
+ (writefd == CURL_SOCKET_BAD)) {
+ /* no sockets, just wait */
+ r = Curl_wait_ms((int)timeout_ms);
+ return r;
+ }
+
+ /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
+ time in this function does not need to be measured. This happens
+ when function is called with a zero timeout or a negative timeout
+ value indicating a blocking call should be performed. */
+
+ if(timeout_ms > 0) {
+ pending_ms = (int)timeout_ms;
+ initial_tv = curlx_tvnow();
+ }
+
+#ifdef HAVE_POLL_FINE
+
+ num = 0;
+ if(readfd0 != CURL_SOCKET_BAD) {
+ pfd[num].fd = readfd0;
+ pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
+ pfd[num].revents = 0;
+ num++;
+ }
+ if(readfd1 != CURL_SOCKET_BAD) {
+ pfd[num].fd = readfd1;
+ pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
+ pfd[num].revents = 0;
+ num++;
+ }
+ if(writefd != CURL_SOCKET_BAD) {
+ pfd[num].fd = writefd;
+ pfd[num].events = POLLWRNORM|POLLOUT;
+ pfd[num].revents = 0;
+ num++;
+ }
+
+ do {
+ if(timeout_ms < 0)
+ pending_ms = -1;
+ else if(!timeout_ms)
+ pending_ms = 0;
+ r = poll(pfd, num, pending_ms);
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ if(timeout_ms > 0) {
+ pending_ms = (int)(timeout_ms - elapsed_ms);
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ }
+ } while(r == -1);
+
+ if(r < 0)
+ return -1;
+ if(r == 0)
+ return 0;
+
+ ret = 0;
+ num = 0;
+ if(readfd0 != CURL_SOCKET_BAD) {
+ if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
+ ret |= CURL_CSELECT_IN;
+ if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
+ ret |= CURL_CSELECT_ERR;
+ num++;
+ }
+ if(readfd1 != CURL_SOCKET_BAD) {
+ if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
+ ret |= CURL_CSELECT_IN2;
+ if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
+ ret |= CURL_CSELECT_ERR;
+ num++;
+ }
+ if(writefd != CURL_SOCKET_BAD) {
+ if(pfd[num].revents & (POLLWRNORM|POLLOUT))
+ ret |= CURL_CSELECT_OUT;
+ if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
+ ret |= CURL_CSELECT_ERR;
+ }
+
+ return ret;
+
+#else /* HAVE_POLL_FINE */
+
+ FD_ZERO(&fds_err);
+ maxfd = (curl_socket_t)-1;
+
+ FD_ZERO(&fds_read);
+ if(readfd0 != CURL_SOCKET_BAD) {
+ VERIFY_SOCK(readfd0);
+ FD_SET(readfd0, &fds_read);
+ FD_SET(readfd0, &fds_err);
+ maxfd = readfd0;
+ }
+ if(readfd1 != CURL_SOCKET_BAD) {
+ VERIFY_SOCK(readfd1);
+ FD_SET(readfd1, &fds_read);
+ FD_SET(readfd1, &fds_err);
+ if(readfd1 > maxfd)
+ maxfd = readfd1;
+ }
+
+ FD_ZERO(&fds_write);
+ if(writefd != CURL_SOCKET_BAD) {
+ VERIFY_SOCK(writefd);
+ FD_SET(writefd, &fds_write);
+ FD_SET(writefd, &fds_err);
+ if(writefd > maxfd)
+ maxfd = writefd;
+ }
+
+ ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
+
+ do {
+ if(timeout_ms > 0) {
+ pending_tv.tv_sec = pending_ms / 1000;
+ pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+ }
+ else if(!timeout_ms) {
+ pending_tv.tv_sec = 0;
+ pending_tv.tv_usec = 0;
+ }
+
+ /* WinSock select() must not be called with an fd_set that contains zero
+ fd flags, or it will return WSAEINVAL. But, it also can't be called
+ with no fd_sets at all! From the documentation:
+
+ Any two of the parameters, readfds, writefds, or exceptfds, can be
+ given as null. At least one must be non-null, and any non-null
+ descriptor set must contain at least one handle to a socket.
+
+ We know that we have at least one bit set in at least two fd_sets in
+ this case, but we may have no bits set in either fds_read or fd_write,
+ so check for that and handle it. Luckily, with WinSock, we can _also_
+ ask how many bits are set on an fd_set.
+
+ It is unclear why WinSock doesn't just handle this for us instead of
+ calling this an error.
+
+ Note also that WinSock ignores the first argument, so we don't worry
+ about the fact that maxfd is computed incorrectly with WinSock (since
+ curl_socket_t is unsigned in such cases and thus -1 is the largest
+ value).
+ */
+ r = select((int)maxfd + 1,
+#ifndef USE_WINSOCK
+ &fds_read,
+ &fds_write,
+#else
+ fds_read.fd_count ? &fds_read : NULL,
+ fds_write.fd_count ? &fds_write : NULL,
+#endif
+ &fds_err, ptimeout);
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ if(timeout_ms > 0) {
+ pending_ms = timeout_ms - elapsed_ms;
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ }
+ } while(r == -1);
+
+ if(r < 0)
+ return -1;
+ if(r == 0)
+ return 0;
+
+ ret = 0;
+ if(readfd0 != CURL_SOCKET_BAD) {
+ if(FD_ISSET(readfd0, &fds_read))
+ ret |= CURL_CSELECT_IN;
+ if(FD_ISSET(readfd0, &fds_err))
+ ret |= CURL_CSELECT_ERR;
+ }
+ if(readfd1 != CURL_SOCKET_BAD) {
+ if(FD_ISSET(readfd1, &fds_read))
+ ret |= CURL_CSELECT_IN2;
+ if(FD_ISSET(readfd1, &fds_err))
+ ret |= CURL_CSELECT_ERR;
+ }
+ if(writefd != CURL_SOCKET_BAD) {
+ if(FD_ISSET(writefd, &fds_write))
+ ret |= CURL_CSELECT_OUT;
+ if(FD_ISSET(writefd, &fds_err))
+ ret |= CURL_CSELECT_ERR;
+ }
+
+ return ret;
+
+#endif /* HAVE_POLL_FINE */
+
+}
+
+/*
+ * This is a wrapper around poll(). If poll() does not exist, then
+ * select() is used instead. An error is returned if select() is
+ * being used and a file descriptor is too large for FD_SETSIZE.
+ * A negative timeout value makes this function wait indefinitely,
+ * unles no valid file descriptor is given, when this happens the
+ * negative timeout is ignored and the function times out immediately.
+ *
+ * Return values:
+ * -1 = system call error or fd >= FD_SETSIZE
+ * 0 = timeout
+ * N = number of structures with non zero revent fields
+ */
+int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
+{
+#ifndef HAVE_POLL_FINE
+ struct timeval pending_tv;
+ struct timeval *ptimeout;
+ fd_set fds_read;
+ fd_set fds_write;
+ fd_set fds_err;
+ curl_socket_t maxfd;
+#endif
+ struct timeval initial_tv = {0,0};
+ bool fds_none = TRUE;
+ unsigned int i;
+ int pending_ms = 0;
+ int error;
+ int r;
+
+ if(ufds) {
+ for(i = 0; i < nfds; i++) {
+ if(ufds[i].fd != CURL_SOCKET_BAD) {
+ fds_none = FALSE;
+ break;
+ }
+ }
+ }
+ if(fds_none) {
+ r = Curl_wait_ms(timeout_ms);
+ return r;
+ }
+
+ /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
+ time in this function does not need to be measured. This happens
+ when function is called with a zero timeout or a negative timeout
+ value indicating a blocking call should be performed. */
+
+ if(timeout_ms > 0) {
+ pending_ms = timeout_ms;
+ initial_tv = curlx_tvnow();
+ }
+
+#ifdef HAVE_POLL_FINE
+
+ do {
+ if(timeout_ms < 0)
+ pending_ms = -1;
+ else if(!timeout_ms)
+ pending_ms = 0;
+ r = poll(ufds, nfds, pending_ms);
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ if(timeout_ms > 0) {
+ pending_ms = timeout_ms - elapsed_ms;
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ }
+ } while(r == -1);
+
+ if(r < 0)
+ return -1;
+ if(r == 0)
+ return 0;
+
+ for(i = 0; i < nfds; i++) {
+ if(ufds[i].fd == CURL_SOCKET_BAD)
+ continue;
+ if(ufds[i].revents & POLLHUP)
+ ufds[i].revents |= POLLIN;
+ if(ufds[i].revents & POLLERR)
+ ufds[i].revents |= (POLLIN|POLLOUT);
+ }
+
+#else /* HAVE_POLL_FINE */
+
+ FD_ZERO(&fds_read);
+ FD_ZERO(&fds_write);
+ FD_ZERO(&fds_err);
+ maxfd = (curl_socket_t)-1;
+
+ for(i = 0; i < nfds; i++) {
+ ufds[i].revents = 0;
+ if(ufds[i].fd == CURL_SOCKET_BAD)
+ continue;
+ VERIFY_SOCK(ufds[i].fd);
+ if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
+ POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
+ if(ufds[i].fd > maxfd)
+ maxfd = ufds[i].fd;
+ if(ufds[i].events & (POLLRDNORM|POLLIN))
+ FD_SET(ufds[i].fd, &fds_read);
+ if(ufds[i].events & (POLLWRNORM|POLLOUT))
+ FD_SET(ufds[i].fd, &fds_write);
+ if(ufds[i].events & (POLLRDBAND|POLLPRI))
+ FD_SET(ufds[i].fd, &fds_err);
+ }
+ }
+
+#ifdef USE_WINSOCK
+ /* WinSock select() can't handle zero events. See the comment about this in
+ Curl_check_socket(). */
+ if(fds_read.fd_count == 0 && fds_write.fd_count == 0
+ && fds_err.fd_count == 0) {
+ r = Curl_wait_ms(timeout_ms);
+ return r;
+ }
+#endif
+
+ ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
+
+ do {
+ if(timeout_ms > 0) {
+ pending_tv.tv_sec = pending_ms / 1000;
+ pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+ }
+ else if(!timeout_ms) {
+ pending_tv.tv_sec = 0;
+ pending_tv.tv_usec = 0;
+ }
+ r = select((int)maxfd + 1,
+#ifndef USE_WINSOCK
+ &fds_read, &fds_write, &fds_err,
+#else
+ /* WinSock select() can't handle fd_sets with zero bits set, so
+ don't give it such arguments. See the comment about this in
+ Curl_check_socket().
+ */
+ fds_read.fd_count ? &fds_read : NULL,
+ fds_write.fd_count ? &fds_write : NULL,
+ fds_err.fd_count ? &fds_err : NULL,
+#endif
+ ptimeout);
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error && error_not_EINTR)
+ break;
+ if(timeout_ms > 0) {
+ pending_ms = timeout_ms - elapsed_ms;
+ if(pending_ms <= 0) {
+ r = 0; /* Simulate a "call timed out" case */
+ break;
+ }
+ }
+ } while(r == -1);
+
+ if(r < 0)
+ return -1;
+ if(r == 0)
+ return 0;
+
+ r = 0;
+ for(i = 0; i < nfds; i++) {
+ ufds[i].revents = 0;
+ if(ufds[i].fd == CURL_SOCKET_BAD)
+ continue;
+ if(FD_ISSET(ufds[i].fd, &fds_read))
+ ufds[i].revents |= POLLIN;
+ if(FD_ISSET(ufds[i].fd, &fds_write))
+ ufds[i].revents |= POLLOUT;
+ if(FD_ISSET(ufds[i].fd, &fds_err))
+ ufds[i].revents |= POLLPRI;
+ if(ufds[i].revents != 0)
+ r++;
+ }
+
+#endif /* HAVE_POLL_FINE */
+
+ return r;
+}
+
+#ifdef TPF
+/*
+ * This is a replacement for select() on the TPF platform.
+ * It is used whenever libcurl calls select().
+ * The call below to tpf_process_signals() is required because
+ * TPF's select calls are not signal interruptible.
+ *
+ * Return values are the same as select's.
+ */
+int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
+ fd_set* excepts, struct timeval* tv)
+{
+ int rc;
+
+ rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
+ tpf_process_signals();
+ return(rc);
+}
+#endif /* TPF */
diff --git a/external/libcurl_android/jni/libcurl/lib/select.h b/external/libcurl_android/jni/libcurl/lib/select.h
new file mode 100755
index 00000000..c00afe16
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/select.h
@@ -0,0 +1,114 @@
+#ifndef HEADER_CURL_SELECT_H
+#define HEADER_CURL_SELECT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#elif defined(HAVE_POLL_H)
+#include <poll.h>
+#endif
+
+/*
+ * Definition of pollfd struct and constants for platforms lacking them.
+ */
+
+#if !defined(HAVE_STRUCT_POLLFD) && \
+ !defined(HAVE_SYS_POLL_H) && \
+ !defined(HAVE_POLL_H)
+
+#define POLLIN 0x01
+#define POLLPRI 0x02
+#define POLLOUT 0x04
+#define POLLERR 0x08
+#define POLLHUP 0x10
+#define POLLNVAL 0x20
+
+struct pollfd
+{
+ curl_socket_t fd;
+ short events;
+ short revents;
+};
+
+#endif
+
+#ifndef POLLRDNORM
+#define POLLRDNORM POLLIN
+#endif
+
+#ifndef POLLWRNORM
+#define POLLWRNORM POLLOUT
+#endif
+
+#ifndef POLLRDBAND
+#define POLLRDBAND POLLPRI
+#endif
+
+/* there are three CSELECT defines that are defined in the public header that
+ are exposed to users, but this *IN2 bit is only ever used internally and
+ therefore defined here */
+#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1)
+
+int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
+ curl_socket_t writefd,
+ long timeout_ms);
+
+/* provide the former API internally */
+#define Curl_socket_ready(x,y,z) \
+ Curl_socket_check(x, CURL_SOCKET_BAD, y, z)
+
+int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
+
+/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set,
+ * EINTR condition is honored and function might exit early without
+ * awaiting full timeout. Otherwise EINTR will be ignored and full
+ * timeout will elapse. */
+extern int Curl_ack_eintr;
+
+int Curl_wait_ms(int timeout_ms);
+
+#ifdef TPF
+int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
+ fd_set* excepts, struct timeval* tv);
+#endif
+
+/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which
+ unfortunately makes it impossible for us to easily check if they're valid
+*/
+#if defined(USE_WINSOCK) || defined(TPF)
+#define VALID_SOCK(x) 1
+#define VERIFY_SOCK(x) Curl_nop_stmt
+#else
+#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
+#define VERIFY_SOCK(x) do { \
+ if(!VALID_SOCK(x)) { \
+ SET_SOCKERRNO(EINVAL); \
+ return -1; \
+ } \
+} WHILE_FALSE
+#endif
+
+#endif /* HEADER_CURL_SELECT_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/sendf.c b/external/libcurl_android/jni/libcurl/lib/sendf.c
new file mode 100755
index 00000000..4a87c79d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/sendf.c
@@ -0,0 +1,686 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "connect.h"
+#include "vtls/vtls.h"
+#include "ssh.h"
+#include "multiif.h"
+#include "non-ascii.h"
+
+#define _MPRINTF_REPLACE /* use the internal *printf() functions */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+#include "strerror.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef CURL_DO_LINEEND_CONV
+/*
+ * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
+ * (\n), with special processing for CRLF sequences that are split between two
+ * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
+ * size of the data is returned.
+ */
+static size_t convert_lineends(struct SessionHandle *data,
+ char *startPtr, size_t size)
+{
+ char *inPtr, *outPtr;
+
+ /* sanity check */
+ if((startPtr == NULL) || (size < 1)) {
+ return(size);
+ }
+
+ if(data->state.prev_block_had_trailing_cr) {
+ /* The previous block of incoming data
+ had a trailing CR, which was turned into a LF. */
+ if(*startPtr == '\n') {
+ /* This block of incoming data starts with the
+ previous block's LF so get rid of it */
+ memmove(startPtr, startPtr+1, size-1);
+ size--;
+ /* and it wasn't a bare CR but a CRLF conversion instead */
+ data->state.crlf_conversions++;
+ }
+ data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
+ }
+
+ /* find 1st CR, if any */
+ inPtr = outPtr = memchr(startPtr, '\r', size);
+ if(inPtr) {
+ /* at least one CR, now look for CRLF */
+ while(inPtr < (startPtr+size-1)) {
+ /* note that it's size-1, so we'll never look past the last byte */
+ if(memcmp(inPtr, "\r\n", 2) == 0) {
+ /* CRLF found, bump past the CR and copy the NL */
+ inPtr++;
+ *outPtr = *inPtr;
+ /* keep track of how many CRLFs we converted */
+ data->state.crlf_conversions++;
+ }
+ else {
+ if(*inPtr == '\r') {
+ /* lone CR, move LF instead */
+ *outPtr = '\n';
+ }
+ else {
+ /* not a CRLF nor a CR, just copy whatever it is */
+ *outPtr = *inPtr;
+ }
+ }
+ outPtr++;
+ inPtr++;
+ } /* end of while loop */
+
+ if(inPtr < startPtr+size) {
+ /* handle last byte */
+ if(*inPtr == '\r') {
+ /* deal with a CR at the end of the buffer */
+ *outPtr = '\n'; /* copy a NL instead */
+ /* note that a CRLF might be split across two blocks */
+ data->state.prev_block_had_trailing_cr = TRUE;
+ }
+ else {
+ /* copy last byte */
+ *outPtr = *inPtr;
+ }
+ outPtr++;
+ }
+ if(outPtr < startPtr+size)
+ /* tidy up by null terminating the now shorter data */
+ *outPtr = '\0';
+
+ return(outPtr - startPtr);
+ }
+ return(size);
+}
+#endif /* CURL_DO_LINEEND_CONV */
+
+/* Curl_infof() is for info message along the way */
+
+void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
+{
+ if(data && data->set.verbose) {
+ va_list ap;
+ size_t len;
+ char print_buffer[2048 + 1];
+ va_start(ap, fmt);
+ vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
+ va_end(ap);
+ len = strlen(print_buffer);
+ Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
+ }
+}
+
+/* Curl_failf() is for messages stating why we failed.
+ * The message SHALL NOT include any LF or CR.
+ */
+
+void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
+{
+ va_list ap;
+ size_t len;
+ va_start(ap, fmt);
+
+ vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
+
+ if(data->set.errorbuffer && !data->state.errorbuf) {
+ snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
+ data->state.errorbuf = TRUE; /* wrote error string */
+ }
+ if(data->set.verbose) {
+ len = strlen(data->state.buffer);
+ if(len < BUFSIZE - 1) {
+ data->state.buffer[len] = '\n';
+ data->state.buffer[++len] = '\0';
+ }
+ Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
+ }
+
+ va_end(ap);
+}
+
+/* Curl_sendf() sends formated data to the server */
+CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
+ const char *fmt, ...)
+{
+ struct SessionHandle *data = conn->data;
+ ssize_t bytes_written;
+ size_t write_len;
+ CURLcode res = CURLE_OK;
+ char *s;
+ char *sptr;
+ va_list ap;
+ va_start(ap, fmt);
+ s = vaprintf(fmt, ap); /* returns an allocated string */
+ va_end(ap);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY; /* failure */
+
+ bytes_written=0;
+ write_len = strlen(s);
+ sptr = s;
+
+ for(;;) {
+ /* Write the buffer to the socket */
+ res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
+
+ if(CURLE_OK != res)
+ break;
+
+ if(data->set.verbose)
+ Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
+
+ if((size_t)bytes_written != write_len) {
+ /* if not all was written at once, we must advance the pointer, decrease
+ the size left and try again! */
+ write_len -= bytes_written;
+ sptr += bytes_written;
+ }
+ else
+ break;
+ }
+
+ free(s); /* free the output string */
+
+ return res;
+}
+
+/*
+ * Curl_write() is an internal write function that sends data to the
+ * server. Works with plain sockets, SCP, SSL or kerberos.
+ *
+ * If the write would block (CURLE_AGAIN), we return CURLE_OK and
+ * (*written == 0). Otherwise we return regular CURLcode value.
+ */
+CURLcode Curl_write(struct connectdata *conn,
+ curl_socket_t sockfd,
+ const void *mem,
+ size_t len,
+ ssize_t *written)
+{
+ ssize_t bytes_written;
+ CURLcode curlcode = CURLE_OK;
+ int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+
+ bytes_written = conn->send[num](conn, num, mem, len, &curlcode);
+
+ *written = bytes_written;
+ if(bytes_written >= 0)
+ /* we completely ignore the curlcode value when subzero is not returned */
+ return CURLE_OK;
+
+ /* handle CURLE_AGAIN or a send failure */
+ switch(curlcode) {
+ case CURLE_AGAIN:
+ *written = 0;
+ return CURLE_OK;
+
+ case CURLE_OK:
+ /* general send failure */
+ return CURLE_SEND_ERROR;
+
+ default:
+ /* we got a specific curlcode, forward it */
+ return curlcode;
+ }
+}
+
+ssize_t Curl_send_plain(struct connectdata *conn, int num,
+ const void *mem, size_t len, CURLcode *code)
+{
+ curl_socket_t sockfd = conn->sock[num];
+ ssize_t bytes_written = swrite(sockfd, mem, len);
+
+ *code = CURLE_OK;
+ if(-1 == bytes_written) {
+ int err = SOCKERRNO;
+
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == err)
+#else
+ /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
+ due to its inability to send off data without blocking. We therefor
+ treat both error codes the same here */
+ (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
+#endif
+ ) {
+ /* this is just a case of EWOULDBLOCK */
+ bytes_written=0;
+ *code = CURLE_AGAIN;
+ }
+ else {
+ failf(conn->data, "Send failure: %s",
+ Curl_strerror(conn, err));
+ conn->data->state.os_errno = err;
+ *code = CURLE_SEND_ERROR;
+ }
+ }
+ return bytes_written;
+}
+
+/*
+ * Curl_write_plain() is an internal write function that sends data to the
+ * server using plain sockets only. Otherwise meant to have the exact same
+ * proto as Curl_write()
+ */
+CURLcode Curl_write_plain(struct connectdata *conn,
+ curl_socket_t sockfd,
+ const void *mem,
+ size_t len,
+ ssize_t *written)
+{
+ ssize_t bytes_written;
+ CURLcode retcode;
+ int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+
+ bytes_written = Curl_send_plain(conn, num, mem, len, &retcode);
+
+ *written = bytes_written;
+
+ return retcode;
+}
+
+ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
+ size_t len, CURLcode *code)
+{
+ curl_socket_t sockfd = conn->sock[num];
+ ssize_t nread = sread(sockfd, buf, len);
+
+ *code = CURLE_OK;
+ if(-1 == nread) {
+ int err = SOCKERRNO;
+
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == err)
+#else
+ /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
+ due to its inability to send off data without blocking. We therefor
+ treat both error codes the same here */
+ (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
+#endif
+ ) {
+ /* this is just a case of EWOULDBLOCK */
+ *code = CURLE_AGAIN;
+ }
+ else {
+ failf(conn->data, "Recv failure: %s",
+ Curl_strerror(conn, err));
+ conn->data->state.os_errno = err;
+ *code = CURLE_RECV_ERROR;
+ }
+ }
+ return nread;
+}
+
+static CURLcode pausewrite(struct SessionHandle *data,
+ int type, /* what type of data */
+ const char *ptr,
+ size_t len)
+{
+ /* signalled to pause sending on this connection, but since we have data
+ we want to send we need to dup it to save a copy for when the sending
+ is again enabled */
+ struct SingleRequest *k = &data->req;
+ char *dupl = malloc(len);
+ if(!dupl)
+ return CURLE_OUT_OF_MEMORY;
+
+ memcpy(dupl, ptr, len);
+
+ /* store this information in the state struct for later use */
+ data->state.tempwrite = dupl;
+ data->state.tempwritesize = len;
+ data->state.tempwritetype = type;
+
+ /* mark the connection as RECV paused */
+ k->keepon |= KEEP_RECV_PAUSE;
+
+ DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
+ len, type));
+
+ return CURLE_OK;
+}
+
+
+/* Curl_client_write() sends data to the write callback(s)
+
+ The bit pattern defines to what "streams" to write to. Body and/or header.
+ The defines are in sendf.h of course.
+
+ If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
+ local character encoding. This is a problem and should be changed in
+ the future to leave the original data alone.
+ */
+CURLcode Curl_client_write(struct connectdata *conn,
+ int type,
+ char *ptr,
+ size_t len)
+{
+ struct SessionHandle *data = conn->data;
+ size_t wrote;
+
+ if(0 == len)
+ len = strlen(ptr);
+
+ /* If reading is actually paused, we're forced to append this chunk of data
+ to the already held data, but only if it is the same type as otherwise it
+ can't work and it'll return error instead. */
+ if(data->req.keepon & KEEP_RECV_PAUSE) {
+ size_t newlen;
+ char *newptr;
+ if(type != data->state.tempwritetype)
+ /* major internal confusion */
+ return CURLE_RECV_ERROR;
+
+ DEBUGASSERT(data->state.tempwrite);
+
+ /* figure out the new size of the data to save */
+ newlen = len + data->state.tempwritesize;
+ /* allocate the new memory area */
+ newptr = realloc(data->state.tempwrite, newlen);
+ if(!newptr)
+ return CURLE_OUT_OF_MEMORY;
+ /* copy the new data to the end of the new area */
+ memcpy(newptr + data->state.tempwritesize, ptr, len);
+ /* update the pointer and the size */
+ data->state.tempwrite = newptr;
+ data->state.tempwritesize = newlen;
+
+ return CURLE_OK;
+ }
+
+ if(type & CLIENTWRITE_BODY) {
+ if((conn->handler->protocol&PROTO_FAMILY_FTP) &&
+ conn->proto.ftpc.transfertype == 'A') {
+ /* convert from the network encoding */
+ CURLcode rc = Curl_convert_from_network(data, ptr, len);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ if(rc)
+ return rc;
+
+#ifdef CURL_DO_LINEEND_CONV
+ /* convert end-of-line markers */
+ len = convert_lineends(data, ptr, len);
+#endif /* CURL_DO_LINEEND_CONV */
+ }
+ /* If the previous block of data ended with CR and this block of data is
+ just a NL, then the length might be zero */
+ if(len) {
+ wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
+ }
+ else {
+ wrote = len;
+ }
+
+ if(CURL_WRITEFUNC_PAUSE == wrote) {
+ if(conn->handler->flags & PROTOPT_NONETWORK) {
+ /* Protocols that work without network cannot be paused. This is
+ actually only FILE:// just now, and it can't pause since the
+ transfer isn't done using the "normal" procedure. */
+ failf(data, "Write callback asked for PAUSE when not supported!");
+ return CURLE_WRITE_ERROR;
+ }
+ else
+ return pausewrite(data, type, ptr, len);
+ }
+ else if(wrote != len) {
+ failf(data, "Failed writing body (%zu != %zu)", wrote, len);
+ return CURLE_WRITE_ERROR;
+ }
+ }
+
+ if((type & CLIENTWRITE_HEADER) &&
+ (data->set.fwrite_header || data->set.writeheader) ) {
+ /*
+ * Write headers to the same callback or to the especially setup
+ * header callback function (added after version 7.7.1).
+ */
+ curl_write_callback writeit=
+ data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func;
+
+ /* Note: The header is in the host encoding
+ regardless of the ftp transfer mode (ASCII/Image) */
+
+ wrote = writeit(ptr, 1, len, data->set.writeheader);
+ if(CURL_WRITEFUNC_PAUSE == wrote)
+ /* here we pass in the HEADER bit only since if this was body as well
+ then it was passed already and clearly that didn't trigger the pause,
+ so this is saved for later with the HEADER bit only */
+ return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
+
+ if(wrote != len) {
+ failf (data, "Failed writing header");
+ return CURLE_WRITE_ERROR;
+ }
+ }
+
+ return CURLE_OK;
+}
+
+CURLcode Curl_read_plain(curl_socket_t sockfd,
+ char *buf,
+ size_t bytesfromsocket,
+ ssize_t *n)
+{
+ ssize_t nread = sread(sockfd, buf, bytesfromsocket);
+
+ if(-1 == nread) {
+ int err = SOCKERRNO;
+#ifdef USE_WINSOCK
+ if(WSAEWOULDBLOCK == err)
+#else
+ if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
+#endif
+ return CURLE_AGAIN;
+ else
+ return CURLE_RECV_ERROR;
+ }
+
+ /* we only return number of bytes read when we return OK */
+ *n = nread;
+ return CURLE_OK;
+}
+
+/*
+ * Internal read-from-socket function. This is meant to deal with plain
+ * sockets, SSL sockets and kerberos sockets.
+ *
+ * Returns a regular CURLcode value.
+ */
+CURLcode Curl_read(struct connectdata *conn, /* connection data */
+ curl_socket_t sockfd, /* read from this socket */
+ char *buf, /* store read data here */
+ size_t sizerequested, /* max amount to read */
+ ssize_t *n) /* amount bytes read */
+{
+ CURLcode curlcode = CURLE_RECV_ERROR;
+ ssize_t nread = 0;
+ size_t bytesfromsocket = 0;
+ char *buffertofill = NULL;
+ bool pipelining = Curl_multi_pipeline_enabled(conn->data->multi);
+
+ /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
+ If it is the second socket, we set num to 1. Otherwise to 0. This lets
+ us use the correct ssl handle. */
+ int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+
+ *n=0; /* reset amount to zero */
+
+ /* If session can pipeline, check connection buffer */
+ if(pipelining) {
+ size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
+ sizerequested);
+
+ /* Copy from our master buffer first if we have some unread data there*/
+ if(bytestocopy > 0) {
+ memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
+ conn->read_pos += bytestocopy;
+ conn->bits.stream_was_rewound = FALSE;
+
+ *n = (ssize_t)bytestocopy;
+ return CURLE_OK;
+ }
+ /* If we come here, it means that there is no data to read from the buffer,
+ * so we read from the socket */
+ bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
+ buffertofill = conn->master_buffer;
+ }
+ else {
+ bytesfromsocket = CURLMIN((long)sizerequested,
+ conn->data->set.buffer_size ?
+ conn->data->set.buffer_size : BUFSIZE);
+ buffertofill = buf;
+ }
+
+ nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &curlcode);
+ if(nread < 0)
+ return curlcode;
+
+ if(pipelining) {
+ memcpy(buf, conn->master_buffer, nread);
+ conn->buf_len = nread;
+ conn->read_pos = nread;
+ }
+
+ *n += nread;
+
+ return CURLE_OK;
+}
+
+/* return 0 on success */
+static int showit(struct SessionHandle *data, curl_infotype type,
+ char *ptr, size_t size)
+{
+ static const char s_infotype[CURLINFO_END][3] = {
+ "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
+
+#ifdef CURL_DOES_CONVERSIONS
+ char buf[BUFSIZE+1];
+ size_t conv_size = 0;
+
+ switch(type) {
+ case CURLINFO_HEADER_OUT:
+ /* assume output headers are ASCII */
+ /* copy the data into my buffer so the original is unchanged */
+ if(size > BUFSIZE) {
+ size = BUFSIZE; /* truncate if necessary */
+ buf[BUFSIZE] = '\0';
+ }
+ conv_size = size;
+ memcpy(buf, ptr, size);
+ /* Special processing is needed for this block if it
+ * contains both headers and data (separated by CRLFCRLF).
+ * We want to convert just the headers, leaving the data as-is.
+ */
+ if(size > 4) {
+ size_t i;
+ for(i = 0; i < size-4; i++) {
+ if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
+ /* convert everything through this CRLFCRLF but no further */
+ conv_size = i + 4;
+ break;
+ }
+ }
+ }
+
+ Curl_convert_from_network(data, buf, conv_size);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* we might as well continue even if it fails... */
+ ptr = buf; /* switch pointer to use my buffer instead */
+ break;
+ default:
+ /* leave everything else as-is */
+ break;
+ }
+#endif /* CURL_DOES_CONVERSIONS */
+
+ if(data->set.fdebug)
+ return (*data->set.fdebug)(data, type, ptr, size,
+ data->set.debugdata);
+
+ switch(type) {
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_HEADER_IN:
+ fwrite(s_infotype[type], 2, 1, data->set.err);
+ fwrite(ptr, size, 1, data->set.err);
+#ifdef CURL_DOES_CONVERSIONS
+ if(size != conv_size) {
+ /* we had untranslated data so we need an explicit newline */
+ fwrite("\n", 1, 1, data->set.err);
+ }
+#endif
+ break;
+ default: /* nada */
+ break;
+ }
+ return 0;
+}
+
+int Curl_debug(struct SessionHandle *data, curl_infotype type,
+ char *ptr, size_t size,
+ struct connectdata *conn)
+{
+ int rc;
+ if(data->set.printhost && conn && conn->host.dispname) {
+ char buffer[160];
+ const char *t=NULL;
+ const char *w="Data";
+ switch (type) {
+ case CURLINFO_HEADER_IN:
+ w = "Header";
+ case CURLINFO_DATA_IN:
+ t = "from";
+ break;
+ case CURLINFO_HEADER_OUT:
+ w = "Header";
+ case CURLINFO_DATA_OUT:
+ t = "to";
+ break;
+ default:
+ break;
+ }
+
+ if(t) {
+ snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
+ conn->host.dispname);
+ rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
+ if(rc)
+ return rc;
+ }
+ }
+ rc = showit(data, type, ptr, size);
+ return rc;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/sendf.h b/external/libcurl_android/jni/libcurl/lib/sendf.h
new file mode 100755
index 00000000..39489e40
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/sendf.h
@@ -0,0 +1,90 @@
+#ifndef HEADER_CURL_SENDF_H
+#define HEADER_CURL_SENDF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *,
+ const char *fmt, ...);
+void Curl_infof(struct SessionHandle *, const char *fmt, ...);
+void Curl_failf(struct SessionHandle *, const char *fmt, ...);
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+
+#if defined(HAVE_VARIADIC_MACROS_C99)
+#define infof(...) Curl_nop_stmt
+#elif defined(HAVE_VARIADIC_MACROS_GCC)
+#define infof(x...) Curl_nop_stmt
+#else
+#define infof (void)
+#endif
+
+#else /* CURL_DISABLE_VERBOSE_STRINGS */
+
+#define infof Curl_infof
+
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+
+#define failf Curl_failf
+
+#define CLIENTWRITE_BODY (1<<0)
+#define CLIENTWRITE_HEADER (1<<1)
+#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
+
+CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
+ size_t len);
+
+/* internal read-function, does plain socket only */
+CURLcode Curl_read_plain(curl_socket_t sockfd,
+ char *buf,
+ size_t bytesfromsocket,
+ ssize_t *n);
+
+ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
+ size_t len, CURLcode *code);
+ssize_t Curl_send_plain(struct connectdata *conn, int num,
+ const void *mem, size_t len, CURLcode *code);
+
+/* internal read-function, does plain socket, SSL and krb4 */
+CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd,
+ char *buf, size_t buffersize,
+ ssize_t *n);
+/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
+CURLcode Curl_write(struct connectdata *conn,
+ curl_socket_t sockfd,
+ const void *mem, size_t len,
+ ssize_t *written);
+
+/* internal write-function, does plain sockets ONLY */
+CURLcode Curl_write_plain(struct connectdata *conn,
+ curl_socket_t sockfd,
+ const void *mem, size_t len,
+ ssize_t *written);
+
+/* the function used to output verbose information */
+int Curl_debug(struct SessionHandle *handle, curl_infotype type,
+ char *data, size_t size,
+ struct connectdata *conn);
+
+
+#endif /* HEADER_CURL_SENDF_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/setup-os400.h b/external/libcurl_android/jni/libcurl/lib/setup-os400.h
new file mode 100755
index 00000000..0331464e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/setup-os400.h
@@ -0,0 +1,239 @@
+#ifndef HEADER_CURL_SETUP_OS400_H
+#define HEADER_CURL_SETUP_OS400_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+
+/* OS/400 netdb.h does not define NI_MAXHOST. */
+#define NI_MAXHOST 1025
+
+/* OS/400 netdb.h does not define NI_MAXSERV. */
+#define NI_MAXSERV 32
+
+/* No OS/400 header file defines u_int32_t. */
+typedef unsigned long u_int32_t;
+
+
+/* System API wrapper prototypes & definitions to support ASCII parameters. */
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <qsossl.h>
+#include <gskssl.h>
+#include <qsoasync.h>
+#include <gssapi.h>
+
+extern int Curl_getaddrinfo_a(const char * nodename,
+ const char * servname,
+ const struct addrinfo * hints,
+ struct addrinfo * * res);
+#define getaddrinfo Curl_getaddrinfo_a
+
+
+extern int Curl_getnameinfo_a(const struct sockaddr * sa,
+ curl_socklen_t salen,
+ char * nodename, curl_socklen_t nodenamelen,
+ char * servname, curl_socklen_t servnamelen,
+ int flags);
+#define getnameinfo Curl_getnameinfo_a
+
+
+/* SSL wrappers. */
+
+extern int Curl_SSL_Init_Application_a(SSLInitApp * init_app);
+#define SSL_Init_Application Curl_SSL_Init_Application_a
+
+
+extern int Curl_SSL_Init_a(SSLInit * init);
+#define SSL_Init Curl_SSL_Init_a
+
+
+extern char * Curl_SSL_Strerror_a(int sslreturnvalue,
+ SSLErrorMsg * serrmsgp);
+#define SSL_Strerror Curl_SSL_Strerror_a
+
+
+/* GSKit wrappers. */
+
+extern int Curl_gsk_environment_open(gsk_handle * my_env_handle);
+#define gsk_environment_open Curl_gsk_environment_open
+
+extern int Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
+ gsk_handle * my_session_handle);
+#define gsk_secure_soc_open Curl_gsk_secure_soc_open
+
+extern int Curl_gsk_environment_close(gsk_handle * my_env_handle);
+#define gsk_environment_close Curl_gsk_environment_close
+
+extern int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle);
+#define gsk_secure_soc_close Curl_gsk_secure_soc_close
+
+extern int Curl_gsk_environment_init(gsk_handle my_env_handle);
+#define gsk_environment_init Curl_gsk_environment_init
+
+extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
+#define gsk_secure_soc_init Curl_gsk_secure_soc_init
+
+extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
+ GSK_BUF_ID bufID,
+ const char * buffer,
+ int bufSize);
+#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a
+
+extern int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle,
+ GSK_ENUM_ID enumID,
+ GSK_ENUM_VALUE enumValue);
+#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum
+
+extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
+ GSK_NUM_ID numID,
+ int numValue);
+#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value
+
+extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
+ GSK_CALLBACK_ID callBackID,
+ void * callBackAreaPtr);
+#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback
+
+extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
+ GSK_BUF_ID bufID,
+ const char * * buffer,
+ int * bufSize);
+#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a
+
+extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
+ GSK_ENUM_ID enumID,
+ GSK_ENUM_VALUE * enumValue);
+#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum
+
+extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
+ GSK_NUM_ID numID,
+ int * numValue);
+#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
+
+extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
+ GSK_CERT_ID certID,
+ const gsk_cert_data_elem * * certDataElem,
+ int * certDataElementCount);
+#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info
+
+extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
+ GSK_MISC_ID miscID);
+#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc
+
+extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
+ char * readBuffer,
+ int readBufSize, int * amtRead);
+#define gsk_secure_soc_read Curl_gsk_secure_soc_read
+
+extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
+ char * writeBuffer,
+ int writeBufSize, int * amtWritten);
+#define gsk_secure_soc_write Curl_gsk_secure_soc_write
+
+extern const char * Curl_gsk_strerror_a(int gsk_return_value);
+#define gsk_strerror Curl_gsk_strerror_a
+
+extern int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
+ int IOCompletionPort,
+ Qso_OverlappedIO_t * communicationsArea);
+#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit
+
+
+/* GSSAPI wrappers. */
+
+extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status,
+ gss_buffer_t in_name,
+ gss_OID in_name_type,
+ gss_name_t * out_name);
+#define gss_import_name Curl_gss_import_name_a
+
+
+extern OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status,
+ OM_uint32 status_value,
+ int status_type, gss_OID mech_type,
+ gss_msg_ctx_t * message_context,
+ gss_buffer_t status_string);
+#define gss_display_status Curl_gss_display_status_a
+
+
+extern OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status,
+ gss_cred_id_t cred_handle,
+ gss_ctx_id_t * context_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ gss_flags_t req_flags,
+ OM_uint32 time_req,
+ gss_channel_bindings_t
+ input_chan_bindings,
+ gss_buffer_t input_token,
+ gss_OID * actual_mech_type,
+ gss_buffer_t output_token,
+ gss_flags_t * ret_flags,
+ OM_uint32 * time_rec);
+#define gss_init_sec_context Curl_gss_init_sec_context_a
+
+
+extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
+ gss_ctx_id_t * context_handle,
+ gss_buffer_t output_token);
+#define gss_delete_sec_context Curl_gss_delete_sec_context_a
+
+
+/* LDAP wrappers. */
+
+#define BerValue struct berval
+
+#define ldap_url_parse ldap_url_parse_utf8
+#define ldap_init Curl_ldap_init_a
+#define ldap_simple_bind_s Curl_ldap_simple_bind_s_a
+#define ldap_search_s Curl_ldap_search_s_a
+#define ldap_get_values_len Curl_ldap_get_values_len_a
+#define ldap_err2string Curl_ldap_err2string_a
+#define ldap_get_dn Curl_ldap_get_dn_a
+#define ldap_first_attribute Curl_ldap_first_attribute_a
+#define ldap_next_attribute Curl_ldap_next_attribute_a
+
+/* Some socket functions must be wrapped to process textual addresses
+ like AF_UNIX. */
+
+extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen);
+extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen);
+extern int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
+ struct sockaddr * dstaddr, int addrlen);
+extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
+ struct sockaddr * fromaddr, int * addrlen);
+
+#define connect Curl_os400_connect
+#define bind Curl_os400_bind
+#define sendto Curl_os400_sendto
+#define recvfrom Curl_os400_recvfrom
+
+#ifdef HAVE_LIBZ
+#define zlibVersion Curl_os400_zlibVersion
+#define inflateInit_ Curl_os400_inflateInit_
+#define inflateInit2_ Curl_os400_inflateInit2_
+#define inflate Curl_os400_inflate
+#define inflateEnd Curl_os400_inflateEnd
+#endif
+
+#endif /* HEADER_CURL_SETUP_OS400_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/setup-vms.h b/external/libcurl_android/jni/libcurl/lib/setup-vms.h
new file mode 100755
index 00000000..f5eedf75
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/setup-vms.h
@@ -0,0 +1,399 @@
+#ifndef HEADER_CURL_SETUP_VMS_H
+#define HEADER_CURL_SETUP_VMS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* */
+/* JEM, 12/30/12, VMS now generates config.h, so only define wrappers for */
+/* getenv(), getpwuid() and provide is_vms_shell() */
+/* Also need upper case symbols for system services, and */
+/* OpenSSL, and some Kerberos image */
+
+#ifdef __DECC
+#pragma message save
+#pragma message disable dollarid
+#endif
+
+/* Hide the stuff we are overriding */
+#define getenv decc_getenv
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE != 64
+# define getpwuid decc_getpwuid
+# endif
+#endif
+#include <stdlib.h>
+ char * decc$getenv(const char * __name);
+#include <pwd.h>
+
+#include <string.h>
+#include <unixlib.h>
+
+#undef getenv
+#undef getpwuid
+#define getenv vms_getenv
+#define getpwuid vms_getpwuid
+
+/* VAX needs these in upper case when compiling exact case */
+#define sys$assign SYS$ASSIGN
+#define sys$dassgn SYS$DASSGN
+#define sys$qiow SYS$QIOW
+
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE
+# pragma __pointer_size __save
+# endif
+#endif
+
+#if __USE_LONG_GID_T
+# define decc_getpwuid DECC$__LONG_GID_GETPWUID
+#else
+# if __INITIAL_POINTER_SIZE
+# define decc_getpwuid decc$__32_getpwuid
+# else
+# define decc_getpwuid decc$getpwuid
+# endif
+#endif
+
+ struct passwd * decc_getpwuid(uid_t uid);
+
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE == 32
+/* Translate the path, but only if the path is a VMS file specification */
+/* The translation is usually only needed for older versions of VMS */
+static char * vms_translate_path(const char * path) {
+char * unix_path;
+char * test_str;
+
+ /* See if the result is in VMS format, if not, we are done */
+ /* Assume that this is a PATH, not just some data */
+ test_str = strpbrk(path, ":[<^");
+ if(test_str == NULL) {
+ return (char *)path;
+ }
+
+ unix_path = decc$translate_vms(path);
+
+ if((int)unix_path <= 0) {
+ /* We can not translate it, so return the original string */
+ return (char *)path;
+ }
+}
+# else
+ /* VMS translate path is actually not needed on the current 64 bit */
+ /* VMS platforms, so instead of figuring out the pointer settings */
+ /* Change it to a noop */
+# define vms_translate_path(__path) __path
+# endif
+#endif
+
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE
+# pragma __pointer_size __restore
+# endif
+#endif
+
+static char * vms_getenv(const char * envvar) {
+
+char * result;
+char * vms_path;
+
+ /* first use the DECC getenv() function */
+ result = decc$getenv(envvar);
+ if(result == NULL) {
+ return result;
+ }
+
+ vms_path = result;
+ result = vms_translate_path(vms_path);
+
+ /* note that if you backport this to use VAX C RTL, that the VAX C RTL */
+ /* may do a malloc(2048) for each call to getenv(), so you will need */
+ /* to add a free(vms_path) */
+ /* Do not do a free() for DEC C RTL builds, which should be used for */
+ /* VMS 5.5-2 and later, even if using GCC */
+
+ return result;
+}
+
+
+static struct passwd vms_passwd_cache;
+
+static struct passwd * vms_getpwuid(uid_t uid) {
+
+struct passwd * my_passwd;
+
+/* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */
+#ifdef __DECC
+# if __INITIAL_POINTER_SIZE
+__char_ptr32 unix_path;
+# else
+char * unix_path;
+# endif
+#else
+char * unix_path;
+#endif
+
+ my_passwd = decc_getpwuid(uid);
+ if(my_passwd == NULL) {
+ return my_passwd;
+ }
+
+ unix_path = vms_translate_path(my_passwd->pw_dir);
+
+ if((long)unix_path <= 0) {
+ /* We can not translate it, so return the original string */
+ return my_passwd;
+ }
+
+ /* If no changes needed just return it */
+ if(unix_path == my_passwd->pw_dir) {
+ return my_passwd;
+ }
+
+ /* Need to copy the structure returned */
+ /* Since curl is only using pw_dir, no need to fix up *
+ /* the pw_shell when running under Bash */
+ vms_passwd_cache.pw_name = my_passwd->pw_name;
+ vms_passwd_cache.pw_uid = my_passwd->pw_uid;
+ vms_passwd_cache.pw_gid = my_passwd->pw_uid;
+ vms_passwd_cache.pw_dir = unix_path;
+ vms_passwd_cache.pw_shell = my_passwd->pw_shell;
+
+ return &vms_passwd_cache;
+}
+
+#ifdef __DECC
+#pragma message restore
+#endif
+
+/* Bug - VMS OpenSSL and Kerberos universal symbols are in uppercase only */
+/* VMS libraries should have universal symbols in exact and uppercase */
+
+#define ASN1_INTEGER_get ASN1_INTEGER_GET
+#define ASN1_STRING_data ASN1_STRING_DATA
+#define ASN1_STRING_length ASN1_STRING_LENGTH
+#define ASN1_STRING_print ASN1_STRING_PRINT
+#define ASN1_STRING_to_UTF8 ASN1_STRING_TO_UTF8
+#define ASN1_STRING_type ASN1_STRING_TYPE
+#define BIO_ctrl BIO_CTRL
+#define BIO_free BIO_FREE
+#define BIO_new BIO_NEW
+#define BIO_s_mem BIO_S_MEM
+#define BN_bn2bin BN_BN2BIN
+#define BN_num_bits BN_NUM_BITS
+#define CRYPTO_cleanup_all_ex_data CRYPTO_CLEANUP_ALL_EX_DATA
+#define CRYPTO_free CRYPTO_FREE
+#define CRYPTO_malloc CRYPTO_MALLOC
+#define DES_ecb_encrypt DES_ECB_ENCRYPT
+#define DES_set_key DES_SET_KEY
+#define DES_set_odd_parity DES_SET_ODD_PARITY
+#define ENGINE_ctrl ENGINE_CTRL
+#define ENGINE_ctrl_cmd ENGINE_CTRL_CMD
+#define ENGINE_finish ENGINE_FINISH
+#define ENGINE_free ENGINE_FREE
+#define ENGINE_get_first ENGINE_GET_FIRST
+#define ENGINE_get_id ENGINE_GET_ID
+#define ENGINE_get_next ENGINE_GET_NEXT
+#define ENGINE_init ENGINE_INIT
+#define ENGINE_load_builtin_engines ENGINE_LOAD_BUILTIN_ENGINES
+#define ENGINE_load_private_key ENGINE_LOAD_PRIVATE_KEY
+#define ENGINE_set_default ENGINE_SET_DEFAULT
+#define ERR_clear_error ERR_CLEAR_ERROR
+#define ERR_error_string ERR_ERROR_STRING
+#define ERR_error_string_n ERR_ERROR_STRING_N
+#define ERR_free_strings ERR_FREE_STRINGS
+#define ERR_get_error ERR_GET_ERROR
+#define ERR_peek_error ERR_PEEK_ERROR
+#define ERR_remove_state ERR_REMOVE_STATE
+#define EVP_PKEY_copy_parameters EVP_PKEY_COPY_PARAMETERS
+#define EVP_PKEY_free EVP_PKEY_FREE
+#define EVP_cleanup EVP_CLEANUP
+#define GENERAL_NAMES_free GENERAL_NAMES_FREE
+#define MD4_Final MD4_FINAL
+#define MD4_Init MD4_INIT
+#define MD4_Update MD4_UPDATE
+#define MD5_Final MD5_FINAL
+#define MD5_Init MD5_INIT
+#define MD5_Update MD5_UPDATE
+#define OPENSSL_add_all_algo_noconf OPENSSL_ADD_ALL_ALGO_NOCONF
+#define PEM_read_X509 PEM_READ_X509
+#define PEM_write_bio_X509 PEM_WRITE_BIO_X509
+#define PKCS12_PBE_add PKCS12_PBE_ADD
+#define PKCS12_free PKCS12_FREE
+#define PKCS12_parse PKCS12_PARSE
+#define RAND_add RAND_ADD
+#define RAND_bytes RAND_BYTES
+#define RAND_egd RAND_EGD
+#define RAND_file_name RAND_FILE_NAME
+#define RAND_load_file RAND_LOAD_FILE
+#define RAND_status RAND_STATUS
+#define SSL_CIPHER_get_name SSL_CIPHER_GET_NAME
+#define SSL_CTX_add_client_CA SSL_CTX_ADD_CLIENT_CA
+#define SSL_CTX_callback_ctrl SSL_CTX_CALLBACK_CTRL
+#define SSL_CTX_check_private_key SSL_CTX_CHECK_PRIVATE_KEY
+#define SSL_CTX_ctrl SSL_CTX_CTRL
+#define SSL_CTX_free SSL_CTX_FREE
+#define SSL_CTX_get_cert_store SSL_CTX_GET_CERT_STORE
+#define SSL_CTX_load_verify_locations SSL_CTX_LOAD_VERIFY_LOCATIONS
+#define SSL_CTX_new SSL_CTX_NEW
+#define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST
+#define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD
+#define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB
+#define SSL_CTX_set_verify SSL_CTX_SET_VERIFY
+#define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY
+#define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE
+#define SSL_CTX_use_cert_chain_file SSL_CTX_USE_CERT_CHAIN_FILE
+#define SSL_CTX_use_certificate SSL_CTX_USE_CERTIFICATE
+#define SSL_CTX_use_certificate_file SSL_CTX_USE_CERTIFICATE_FILE
+#define SSL_SESSION_free SSL_SESSION_FREE
+#define SSL_connect SSL_CONNECT
+#define SSL_free SSL_FREE
+#define SSL_get1_session SSL_GET1_SESSION
+#define SSL_get_certificate SSL_GET_CERTIFICATE
+#define SSL_get_current_cipher SSL_GET_CURRENT_CIPHER
+#define SSL_get_error SSL_GET_ERROR
+#define SSL_get_peer_cert_chain SSL_GET_PEER_CERT_CHAIN
+#define SSL_get_peer_certificate SSL_GET_PEER_CERTIFICATE
+#define SSL_get_privatekey SSL_GET_PRIVATEKEY
+#define SSL_get_shutdown SSL_GET_SHUTDOWN
+#define SSL_get_verify_result SSL_GET_VERIFY_RESULT
+#define SSL_library_init SSL_LIBRARY_INIT
+#define SSL_load_error_strings SSL_LOAD_ERROR_STRINGS
+#define SSL_new SSL_NEW
+#define SSL_peek SSL_PEEK
+#define SSL_pending SSL_PENDING
+#define SSL_read SSL_READ
+#define SSL_set_connect_state SSL_SET_CONNECT_STATE
+#define SSL_set_fd SSL_SET_FD
+#define SSL_set_session SSL_SET_SESSION
+#define SSL_shutdown SSL_SHUTDOWN
+#define SSL_write SSL_WRITE
+#define SSLeay SSLEAY
+#define SSLv23_client_method SSLV23_CLIENT_METHOD
+#define SSLv3_client_method SSLV3_CLIENT_METHOD
+#define TLSv1_client_method TLSV1_CLIENT_METHOD
+#define UI_OpenSSL UI_OPENSSL
+#define X509V3_EXT_print X509V3_EXT_PRINT
+#define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL
+#define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT
+#define X509_LOOKUP_file X509_LOOKUP_FILE
+#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA
+#define X509_NAME_get_entry X509_NAME_GET_ENTRY
+#define X509_NAME_get_index_by_NID X509_NAME_GET_INDEX_BY_NID
+#define X509_NAME_print_ex X509_NAME_PRINT_EX
+#define X509_STORE_CTX_get_current_cert X509_STORE_CTX_GET_CURRENT_CERT
+#define X509_STORE_add_lookup X509_STORE_ADD_LOOKUP
+#define X509_STORE_set_flags X509_STORE_SET_FLAGS
+#define X509_check_issued X509_CHECK_ISSUED
+#define X509_free X509_FREE
+#define X509_get_ext_d2i X509_GET_EXT_D2I
+#define X509_get_issuer_name X509_GET_ISSUER_NAME
+#define X509_get_pubkey X509_GET_PUBKEY
+#define X509_get_serialNumber X509_GET_SERIALNUMBER
+#define X509_get_subject_name X509_GET_SUBJECT_NAME
+#define X509_load_crl_file X509_LOAD_CRL_FILE
+#define X509_verify_cert_error_string X509_VERIFY_CERT_ERROR_STRING
+#define d2i_PKCS12_fp D2I_PKCS12_FP
+#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT
+#define sk_num SK_NUM
+#define sk_pop SK_POP
+#define sk_pop_free SK_POP_FREE
+#define sk_value SK_VALUE
+
+#define USE_UPPERCASE_GSSAPI 1
+#define gss_seal GSS_SEAL
+#define gss_unseal GSS_UNSEAL
+
+#define USE_UPPERCASE_KRBAPI 1
+
+/* AI_NUMERICHOST needed for IP V6 support in Curl */
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#ifndef AI_NUMERICHOST
+#ifdef ENABLE_IPV6
+#undef ENABLE_IPV6
+#endif
+#endif
+#endif
+
+/* VAX symbols are always in uppercase */
+#ifdef __VAX
+#define inflate INFLATE
+#define inflateEnd INFLATEEND
+#define inflateInit2_ INFLATEINIT2_
+#define inflateInit_ INFLATEINIT_
+#define zlibVersion ZLIBVERSION
+#endif
+
+/* Older VAX OpenSSL port defines these as Macros */
+/* Need to include the headers first and then redefine */
+/* that way a newer port will also work if some one has one */
+#ifdef __VAX
+
+# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+# define des_set_odd_parity DES_SET_ODD_PARITY
+# define des_set_key DES_SET_KEY
+# define des_ecb_encrypt DES_ECB_ENCRYPT
+
+# endif
+# include <openssl/evp.h>
+# ifndef OpenSSL_add_all_algorithms
+# define OpenSSL_add_all_algorithms OPENSSL_ADD_ALL_ALGORITHMS
+ void OPENSSL_ADD_ALL_ALGORITHMS(void);
+# endif
+
+ /* Curl defines these to lower case and VAX needs them in upper case */
+ /* So we need static routines */
+# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+
+# undef des_set_odd_parity
+# undef DES_set_odd_parity
+# undef des_set_key
+# undef DES_set_key
+# undef des_ecb_encrypt
+# undef DES_ecb_encrypt
+
+ static void des_set_odd_parity(des_cblock *key) {
+ DES_SET_ODD_PARITY(key);
+ }
+
+ static int des_set_key(const_des_cblock *key,
+ des_key_schedule schedule) {
+ return DES_SET_KEY(key, schedule);
+ }
+
+ static void des_ecb_encrypt(const_des_cblock *input,
+ des_cblock *output,
+ des_key_schedule ks,int enc) {
+ DES_ECB_ENCRYPT(input, output, ks, enc);
+ }
+#endif
+/* Need this to stop a macro redefinition error */
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+# ifdef X509_STORE_set_flags
+# undef X509_STORE_set_flags
+# define X509_STORE_set_flags(x,y) Curl_nop_stmt
+# endif
+#endif
+#endif
+
+#endif /* HEADER_CURL_SETUP_VMS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/share.c b/external/libcurl_android/jni/libcurl/lib/share.c
new file mode 100755
index 00000000..b8b6bee8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/share.c
@@ -0,0 +1,254 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "share.h"
+#include "vtls/vtls.h"
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+CURLSH *
+curl_share_init(void)
+{
+ struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
+ if(share)
+ share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
+
+ return share;
+}
+
+#undef curl_share_setopt
+CURLSHcode
+curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
+{
+ struct Curl_share *share = (struct Curl_share *)sh;
+ va_list param;
+ int type;
+ curl_lock_function lockfunc;
+ curl_unlock_function unlockfunc;
+ void *ptr;
+ CURLSHcode res = CURLSHE_OK;
+
+ if(share->dirty)
+ /* don't allow setting options while one or more handles are already
+ using this share */
+ return CURLSHE_IN_USE;
+
+ va_start(param, option);
+
+ switch(option) {
+ case CURLSHOPT_SHARE:
+ /* this is a type this share will share */
+ type = va_arg(param, int);
+ share->specifier |= (1<<type);
+ switch( type ) {
+ case CURL_LOCK_DATA_DNS:
+ if(!share->hostcache) {
+ share->hostcache = Curl_mk_dnscache();
+ if(!share->hostcache)
+ res = CURLSHE_NOMEM;
+ }
+ break;
+
+ case CURL_LOCK_DATA_COOKIE:
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(!share->cookies) {
+ share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE );
+ if(!share->cookies)
+ res = CURLSHE_NOMEM;
+ }
+#else /* CURL_DISABLE_HTTP */
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
+ case CURL_LOCK_DATA_SSL_SESSION:
+#ifdef USE_SSL
+ if(!share->sslsession) {
+ share->max_ssl_sessions = 8;
+ share->sslsession = calloc(share->max_ssl_sessions,
+ sizeof(struct curl_ssl_session));
+ share->sessionage = 0;
+ if(!share->sslsession)
+ res = CURLSHE_NOMEM;
+ }
+#else
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
+ case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
+ break;
+
+ default:
+ res = CURLSHE_BAD_OPTION;
+ }
+ break;
+
+ case CURLSHOPT_UNSHARE:
+ /* this is a type this share will no longer share */
+ type = va_arg(param, int);
+ share->specifier &= ~(1<<type);
+ switch( type ) {
+ case CURL_LOCK_DATA_DNS:
+ if(share->hostcache) {
+ Curl_hash_destroy(share->hostcache);
+ share->hostcache = NULL;
+ }
+ break;
+
+ case CURL_LOCK_DATA_COOKIE:
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(share->cookies) {
+ Curl_cookie_cleanup(share->cookies);
+ share->cookies = NULL;
+ }
+#else /* CURL_DISABLE_HTTP */
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
+ case CURL_LOCK_DATA_SSL_SESSION:
+#ifdef USE_SSL
+ Curl_safefree(share->sslsession);
+#else
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
+ case CURL_LOCK_DATA_CONNECT:
+ break;
+
+ default:
+ res = CURLSHE_BAD_OPTION;
+ break;
+ }
+ break;
+
+ case CURLSHOPT_LOCKFUNC:
+ lockfunc = va_arg(param, curl_lock_function);
+ share->lockfunc = lockfunc;
+ break;
+
+ case CURLSHOPT_UNLOCKFUNC:
+ unlockfunc = va_arg(param, curl_unlock_function);
+ share->unlockfunc = unlockfunc;
+ break;
+
+ case CURLSHOPT_USERDATA:
+ ptr = va_arg(param, void *);
+ share->clientdata = ptr;
+ break;
+
+ default:
+ res = CURLSHE_BAD_OPTION;
+ break;
+ }
+
+ va_end(param);
+
+ return res;
+}
+
+CURLSHcode
+curl_share_cleanup(CURLSH *sh)
+{
+ struct Curl_share *share = (struct Curl_share *)sh;
+
+ if(share == NULL)
+ return CURLSHE_INVALID;
+
+ if(share->lockfunc)
+ share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
+ share->clientdata);
+
+ if(share->dirty) {
+ if(share->unlockfunc)
+ share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
+ return CURLSHE_IN_USE;
+ }
+
+ if(share->hostcache) {
+ Curl_hash_destroy(share->hostcache);
+ share->hostcache = NULL;
+ }
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(share->cookies)
+ Curl_cookie_cleanup(share->cookies);
+#endif
+
+#ifdef USE_SSL
+ if(share->sslsession) {
+ size_t i;
+ for(i = 0; i < share->max_ssl_sessions; i++)
+ Curl_ssl_kill_session(&(share->sslsession[i]));
+ free(share->sslsession);
+ }
+#endif
+
+ if(share->unlockfunc)
+ share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
+ free(share);
+
+ return CURLSHE_OK;
+}
+
+
+CURLSHcode
+Curl_share_lock(struct SessionHandle *data, curl_lock_data type,
+ curl_lock_access accesstype)
+{
+ struct Curl_share *share = data->share;
+
+ if(share == NULL)
+ return CURLSHE_INVALID;
+
+ if(share->specifier & (1<<type)) {
+ if(share->lockfunc) /* only call this if set! */
+ share->lockfunc(data, type, accesstype, share->clientdata);
+ }
+ /* else if we don't share this, pretend successful lock */
+
+ return CURLSHE_OK;
+}
+
+CURLSHcode
+Curl_share_unlock(struct SessionHandle *data, curl_lock_data type)
+{
+ struct Curl_share *share = data->share;
+
+ if(share == NULL)
+ return CURLSHE_INVALID;
+
+ if(share->specifier & (1<<type)) {
+ if(share->unlockfunc) /* only call this if set! */
+ share->unlockfunc (data, type, share->clientdata);
+ }
+
+ return CURLSHE_OK;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/share.h b/external/libcurl_android/jni/libcurl/lib/share.h
new file mode 100755
index 00000000..9a5128e9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/share.h
@@ -0,0 +1,61 @@
+#ifndef HEADER_CURL_SHARE_H
+#define HEADER_CURL_SHARE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include <curl/curl.h>
+#include "cookie.h"
+#include "urldata.h"
+
+/* SalfordC says "A structure member may not be volatile". Hence:
+ */
+#ifdef __SALFORDC__
+#define CURL_VOLATILE
+#else
+#define CURL_VOLATILE volatile
+#endif
+
+/* this struct is libcurl-private, don't export details */
+struct Curl_share {
+ unsigned int specifier;
+ CURL_VOLATILE unsigned int dirty;
+
+ curl_lock_function lockfunc;
+ curl_unlock_function unlockfunc;
+ void *clientdata;
+
+ struct curl_hash *hostcache;
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ struct CookieInfo *cookies;
+#endif
+
+ struct curl_ssl_session *sslsession;
+ size_t max_ssl_sessions;
+ long sessionage;
+};
+
+CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data,
+ curl_lock_access);
+CURLSHcode Curl_share_unlock (struct SessionHandle *, curl_lock_data);
+
+#endif /* HEADER_CURL_SHARE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/sigpipe.h b/external/libcurl_android/jni/libcurl/lib/sigpipe.h
new file mode 100755
index 00000000..e8d2acd6
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/sigpipe.h
@@ -0,0 +1,78 @@
+#ifndef HEADER_CURL_SIGPIPE_H
+#define HEADER_CURL_SIGPIPE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && defined(USE_OPENSSL)
+#include <signal.h>
+
+struct sigpipe_ignore {
+ struct sigaction old_pipe_act;
+ bool no_signal;
+};
+
+#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x
+
+/*
+ * sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl
+ * internals, and then sigpipe_restore() will restore the situation when we
+ * return from libcurl again.
+ */
+static void sigpipe_ignore(struct SessionHandle *data,
+ struct sigpipe_ignore *ig)
+{
+ /* get a local copy of no_signal because the SessionHandle might not be
+ around when we restore */
+ ig->no_signal = data->set.no_signal;
+ if(!data->set.no_signal) {
+ struct sigaction action;
+ /* first, extract the existing situation */
+ memset(&ig->old_pipe_act, 0, sizeof(struct sigaction));
+ sigaction(SIGPIPE, NULL, &ig->old_pipe_act);
+ action = ig->old_pipe_act;
+ /* ignore this signal */
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+ }
+}
+
+/*
+ * sigpipe_restore() puts back the outside world's opinion of signal handler
+ * and SIGPIPE handling. It MUST only be called after a corresponding
+ * sigpipe_ignore() was used.
+ */
+static void sigpipe_restore(struct sigpipe_ignore *ig)
+{
+ if(!ig->no_signal)
+ /* restore the outside state */
+ sigaction(SIGPIPE, &ig->old_pipe_act, NULL);
+}
+
+#else
+/* for systems without sigaction */
+#define sigpipe_ignore(x,y) Curl_nop_stmt
+#define sigpipe_restore(x) Curl_nop_stmt
+#define SIGPIPE_VARIABLE(x)
+#endif
+
+#endif /* HEADER_CURL_SIGPIPE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/slist.c b/external/libcurl_android/jni/libcurl/lib/slist.c
new file mode 100755
index 00000000..3cac6ca2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/slist.c
@@ -0,0 +1,143 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "curl_memory.h"
+#include "slist.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* returns last node in linked list */
+static struct curl_slist *slist_get_last(struct curl_slist *list)
+{
+ struct curl_slist *item;
+
+ /* if caller passed us a NULL, return now */
+ if(!list)
+ return NULL;
+
+ /* loop through to find the last item */
+ item = list;
+ while(item->next) {
+ item = item->next;
+ }
+ return item;
+}
+
+/*
+ * Curl_slist_append_nodup() appends a string to the linked list. Rather than
+ * copying the string in dynamic storage, it takes its ownership. The string
+ * should have been malloc()ated. Curl_slist_append_nodup always returns
+ * the address of the first record, so that you can use this function as an
+ * initialization function as well as an append function.
+ * If an error occurs, NULL is returned and the string argument is NOT
+ * released.
+ */
+struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data)
+{
+ struct curl_slist *last;
+ struct curl_slist *new_item;
+
+ DEBUGASSERT(data);
+
+ new_item = malloc(sizeof(struct curl_slist));
+ if(!new_item)
+ return NULL;
+
+ new_item->next = NULL;
+ new_item->data = data;
+
+ /* if this is the first item, then new_item *is* the list */
+ if(!list)
+ return new_item;
+
+ last = slist_get_last(list);
+ last->next = new_item;
+ return list;
+}
+
+/*
+ * curl_slist_append() appends a string to the linked list. It always returns
+ * the address of the first record, so that you can use this function as an
+ * initialization function as well as an append function. If you find this
+ * bothersome, then simply create a separate _init function and call it
+ * appropriately from within the program.
+ */
+struct curl_slist *curl_slist_append(struct curl_slist *list,
+ const char *data)
+{
+ char *dupdata = strdup(data);
+
+ if(!dupdata)
+ return NULL;
+
+ list = Curl_slist_append_nodup(list, dupdata);
+ if(!list)
+ free(dupdata);
+
+ return list;
+}
+
+/*
+ * Curl_slist_duplicate() duplicates a linked list. It always returns the
+ * address of the first record of the cloned list or NULL in case of an
+ * error (or if the input list was NULL).
+ */
+struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist)
+{
+ struct curl_slist *outlist = NULL;
+ struct curl_slist *tmp;
+
+ while(inlist) {
+ tmp = curl_slist_append(outlist, inlist->data);
+
+ if(!tmp) {
+ curl_slist_free_all(outlist);
+ return NULL;
+ }
+
+ outlist = tmp;
+ inlist = inlist->next;
+ }
+ return outlist;
+}
+
+/* be nice and clean up resources */
+void curl_slist_free_all(struct curl_slist *list)
+{
+ struct curl_slist *next;
+ struct curl_slist *item;
+
+ if(!list)
+ return;
+
+ item = list;
+ do {
+ next = item->next;
+ Curl_safefree(item->data);
+ free(item);
+ item = next;
+ } while(next);
+}
+
diff --git a/external/libcurl_android/jni/libcurl/lib/slist.h b/external/libcurl_android/jni/libcurl/lib/slist.h
new file mode 100755
index 00000000..ea7dcc48
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/slist.h
@@ -0,0 +1,40 @@
+#ifndef HEADER_CURL_SLIST_H
+#define HEADER_CURL_SLIST_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Curl_slist_duplicate() duplicates a linked list. It always returns the
+ * address of the first record of the cloned list or NULL in case of an
+ * error (or if the input list was NULL).
+ */
+struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist);
+
+/*
+ * Curl_slist_append_nodup() takes ownership of the given string and appends
+ * it to the list.
+ */
+struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list,
+ char *data);
+
+#endif /* HEADER_CURL_SLIST_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/smtp.c b/external/libcurl_android/jni/libcurl/lib/smtp.c
new file mode 100755
index 00000000..9aa8b15b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/smtp.c
@@ -0,0 +1,2378 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * RFC1870 SMTP Service Extension for Message Size
+ * RFC2195 CRAM-MD5 authentication
+ * RFC2831 DIGEST-MD5 authentication
+ * RFC3207 SMTP over TLS
+ * RFC4422 Simple Authentication and Security Layer (SASL)
+ * RFC4616 PLAIN authentication
+ * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
+ * RFC4954 SMTP Authentication
+ * RFC5321 SMTP protocol
+ * RFC6749 OAuth 2.0 Authorization Framework
+ * Draft SMTP URL Interface <draft-earhart-url-smtp-00.txt>
+ * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_SMTP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "if2ip.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "socks.h"
+#include "smtp.h"
+
+#include "strtoofft.h"
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "select.h"
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "curl_gethostname.h"
+#include "curl_sasl.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Local API functions */
+static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done);
+static CURLcode smtp_do(struct connectdata *conn, bool *done);
+static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
+ bool premature);
+static CURLcode smtp_connect(struct connectdata *conn, bool *done);
+static CURLcode smtp_disconnect(struct connectdata *conn, bool dead);
+static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done);
+static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
+static CURLcode smtp_setup_connection(struct connectdata *conn);
+static CURLcode smtp_parse_url_options(struct connectdata *conn);
+static CURLcode smtp_parse_url_path(struct connectdata *conn);
+static CURLcode smtp_parse_custom_request(struct connectdata *conn);
+static CURLcode smtp_calc_sasl_details(struct connectdata *conn,
+ const char **mech,
+ char **initresp, size_t *len,
+ smtpstate *state1, smtpstate *state2);
+
+/*
+ * SMTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_smtp = {
+ "SMTP", /* scheme */
+ smtp_setup_connection, /* setup_connection */
+ smtp_do, /* do_it */
+ smtp_done, /* done */
+ ZERO_NULL, /* do_more */
+ smtp_connect, /* connect_it */
+ smtp_multi_statemach, /* connecting */
+ smtp_doing, /* doing */
+ smtp_getsock, /* proto_getsock */
+ smtp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ smtp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMTP, /* defport */
+ CURLPROTO_SMTP, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * SMTPS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_smtps = {
+ "SMTPS", /* scheme */
+ smtp_setup_connection, /* setup_connection */
+ smtp_do, /* do_it */
+ smtp_done, /* done */
+ ZERO_NULL, /* do_more */
+ smtp_connect, /* connect_it */
+ smtp_multi_statemach, /* connecting */
+ smtp_doing, /* doing */
+ smtp_getsock, /* proto_getsock */
+ smtp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ smtp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMTPS, /* defport */
+ CURLPROTO_SMTPS, /* protocol */
+ PROTOPT_CLOSEACTION | PROTOPT_SSL
+ | PROTOPT_NOURLQUERY /* flags */
+};
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * HTTP-proxyed SMTP protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_smtp_proxy = {
+ "SMTP", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMTP, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+#ifdef USE_SSL
+/*
+ * HTTP-proxyed SMTPS protocol handler.
+ */
+
+static const struct Curl_handler Curl_handler_smtps_proxy = {
+ "SMTPS", /* scheme */
+ Curl_http_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SMTPS, /* defport */
+ CURLPROTO_HTTP, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+#endif
+#endif
+
+#ifdef USE_SSL
+static void smtp_to_smtps(struct connectdata *conn)
+{
+ conn->handler = &Curl_handler_smtps;
+}
+#else
+#define smtp_to_smtps(x) Curl_nop_stmt
+#endif
+
+/***********************************************************************
+ *
+ * smtp_endofresp()
+ *
+ * Checks for an ending SMTP status code at the start of the given string, but
+ * also detects various capabilities from the EHLO response including the
+ * supported authentication mechanisms.
+ */
+static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
+ int *resp)
+{
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ bool result = FALSE;
+
+ /* Nothing for us */
+ if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
+ return FALSE;
+
+ /* Do we have a command response? This should be the response code followed
+ by a space and optionally some text as per RFC-5321 and as outlined in
+ Section 4. Examples of RFC-4954 but some e-mail servers ignore this and
+ only send the response code instead as per Section 4.2. */
+ if(line[3] == ' ' || len == 5) {
+ result = TRUE;
+ *resp = curlx_sltosi(strtol(line, NULL, 10));
+
+ /* Make sure real server never sends internal value */
+ if(*resp == 1)
+ *resp = 0;
+ }
+ /* Do we have a multiline (continuation) response? */
+ else if(line[3] == '-' &&
+ (smtpc->state == SMTP_EHLO || smtpc->state == SMTP_COMMAND)) {
+ result = TRUE;
+ *resp = 1; /* Internal response code */
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_get_message()
+ *
+ * Gets the authentication message from the response buffer.
+ */
+static void smtp_get_message(char *buffer, char** outptr)
+{
+ size_t len = 0;
+ char* message = NULL;
+
+ /* Find the start of the message */
+ for(message = buffer + 4; *message == ' ' || *message == '\t'; message++)
+ ;
+
+ /* Find the end of the message */
+ for(len = strlen(message); len--;)
+ if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+ message[len] != '\t')
+ break;
+
+ /* Terminate the message */
+ if(++len) {
+ message[len] = '\0';
+ }
+
+ *outptr = message;
+}
+
+/***********************************************************************
+ *
+ * state()
+ *
+ * This is the ONLY way to change SMTP state!
+ */
+static void state(struct connectdata *conn, smtpstate newstate)
+{
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[] = {
+ "STOP",
+ "SERVERGREET",
+ "EHLO",
+ "HELO",
+ "STARTTLS",
+ "UPGRADETLS",
+ "AUTH_PLAIN",
+ "AUTH_LOGIN",
+ "AUTH_LOGIN_PASSWD",
+ "AUTH_CRAMMD5",
+ "AUTH_DIGESTMD5",
+ "AUTH_DIGESTMD5_RESP",
+ "AUTH_NTLM",
+ "AUTH_NTLM_TYPE2MSG",
+ "AUTH_GSSAPI",
+ "AUTH_GSSAPI_TOKEN",
+ "AUTH_GSSAPI_NO_DATA",
+ "AUTH_XOAUTH2",
+ "AUTH_CANCEL",
+ "AUTH_FINAL",
+ "COMMAND",
+ "MAIL",
+ "RCPT",
+ "DATA",
+ "POSTDATA",
+ "QUIT",
+ /* LAST */
+ };
+
+ if(smtpc->state != newstate)
+ infof(conn->data, "SMTP %p state change from %s to %s\n",
+ (void *)smtpc, names[smtpc->state], names[newstate]);
+#endif
+
+ smtpc->state = newstate;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_ehlo()
+ *
+ * Sends the EHLO command to not only initialise communication with the ESMTP
+ * server but to also obtain a list of server side supported capabilities.
+ */
+static CURLcode smtp_perform_ehlo(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ smtpc->authmechs = 0; /* No known authentication mechanisms yet */
+ smtpc->authused = 0; /* Clear the authentication mechanism used
+ for esmtp connections */
+ smtpc->tls_supported = FALSE; /* Clear the TLS capability */
+ smtpc->auth_supported = FALSE; /* Clear the AUTH capability */
+
+ /* Send the EHLO command */
+ result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain);
+
+ if(!result)
+ state(conn, SMTP_EHLO);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_helo()
+ *
+ * Sends the HELO command to initialise communication with the SMTP server.
+ */
+static CURLcode smtp_perform_helo(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ smtpc->authused = 0; /* No authentication mechanism used in smtp
+ connections */
+
+ /* Send the HELO command */
+ result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain);
+
+ if(!result)
+ state(conn, SMTP_HELO);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_starttls()
+ *
+ * Sends the STLS command to start the upgrade to TLS.
+ */
+static CURLcode smtp_perform_starttls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the STARTTLS command */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS");
+
+ if(!result)
+ state(conn, SMTP_STARTTLS);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_upgrade_tls()
+ *
+ * Performs the upgrade to TLS.
+ */
+static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ /* Start the SSL connection */
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone);
+
+ if(!result) {
+ if(smtpc->state != SMTP_UPGRADETLS)
+ state(conn, SMTP_UPGRADETLS);
+
+ if(smtpc->ssldone) {
+ smtp_to_smtps(conn);
+ result = smtp_perform_ehlo(conn);
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_auth()
+ *
+ * Sends an AUTH command allowing the client to login with the given SASL
+ * authentication mechanism.
+ */
+static CURLcode smtp_perform_auth(struct connectdata *conn,
+ const char *mech,
+ const char *initresp, size_t len,
+ smtpstate state1, smtpstate state2)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ if(initresp && 8 + strlen(mech) + len <= 512) { /* AUTH <mech> ...<crlf> */
+ /* Send the AUTH command with the initial response */
+ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
+
+ if(!result)
+ state(conn, state2);
+ }
+ else {
+ /* Send the AUTH command */
+ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
+
+ if(!result)
+ state(conn, state1);
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_authentication()
+ *
+ * Initiates the authentication sequence, with the appropriate SASL
+ * authentication mechanism.
+ */
+static CURLcode smtp_perform_authentication(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ const char *mech = NULL;
+ char *initresp = NULL;
+ size_t len = 0;
+ smtpstate state1 = SMTP_STOP;
+ smtpstate state2 = SMTP_STOP;
+
+ /* Check we have a username and password to authenticate with, and the
+ server supports authentiation, and end the connect phase if not */
+ if(!conn->bits.user_passwd || !smtpc->auth_supported) {
+ state(conn, SMTP_STOP);
+
+ return result;
+ }
+
+ /* Calculate the SASL login details */
+ result = smtp_calc_sasl_details(conn, &mech, &initresp, &len, &state1,
+ &state2);
+
+ if(!result) {
+ if(mech) {
+ /* Perform SASL based authentication */
+ result = smtp_perform_auth(conn, mech, initresp, len, state1, state2);
+
+ Curl_safefree(initresp);
+ }
+ else {
+ /* Other mechanisms not supported */
+ infof(conn->data, "No known authentication mechanisms supported!\n");
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_command()
+ *
+ * Sends a SMTP based command.
+ */
+static CURLcode smtp_perform_command(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ /* Send the command */
+ if(smtp->rcpt)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s",
+ smtp->custom && smtp->custom[0] != '\0' ?
+ smtp->custom : "VRFY",
+ smtp->rcpt->data);
+ else
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s",
+ smtp->custom && smtp->custom[0] != '\0' ?
+ smtp->custom : "HELP");
+
+ if(!result)
+ state(conn, SMTP_COMMAND);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_mail()
+ *
+ * Sends an MAIL command to initiate the upload of a message.
+ */
+static CURLcode smtp_perform_mail(struct connectdata *conn)
+{
+ char *from = NULL;
+ char *auth = NULL;
+ char *size = NULL;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ /* Calculate the FROM parameter */
+ if(!data->set.str[STRING_MAIL_FROM])
+ /* Null reverse-path, RFC-5321, sect. 3.6.3 */
+ from = strdup("<>");
+ else if(data->set.str[STRING_MAIL_FROM][0] == '<')
+ from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
+ else
+ from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);
+
+ if(!from)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Calculate the optional AUTH parameter */
+ if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.authused) {
+ if(data->set.str[STRING_MAIL_AUTH][0] != '\0')
+ auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]);
+ else
+ /* Empty AUTH, RFC-2554, sect. 5 */
+ auth = strdup("<>");
+
+ if(!auth) {
+ Curl_safefree(from);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Calculate the optional SIZE parameter */
+ if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) {
+ size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
+
+ if(!size) {
+ Curl_safefree(from);
+ Curl_safefree(auth);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Send the MAIL command */
+ if(!auth && !size)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ "MAIL FROM:%s", from);
+ else if(auth && !size)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ "MAIL FROM:%s AUTH=%s", from, auth);
+ else if(auth && size)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size);
+ else
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ "MAIL FROM:%s SIZE=%s", from, size);
+
+ Curl_safefree(from);
+ Curl_safefree(auth);
+ Curl_safefree(size);
+
+ if(!result)
+ state(conn, SMTP_MAIL);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_rcpt_to()
+ *
+ * Sends a RCPT TO command for a given recipient as part of the message upload
+ * process.
+ */
+static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ /* Send the RCPT TO command */
+ if(smtp->rcpt->data[0] == '<')
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
+ smtp->rcpt->data);
+ else
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>",
+ smtp->rcpt->data);
+ if(!result)
+ state(conn, SMTP_RCPT);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform_quit()
+ *
+ * Performs the quit action prior to sclose() being called.
+ */
+static CURLcode smtp_perform_quit(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+ /* Send the QUIT command */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT");
+
+ if(!result)
+ state(conn, SMTP_QUIT);
+
+ return result;
+}
+
+/* For the initial server greeting */
+static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2) {
+ failf(data, "Got unexpected smtp-server response: %d", smtpcode);
+ result = CURLE_FTP_WEIRD_SERVER_REPLY;
+ }
+ else
+ result = smtp_perform_ehlo(conn);
+
+ return result;
+}
+
+/* For STARTTLS responses */
+static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 220) {
+ if(data->set.use_ssl != CURLUSESSL_TRY) {
+ failf(data, "STARTTLS denied. %c", smtpcode);
+ result = CURLE_USE_SSL_FAILED;
+ }
+ else
+ result = smtp_perform_authentication(conn);
+ }
+ else
+ result = smtp_perform_upgrade_tls(conn);
+
+ return result;
+}
+
+/* For EHLO responses */
+static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ const char *line = data->state.buffer;
+ size_t len = strlen(line);
+ size_t wordlen;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2 && smtpcode != 1) {
+ if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use)
+ result = smtp_perform_helo(conn);
+ else {
+ failf(data, "Remote access denied: %d", smtpcode);
+ result = CURLE_REMOTE_ACCESS_DENIED;
+ }
+ }
+ else {
+ line += 4;
+ len -= 4;
+
+ /* Does the server support the STARTTLS capability? */
+ if(len >= 8 && !memcmp(line, "STARTTLS", 8))
+ smtpc->tls_supported = TRUE;
+
+ /* Does the server support the SIZE capability? */
+ else if(len >= 4 && !memcmp(line, "SIZE", 4))
+ smtpc->size_supported = TRUE;
+
+ /* Does the server support authentication? */
+ else if(len >= 5 && !memcmp(line, "AUTH ", 5)) {
+ smtpc->auth_supported = TRUE;
+
+ /* Advance past the AUTH keyword */
+ line += 5;
+ len -= 5;
+
+ /* Loop through the data line */
+ for(;;) {
+ while(len &&
+ (*line == ' ' || *line == '\t' ||
+ *line == '\r' || *line == '\n')) {
+
+ line++;
+ len--;
+ }
+
+ if(!len)
+ break;
+
+ /* Extract the word */
+ for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
+ line[wordlen] != '\t' && line[wordlen] != '\r' &&
+ line[wordlen] != '\n';)
+ wordlen++;
+
+ /* Test the word for a matching authentication mechanism */
+ if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
+ smtpc->authmechs |= SASL_MECH_LOGIN;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
+ smtpc->authmechs |= SASL_MECH_PLAIN;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
+ smtpc->authmechs |= SASL_MECH_CRAM_MD5;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
+ smtpc->authmechs |= SASL_MECH_DIGEST_MD5;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
+ smtpc->authmechs |= SASL_MECH_GSSAPI;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
+ smtpc->authmechs |= SASL_MECH_EXTERNAL;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
+ smtpc->authmechs |= SASL_MECH_NTLM;
+ else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
+ smtpc->authmechs |= SASL_MECH_XOAUTH2;
+
+ line += wordlen;
+ len -= wordlen;
+ }
+ }
+
+ if(smtpcode != 1) {
+ if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* We don't have a SSL/TLS connection yet, but SSL is requested */
+ if(smtpc->tls_supported)
+ /* Switch to TLS connection now */
+ result = smtp_perform_starttls(conn);
+ else if(data->set.use_ssl == CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = smtp_perform_authentication(conn);
+ else {
+ failf(data, "STARTTLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
+ }
+ else
+ result = smtp_perform_authentication(conn);
+ }
+ }
+
+ return result;
+}
+
+/* For HELO responses */
+static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2) {
+ failf(data, "Remote access denied: %d", smtpcode);
+ result = CURLE_REMOTE_ACCESS_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, SMTP_STOP);
+
+ return result;
+}
+
+/* For AUTH PLAIN (without initial response) responses */
+static CURLcode smtp_state_auth_plain_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *plainauth = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the authorisation message */
+ result = Curl_sasl_create_plain_message(conn->data, conn->user,
+ conn->passwd, &plainauth, &len);
+ if(!result && plainauth) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
+
+ if(!result)
+ state(conn, SMTP_AUTH_FINAL);
+ }
+ }
+
+ Curl_safefree(plainauth);
+
+ return result;
+}
+
+/* For AUTH LOGIN (without initial response) responses */
+static CURLcode smtp_state_auth_login_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *authuser = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the user message */
+ result = Curl_sasl_create_login_message(conn->data, conn->user,
+ &authuser, &len);
+ if(!result && authuser) {
+ /* Send the user */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
+
+ if(!result)
+ state(conn, SMTP_AUTH_LOGIN_PASSWD);
+ }
+ }
+
+ Curl_safefree(authuser);
+
+ return result;
+}
+
+/* For AUTH LOGIN user entry responses */
+static CURLcode smtp_state_auth_login_password_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *authpasswd = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the password message */
+ result = Curl_sasl_create_login_message(conn->data, conn->passwd,
+ &authpasswd, &len);
+ if(!result && authpasswd) {
+ /* Send the password */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
+
+ if(!result)
+ state(conn, SMTP_AUTH_FINAL);
+ }
+ }
+
+ Curl_safefree(authpasswd);
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+/* For AUTH CRAM-MD5 responses */
+static CURLcode smtp_state_auth_cram_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlg = NULL;
+ char *chlg64 = NULL;
+ char *rplyb64 = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Get the challenge message */
+ smtp_get_message(data->state.buffer, &chlg64);
+
+ /* Decode the challenge message */
+ result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
+ if(result) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*");
+
+ if(!result)
+ state(conn, SMTP_AUTH_CANCEL);
+ }
+ else {
+ /* Create the response message */
+ result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user,
+ conn->passwd, &rplyb64, &len);
+ if(!result && rplyb64) {
+ /* Send the response */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
+
+ if(!result)
+ state(conn, SMTP_AUTH_FINAL);
+ }
+ }
+
+ Curl_safefree(chlg);
+ Curl_safefree(rplyb64);
+
+ return result;
+}
+
+/* For AUTH DIGEST-MD5 challenge responses */
+static CURLcode smtp_state_auth_digest_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlg64 = NULL;
+ char *rplyb64 = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Get the challenge message */
+ smtp_get_message(data->state.buffer, &chlg64);
+
+ /* Create the response message */
+ result = Curl_sasl_create_digest_md5_message(data, chlg64,
+ conn->user, conn->passwd,
+ "smtp", &rplyb64, &len);
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*");
+
+ if(!result)
+ state(conn, SMTP_AUTH_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
+
+ if(!result)
+ state(conn, SMTP_AUTH_DIGESTMD5_RESP);
+ }
+
+ Curl_safefree(rplyb64);
+
+ return result;
+}
+
+/* For AUTH DIGEST-MD5 challenge-response responses */
+static CURLcode smtp_state_auth_digest_resp_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Authentication failed: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Send an empty response */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "");
+
+ if(!result)
+ state(conn, SMTP_AUTH_FINAL);
+ }
+
+ return result;
+}
+
+#endif
+
+#ifdef USE_NTLM
+/* For AUTH NTLM (without initial response) responses */
+static CURLcode smtp_state_auth_ntlm_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *type1msg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the type-1 message */
+ result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
+ &conn->ntlm,
+ &type1msg, &len);
+ if(!result && type1msg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type1msg);
+
+ if(!result)
+ state(conn, SMTP_AUTH_NTLM_TYPE2MSG);
+ }
+ }
+
+ Curl_safefree(type1msg);
+
+ return result;
+}
+
+/* For NTLM type-2 responses (sent in reponse to our type-1 message) */
+static CURLcode smtp_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *type2msg = NULL;
+ char *type3msg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the type-2 message */
+ smtp_get_message(data->state.buffer, &type2msg);
+
+ /* Decode the type-2 message */
+ result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
+ if(result) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*");
+
+ if(!result)
+ state(conn, SMTP_AUTH_CANCEL);
+ }
+ else {
+ /* Create the type-3 message */
+ result = Curl_sasl_create_ntlm_type3_message(data, conn->user,
+ conn->passwd, &conn->ntlm,
+ &type3msg, &len);
+ if(!result && type3msg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type3msg);
+
+ if(!result)
+ state(conn, SMTP_AUTH_FINAL);
+ }
+ }
+ }
+
+ Curl_safefree(type3msg);
+
+ return result;
+}
+#endif
+
+#if defined(USE_WINDOWS_SSPI)
+/* For AUTH GSSAPI (without initial response) responses */
+static CURLcode smtp_state_auth_gssapi_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ char *respmsg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the initial response message */
+ result = Curl_sasl_create_gssapi_user_message(data, conn->user,
+ conn->passwd, "smtp",
+ smtpc->mutual_auth, NULL,
+ &conn->krb5,
+ &respmsg, &len);
+ if(!result && respmsg) {
+ /* Send the message */
+ result = Curl_pp_sendf(&smtpc->pp, "%s", respmsg);
+
+ if(!result)
+ state(conn, SMTP_AUTH_GSSAPI_TOKEN);
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+
+/* For AUTH GSSAPI user token responses */
+static CURLcode smtp_state_auth_gssapi_token_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ char *chlgmsg = NULL;
+ char *respmsg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the challenge message */
+ smtp_get_message(data->state.buffer, &chlgmsg);
+
+ if(smtpc->mutual_auth)
+ /* Decode the user token challenge and create the optional response
+ message */
+ result = Curl_sasl_create_gssapi_user_message(data, NULL, NULL, NULL,
+ smtpc->mutual_auth,
+ chlgmsg, &conn->krb5,
+ &respmsg, &len);
+ else
+ /* Decode the security challenge and create the response message */
+ result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
+ &conn->krb5,
+ &respmsg, &len);
+
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&smtpc->pp, "%s", "*");
+
+ if(!result)
+ state(conn, SMTP_AUTH_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ if(respmsg)
+ result = Curl_pp_sendf(&smtpc->pp, "%s", respmsg);
+ else
+ result = Curl_pp_sendf(&smtpc->pp, "%s", "");
+
+ if(!result)
+ state(conn, (smtpc->mutual_auth ? SMTP_AUTH_GSSAPI_NO_DATA :
+ SMTP_AUTH_FINAL));
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+
+/* For AUTH GSSAPI no data responses */
+static CURLcode smtp_state_auth_gssapi_no_data_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ char *chlgmsg = NULL;
+ char *respmsg = NULL;
+ size_t len = 0;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Get the challenge message */
+ smtp_get_message(data->state.buffer, &chlgmsg);
+
+ /* Decode the security challenge and create the response message */
+ result = Curl_sasl_create_gssapi_security_message(data, chlgmsg,
+ &conn->krb5,
+ &respmsg, &len);
+ if(result) {
+ if(result == CURLE_BAD_CONTENT_ENCODING) {
+ /* Send the cancellation */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*");
+
+ if(!result)
+ state(conn, SMTP_AUTH_CANCEL);
+ }
+ }
+ else {
+ /* Send the response */
+ if(respmsg) {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", respmsg);
+
+ if(!result)
+ state(conn, SMTP_AUTH_FINAL);
+ }
+ }
+ }
+
+ Curl_safefree(respmsg);
+
+ return result;
+}
+#endif
+
+/* For AUTH XOAUTH2 (without initial response) responses */
+static CURLcode smtp_state_auth_xoauth2_resp(struct connectdata *conn,
+ int smtpcode, smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t len = 0;
+ char *xoauth = NULL;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ /* Create the authorisation message */
+ result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
+ conn->xoauth2_bearer,
+ &xoauth, &len);
+ if(!result && xoauth) {
+ /* Send the message */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", xoauth);
+
+ if(!result)
+ state(conn, SMTP_AUTH_FINAL);
+ }
+ }
+
+ Curl_safefree(xoauth);
+
+ return result;
+}
+
+/* For AUTH cancellation responses */
+static CURLcode smtp_state_auth_cancel_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ const char *mech = NULL;
+ char *initresp = NULL;
+ size_t len = 0;
+ smtpstate state1 = SMTP_STOP;
+ smtpstate state2 = SMTP_STOP;
+
+ (void)smtpcode;
+ (void)instate; /* no use for this yet */
+
+ /* Remove the offending mechanism from the supported list */
+ smtpc->authmechs ^= smtpc->authused;
+
+ /* Calculate alternative SASL login details */
+ result = smtp_calc_sasl_details(conn, &mech, &initresp, &len, &state1,
+ &state2);
+
+ if(!result) {
+ /* Do we have any mechanisms left? */
+ if(mech) {
+ /* Retry SASL based authentication */
+ result = smtp_perform_auth(conn, mech, initresp, len, state1, state2);
+
+ Curl_safefree(initresp);
+ }
+ else {
+ failf(data, "Authentication cancelled");
+
+ result = CURLE_LOGIN_DENIED;
+ }
+ }
+
+ return result;
+}
+
+/* For final responses in the AUTH sequence */
+static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 235) {
+ failf(data, "Authentication failed: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ /* End of connect phase */
+ state(conn, SMTP_STOP);
+
+ return result;
+}
+
+/* For command responses */
+static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+ char *line = data->state.buffer;
+ size_t len = strlen(line);
+
+ (void)instate; /* no use for this yet */
+
+ if((smtp->rcpt && smtpcode/100 != 2 && smtpcode != 553 && smtpcode != 1) ||
+ (!smtp->rcpt && smtpcode/100 != 2 && smtpcode != 1)) {
+ failf(data, "Command failed: %d", smtpcode);
+ result = CURLE_RECV_ERROR;
+ }
+ else {
+ /* Temporarily add the LF character back and send as body to the client */
+ if(!data->set.opt_no_body) {
+ line[len] = '\n';
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ line[len] = '\0';
+ }
+
+ if(smtpcode != 1) {
+ if(smtp->rcpt) {
+ smtp->rcpt = smtp->rcpt->next;
+
+ if(smtp->rcpt) {
+ /* Send the next command */
+ result = smtp_perform_command(conn);
+ }
+ else
+ /* End of DO phase */
+ state(conn, SMTP_STOP);
+ }
+ else
+ /* End of DO phase */
+ state(conn, SMTP_STOP);
+ }
+ }
+
+ return result;
+}
+
+/* For MAIL responses */
+static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2) {
+ failf(data, "MAIL failed: %d", smtpcode);
+ result = CURLE_SEND_ERROR;
+ }
+ else
+ /* Start the RCPT TO command */
+ result = smtp_perform_rcpt_to(conn);
+
+ return result;
+}
+
+/* For RCPT responses */
+static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode/100 != 2) {
+ failf(data, "RCPT failed: %d", smtpcode);
+ result = CURLE_SEND_ERROR;
+ }
+ else {
+ smtp->rcpt = smtp->rcpt->next;
+
+ if(smtp->rcpt)
+ /* Send the next RCPT TO command */
+ result = smtp_perform_rcpt_to(conn);
+ else {
+ /* Send the DATA command */
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
+
+ if(!result)
+ state(conn, SMTP_DATA);
+ }
+ }
+
+ return result;
+}
+
+/* For DATA response */
+static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 354) {
+ failf(data, "DATA failed: %d", smtpcode);
+ result = CURLE_SEND_ERROR;
+ }
+ else {
+ /* Set the progress upload size */
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+
+ /* SMTP upload */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+
+ /* End of DO phase */
+ state(conn, SMTP_STOP);
+ }
+
+ return result;
+}
+
+/* For POSTDATA responses, which are received after the entire DATA
+ part has been sent to the server */
+static CURLcode smtp_state_postdata_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 250)
+ result = CURLE_RECV_ERROR;
+
+ /* End of DONE phase */
+ state(conn, SMTP_STOP);
+
+ return result;
+}
+
+static CURLcode smtp_statemach_act(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ struct SessionHandle *data = conn->data;
+ int smtpcode;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct pingpong *pp = &smtpc->pp;
+ size_t nread = 0;
+
+ /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
+ if(smtpc->state == SMTP_UPGRADETLS)
+ return smtp_perform_upgrade_tls(conn);
+
+ /* Flush any data that needs to be sent */
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
+
+ do {
+ /* Read the response from the server */
+ result = Curl_pp_readresp(sock, pp, &smtpcode, &nread);
+ if(result)
+ return result;
+
+ /* Store the latest response for later retrieval if necessary */
+ if(smtpc->state != SMTP_QUIT && smtpcode != 1)
+ data->info.httpcode = smtpcode;
+
+ if(!smtpcode)
+ break;
+
+ /* We have now received a full SMTP server response */
+ switch(smtpc->state) {
+ case SMTP_SERVERGREET:
+ result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_EHLO:
+ result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_HELO:
+ result = smtp_state_helo_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_STARTTLS:
+ result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_PLAIN:
+ result = smtp_state_auth_plain_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_LOGIN:
+ result = smtp_state_auth_login_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_LOGIN_PASSWD:
+ result = smtp_state_auth_login_password_resp(conn, smtpcode,
+ smtpc->state);
+ break;
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ case SMTP_AUTH_CRAMMD5:
+ result = smtp_state_auth_cram_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_DIGESTMD5:
+ result = smtp_state_auth_digest_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_DIGESTMD5_RESP:
+ result = smtp_state_auth_digest_resp_resp(conn, smtpcode, smtpc->state);
+ break;
+#endif
+
+#ifdef USE_NTLM
+ case SMTP_AUTH_NTLM:
+ result = smtp_state_auth_ntlm_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_NTLM_TYPE2MSG:
+ result = smtp_state_auth_ntlm_type2msg_resp(conn, smtpcode,
+ smtpc->state);
+ break;
+#endif
+
+#if defined(USE_WINDOWS_SSPI)
+ case SMTP_AUTH_GSSAPI:
+ result = smtp_state_auth_gssapi_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_GSSAPI_TOKEN:
+ result = smtp_state_auth_gssapi_token_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_GSSAPI_NO_DATA:
+ result = smtp_state_auth_gssapi_no_data_resp(conn, smtpcode,
+ smtpc->state);
+ break;
+#endif
+
+ case SMTP_AUTH_XOAUTH2:
+ result = smtp_state_auth_xoauth2_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_CANCEL:
+ result = smtp_state_auth_cancel_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTH_FINAL:
+ result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_COMMAND:
+ result = smtp_state_command_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_MAIL:
+ result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_RCPT:
+ result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_DATA:
+ result = smtp_state_data_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_POSTDATA:
+ result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_QUIT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ state(conn, SMTP_STOP);
+ break;
+ }
+ } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
+
+ return result;
+}
+
+/* Called repeatedly until done from multi.c */
+static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
+ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone);
+ if(result || !smtpc->ssldone)
+ return result;
+ }
+
+ result = Curl_pp_statemach(&smtpc->pp, FALSE);
+ *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;
+
+ return result;
+}
+
+static CURLcode smtp_block_statemach(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ while(smtpc->state != SMTP_STOP && !result)
+ result = Curl_pp_statemach(&smtpc->pp, TRUE);
+
+ return result;
+}
+
+/* Allocate and initialize the SMTP struct for the current SessionHandle if
+ required */
+static CURLcode smtp_init(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp;
+
+ smtp = data->req.protop = calloc(sizeof(struct SMTP), 1);
+ if(!smtp)
+ result = CURLE_OUT_OF_MEMORY;
+
+ return result;
+}
+
+/* For the SMTP "protocol connect" and "doing" phases only */
+static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ return Curl_pp_getsock(&conn->proto.smtpc.pp, socks, numsocks);
+}
+
+/***********************************************************************
+ *
+ * smtp_connect()
+ *
+ * This function should do everything that is to be considered a part of
+ * the connection phase.
+ *
+ * The variable pointed to by 'done' will be TRUE if the protocol-layer
+ * connect phase is done when this function returns, or FALSE if not.
+ */
+static CURLcode smtp_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct pingpong *pp = &smtpc->pp;
+
+ *done = FALSE; /* default to not done yet */
+
+ /* We always support persistent connections in SMTP */
+ connkeep(conn, "SMTP default");
+
+ /* Set the default response time-out */
+ pp->response_time = RESP_TIMEOUT;
+ pp->statemach_act = smtp_statemach_act;
+ pp->endofresp = smtp_endofresp;
+ pp->conn = conn;
+
+ /* Set the default preferred authentication mechanism */
+ smtpc->prefmech = SASL_AUTH_ANY;
+
+ /* Initialise the pingpong layer */
+ Curl_pp_init(pp);
+
+ /* Parse the URL options */
+ result = smtp_parse_url_options(conn);
+ if(result)
+ return result;
+
+ /* Parse the URL path */
+ result = smtp_parse_url_path(conn);
+ if(result)
+ return result;
+
+ /* Start off waiting for the server greeting response */
+ state(conn, SMTP_SERVERGREET);
+
+ result = smtp_multi_statemach(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_done()
+ *
+ * The DONE function. This does what needs to be done after a single DO has
+ * performed.
+ *
+ * Input argument is already checked for validity.
+ */
+static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+ struct pingpong *pp = &conn->proto.smtpc.pp;
+ const char *eob;
+ ssize_t len;
+ ssize_t bytes_written;
+
+ (void)premature;
+
+ if(!smtp || !pp->conn)
+ /* When the easy handle is removed from the multi interface while libcurl
+ is still trying to resolve the host name, the SMTP struct is not yet
+ initialized. However, the removal action calls Curl_done() which in
+ turn calls this function, so we simply return success. */
+ return CURLE_OK;
+
+ if(status) {
+ connclose(conn, "SMTP done with bad status"); /* marked for closure */
+ result = status; /* use the already set error code */
+ }
+ else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) {
+ /* Calculate the EOB taking into account any terminating CRLF from the
+ previous line of the email or the CRLF of the DATA command when there
+ is "no mail data". RFC-5321, sect. 4.1.1.4. */
+ eob = SMTP_EOB;
+ len = SMTP_EOB_LEN;
+ if(smtp->trailing_crlf || !conn->data->state.infilesize) {
+ eob += 2;
+ len -= 2;
+ }
+
+ /* Send the end of block data */
+ result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written);
+ if(result)
+ return result;
+
+ if(bytes_written != len) {
+ /* The whole chunk was not sent so keep it around and adjust the
+ pingpong structure accordingly */
+ pp->sendthis = strdup(eob);
+ pp->sendsize = len;
+ pp->sendleft = len - bytes_written;
+ }
+ else
+ /* Successfully sent so adjust the response timeout relative to now */
+ pp->response = Curl_tvnow();
+
+ state(conn, SMTP_POSTDATA);
+
+ /* Run the state-machine
+
+ TODO: when the multi interface is used, this _really_ should be using
+ the smtp_multi_statemach function but we have no general support for
+ non-blocking DONE operations, not in the multi state machine and with
+ Curl_done() invokes on several places in the code!
+ */
+ result = smtp_block_statemach(conn);
+ }
+
+ /* Cleanup our per-request based variables */
+ Curl_safefree(smtp->custom);
+
+ /* Clear the transfer mode for the next request */
+ smtp->transfer = FTPTRANSFER_BODY;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_perform()
+ *
+ * This is the actual DO function for SMTP. Transfer a mail, send a command
+ * or get some data according to the options previously setup.
+ */
+static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
+ bool *dophase_done)
+{
+ /* This is SMTP and no proxy */
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ if(data->set.opt_no_body) {
+ /* Requested no body means no transfer */
+ smtp->transfer = FTPTRANSFER_INFO;
+ }
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* Store the first recipient (or NULL if not specified) */
+ smtp->rcpt = data->set.mail_rcpt;
+
+ /* Start the first command in the DO phase */
+ if(data->set.upload && data->set.mail_rcpt)
+ /* MAIL transfer */
+ result = smtp_perform_mail(conn);
+ else
+ /* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */
+ result = smtp_perform_command(conn);
+
+ if(result)
+ return result;
+
+ /* Run the state-machine */
+ result = smtp_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_do()
+ *
+ * This function is registered as 'curl_do' function. It decodes the path
+ * parts etc as a wrapper to the actual DO function (smtp_perform).
+ *
+ * The input argument is already checked for validity.
+ */
+static CURLcode smtp_do(struct connectdata *conn, bool *done)
+{
+ CURLcode result = CURLE_OK;
+
+ *done = FALSE; /* default to false */
+
+ /* Parse the custom request */
+ result = smtp_parse_custom_request(conn);
+ if(result)
+ return result;
+
+ result = smtp_regular_transfer(conn, done);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_disconnect()
+ *
+ * Disconnect from an SMTP server. Cleanup protocol-specific per-connection
+ * resources. BLOCKING.
+ */
+static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ /* We cannot send quit unconditionally. If this connection is stale or
+ bad in any way, sending quit and waiting around here will make the
+ disconnect wait in vain and cause more problems than we need to. */
+
+ /* The SMTP session may or may not have been allocated/setup at this
+ point! */
+ if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart)
+ if(!smtp_perform_quit(conn))
+ (void)smtp_block_statemach(conn); /* ignore errors on QUIT */
+
+ /* Disconnect from the server */
+ Curl_pp_disconnect(&smtpc->pp);
+
+ /* Cleanup the SASL module */
+ Curl_sasl_cleanup(conn, smtpc->authused);
+
+ /* Cleanup our connection based variables */
+ Curl_safefree(smtpc->domain);
+
+ return CURLE_OK;
+}
+
+/* Call this when the DO phase has completed */
+static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected)
+{
+ struct SMTP *smtp = conn->data->req.protop;
+
+ (void)connected;
+
+ if(smtp->transfer != FTPTRANSFER_BODY)
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ return CURLE_OK;
+}
+
+/* Called from multi.c while DOing */
+static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result = smtp_multi_statemach(conn, dophase_done);
+
+ if(result)
+ DEBUGF(infof(conn->data, "DO phase failed\n"));
+ else if(*dophase_done) {
+ result = smtp_dophase_done(conn, FALSE /* not connected */);
+
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_regular_transfer()
+ *
+ * The input argument is already checked for validity.
+ *
+ * Performs all commands done before a regular transfer between a local and a
+ * remote host.
+ */
+static CURLcode smtp_regular_transfer(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
+ struct SessionHandle *data = conn->data;
+
+ /* Make sure size is unknown at this point */
+ data->req.size = -1;
+
+ /* Set the progress data */
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ /* Carry out the perform */
+ result = smtp_perform(conn, &connected, dophase_done);
+
+ /* Perform post DO phase operations if necessary */
+ if(!result && *dophase_done)
+ result = smtp_dophase_done(conn, connected);
+
+ return result;
+}
+
+static CURLcode smtp_setup_connection(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode result;
+
+ if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
+ /* Unless we have asked to tunnel SMTP operations through the proxy, we
+ switch and use HTTP operations only */
+#ifndef CURL_DISABLE_HTTP
+ if(conn->handler == &Curl_handler_smtp)
+ conn->handler = &Curl_handler_smtp_proxy;
+ else {
+#ifdef USE_SSL
+ conn->handler = &Curl_handler_smtps_proxy;
+#else
+ failf(data, "SMTPS not supported!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+ /* set it up as a HTTP connection instead */
+ return conn->handler->setup_connection(conn);
+
+#else
+ failf(data, "SMTP over http proxy requires HTTP support built-in!");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ }
+
+ /* Initialise the SMTP layer */
+ result = smtp_init(conn);
+ if(result)
+ return result;
+
+ data->state.path++; /* don't include the initial slash */
+
+ return CURLE_OK;
+}
+
+/***********************************************************************
+ *
+ * smtp_parse_url_options()
+ *
+ * Parse the URL login options.
+ */
+static CURLcode smtp_parse_url_options(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ const char *options = conn->options;
+ const char *ptr = options;
+ bool reset = TRUE;
+
+ while(ptr && *ptr) {
+ const char *key = ptr;
+
+ while(*ptr && *ptr != '=')
+ ptr++;
+
+ if(strnequal(key, "AUTH", 4)) {
+ size_t len = 0;
+ const char *value = ++ptr;
+
+ if(reset) {
+ reset = FALSE;
+ smtpc->prefmech = SASL_AUTH_NONE;
+ }
+
+ while(*ptr && *ptr != ';') {
+ ptr++;
+ len++;
+ }
+
+ if(strnequal(value, "*", len))
+ smtpc->prefmech = SASL_AUTH_ANY;
+ else if(strnequal(value, SASL_MECH_STRING_LOGIN, len))
+ smtpc->prefmech |= SASL_MECH_LOGIN;
+ else if(strnequal(value, SASL_MECH_STRING_PLAIN, len))
+ smtpc->prefmech |= SASL_MECH_PLAIN;
+ else if(strnequal(value, SASL_MECH_STRING_CRAM_MD5, len))
+ smtpc->prefmech |= SASL_MECH_CRAM_MD5;
+ else if(strnequal(value, SASL_MECH_STRING_DIGEST_MD5, len))
+ smtpc->prefmech |= SASL_MECH_DIGEST_MD5;
+ else if(strnequal(value, SASL_MECH_STRING_GSSAPI, len))
+ smtpc->prefmech |= SASL_MECH_GSSAPI;
+ else if(strnequal(value, SASL_MECH_STRING_NTLM, len))
+ smtpc->prefmech |= SASL_MECH_NTLM;
+ else if(strnequal(value, SASL_MECH_STRING_XOAUTH2, len))
+ smtpc->prefmech |= SASL_MECH_XOAUTH2;
+
+ if(*ptr == ';')
+ ptr++;
+ }
+ else
+ result = CURLE_URL_MALFORMAT;
+ }
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_parse_url_path()
+ *
+ * Parse the URL path into separate path components.
+ */
+static CURLcode smtp_parse_url_path(struct connectdata *conn)
+{
+ /* The SMTP struct is already initialised in smtp_connect() */
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ const char *path = data->state.path;
+ char localhost[HOSTNAME_MAX + 1];
+
+ /* Calculate the path if necessary */
+ if(!*path) {
+ if(!Curl_gethostname(localhost, sizeof(localhost)))
+ path = localhost;
+ else
+ path = "localhost";
+ }
+
+ /* URL decode the path and use it as the domain in our EHLO */
+ return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
+}
+
+/***********************************************************************
+ *
+ * smtp_parse_custom_request()
+ *
+ * Parse the custom request.
+ */
+static CURLcode smtp_parse_custom_request(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+ const char *custom = data->set.str[STRING_CUSTOMREQUEST];
+
+ /* URL decode the custom request */
+ if(custom)
+ result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE);
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * smtp_calc_sasl_details()
+ *
+ * Calculate the required login details for SASL authentication.
+ */
+static CURLcode smtp_calc_sasl_details(struct connectdata *conn,
+ const char **mech,
+ char **initresp, size_t *len,
+ smtpstate *state1, smtpstate *state2)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+
+ /* Calculate the supported authentication mechanism, by decreasing order of
+ security, as well as the initial response where appropriate */
+#if defined(USE_WINDOWS_SSPI)
+ if((smtpc->authmechs & SASL_MECH_GSSAPI) &&
+ (smtpc->prefmech & SASL_MECH_GSSAPI)) {
+ smtpc->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
+
+ *mech = SASL_MECH_STRING_GSSAPI;
+ *state1 = SMTP_AUTH_GSSAPI;
+ *state2 = SMTP_AUTH_GSSAPI_TOKEN;
+ smtpc->authused = SASL_MECH_GSSAPI;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_gssapi_user_message(data, conn->user,
+ conn->passwd, "smtp",
+ smtpc->mutual_auth,
+ NULL, &conn->krb5,
+ initresp, len);
+ }
+ else
+#endif
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) &&
+ (smtpc->prefmech & SASL_MECH_DIGEST_MD5)) {
+ *mech = SASL_MECH_STRING_DIGEST_MD5;
+ *state1 = SMTP_AUTH_DIGESTMD5;
+ smtpc->authused = SASL_MECH_DIGEST_MD5;
+ }
+ else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) &&
+ (smtpc->prefmech & SASL_MECH_CRAM_MD5)) {
+ *mech = SASL_MECH_STRING_CRAM_MD5;
+ *state1 = SMTP_AUTH_CRAMMD5;
+ smtpc->authused = SASL_MECH_CRAM_MD5;
+ }
+ else
+#endif
+#ifdef USE_NTLM
+ if((smtpc->authmechs & SASL_MECH_NTLM) &&
+ (smtpc->prefmech & SASL_MECH_NTLM)) {
+ *mech = SASL_MECH_STRING_NTLM;
+ *state1 = SMTP_AUTH_NTLM;
+ *state2 = SMTP_AUTH_NTLM_TYPE2MSG;
+ smtpc->authused = SASL_MECH_NTLM;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
+ &conn->ntlm,
+ initresp, len);
+ }
+ else
+#endif
+ if(((smtpc->authmechs & SASL_MECH_XOAUTH2) &&
+ (smtpc->prefmech & SASL_MECH_XOAUTH2) &&
+ (smtpc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
+ *mech = SASL_MECH_STRING_XOAUTH2;
+ *state1 = SMTP_AUTH_XOAUTH2;
+ *state2 = SMTP_AUTH_FINAL;
+ smtpc->authused = SASL_MECH_XOAUTH2;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_xoauth2_message(data, conn->user,
+ conn->xoauth2_bearer,
+ initresp, len);
+ }
+ else if((smtpc->authmechs & SASL_MECH_LOGIN) &&
+ (smtpc->prefmech & SASL_MECH_LOGIN)) {
+ *mech = SASL_MECH_STRING_LOGIN;
+ *state1 = SMTP_AUTH_LOGIN;
+ *state2 = SMTP_AUTH_LOGIN_PASSWD;
+ smtpc->authused = SASL_MECH_LOGIN;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_login_message(data, conn->user, initresp, len);
+ }
+ else if((smtpc->authmechs & SASL_MECH_PLAIN) &&
+ (smtpc->prefmech & SASL_MECH_PLAIN)) {
+ *mech = SASL_MECH_STRING_PLAIN;
+ *state1 = SMTP_AUTH_PLAIN;
+ *state2 = SMTP_AUTH_FINAL;
+ smtpc->authused = SASL_MECH_PLAIN;
+
+ if(data->set.sasl_ir)
+ result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
+ initresp, len);
+ }
+
+ return result;
+}
+
+CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
+{
+ /* When sending a SMTP payload we must detect CRLF. sequences making sure
+ they are sent as CRLF.. instead, as a . on the beginning of a line will
+ be deleted by the server when not part of an EOB terminator and a
+ genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of
+ data by the server
+ */
+ ssize_t i;
+ ssize_t si;
+ struct SessionHandle *data = conn->data;
+ struct SMTP *smtp = data->req.protop;
+
+ /* Do we need to allocate the scatch buffer? */
+ if(!data->state.scratch) {
+ data->state.scratch = malloc(2 * BUFSIZE);
+
+ if(!data->state.scratch) {
+ failf (data, "Failed to alloc scratch buffer!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* This loop can be improved by some kind of Boyer-Moore style of
+ approach but that is saved for later... */
+ for(i = 0, si = 0; i < nread; i++) {
+ if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) {
+ smtp->eob++;
+
+ /* Is the EOB potentially the terminating CRLF? */
+ if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob)
+ smtp->trailing_crlf = TRUE;
+ else
+ smtp->trailing_crlf = FALSE;
+ }
+ else if(smtp->eob) {
+ /* A previous substring matched so output that first */
+ memcpy(&data->state.scratch[si], SMTP_EOB, smtp->eob);
+ si += smtp->eob;
+
+ /* Then compare the first byte */
+ if(SMTP_EOB[0] == data->req.upload_fromhere[i])
+ smtp->eob = 1;
+ else
+ smtp->eob = 0;
+
+ /* Reset the trailing CRLF flag as there was more data */
+ smtp->trailing_crlf = FALSE;
+ }
+
+ /* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */
+ if(SMTP_EOB_FIND_LEN == smtp->eob) {
+ /* Copy the replacement data to the target buffer */
+ memcpy(&data->state.scratch[si], SMTP_EOB_REPL, SMTP_EOB_REPL_LEN);
+ si += SMTP_EOB_REPL_LEN;
+ smtp->eob = 0;
+ }
+ else if(!smtp->eob)
+ data->state.scratch[si++] = data->req.upload_fromhere[i];
+ }
+
+ if(smtp->eob) {
+ /* A substring matched before processing ended so output that now */
+ memcpy(&data->state.scratch[si], SMTP_EOB, smtp->eob);
+ si += smtp->eob;
+ smtp->eob = 0;
+ }
+
+ if(si != nread) {
+ /* Only use the new buffer if we replaced something */
+ nread = si;
+
+ /* Upload from the new (replaced) buffer instead */
+ data->req.upload_fromhere = data->state.scratch;
+
+ /* Set the new amount too */
+ data->req.upload_present = nread;
+ }
+
+ return CURLE_OK;
+}
+
+#endif /* CURL_DISABLE_SMTP */
diff --git a/external/libcurl_android/jni/libcurl/lib/smtp.h b/external/libcurl_android/jni/libcurl/lib/smtp.h
new file mode 100755
index 00000000..db1b1e67
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/smtp.h
@@ -0,0 +1,106 @@
+#ifndef HEADER_CURL_SMTP_H
+#define HEADER_CURL_SMTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "pingpong.h"
+
+/****************************************************************************
+ * SMTP unique setup
+ ***************************************************************************/
+typedef enum {
+ SMTP_STOP, /* do nothing state, stops the state machine */
+ SMTP_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ SMTP_EHLO,
+ SMTP_HELO,
+ SMTP_STARTTLS,
+ SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ SMTP_AUTH_PLAIN,
+ SMTP_AUTH_LOGIN,
+ SMTP_AUTH_LOGIN_PASSWD,
+ SMTP_AUTH_CRAMMD5,
+ SMTP_AUTH_DIGESTMD5,
+ SMTP_AUTH_DIGESTMD5_RESP,
+ SMTP_AUTH_NTLM,
+ SMTP_AUTH_NTLM_TYPE2MSG,
+ SMTP_AUTH_GSSAPI,
+ SMTP_AUTH_GSSAPI_TOKEN,
+ SMTP_AUTH_GSSAPI_NO_DATA,
+ SMTP_AUTH_XOAUTH2,
+ SMTP_AUTH_CANCEL,
+ SMTP_AUTH_FINAL,
+ SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */
+ SMTP_MAIL, /* MAIL FROM */
+ SMTP_RCPT, /* RCPT TO */
+ SMTP_DATA,
+ SMTP_POSTDATA,
+ SMTP_QUIT,
+ SMTP_LAST /* never used */
+} smtpstate;
+
+/* This SMTP struct is used in the SessionHandle. All SMTP data that is
+ connection-oriented must be in smtp_conn to properly deal with the fact that
+ perhaps the SessionHandle is changed between the times the connection is
+ used. */
+struct SMTP {
+ curl_pp_transfer transfer;
+ char *custom; /* Custom Request */
+ struct curl_slist *rcpt; /* Recipient list */
+ size_t eob; /* Number of bytes of the EOB (End Of Body) that
+ have been received so far */
+ bool trailing_crlf; /* Specifies if the tailing CRLF is present */
+};
+
+/* smtp_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct smtp_conn {
+ struct pingpong pp;
+ smtpstate state; /* Always use smtp.c:state() to change state! */
+ bool ssldone; /* Is connect() over SSL done? */
+ char *domain; /* Client address/name to send in the EHLO */
+ unsigned int authmechs; /* Accepted authentication mechanisms */
+ unsigned int prefmech; /* Preferred authentication mechanism */
+ unsigned int authused; /* Auth mechanism used for the connection */
+ bool tls_supported; /* StartTLS capability supported by server */
+ bool size_supported; /* If server supports SIZE extension according to
+ RFC 1870 */
+ bool auth_supported; /* AUTH capability supported by server */
+ bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
+};
+
+extern const struct Curl_handler Curl_handler_smtp;
+extern const struct Curl_handler Curl_handler_smtps;
+
+/* this is the 5-bytes End-Of-Body marker for SMTP */
+#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a"
+#define SMTP_EOB_LEN 5
+#define SMTP_EOB_FIND_LEN 3
+
+/* if found in data, replace it with this string instead */
+#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
+#define SMTP_EOB_REPL_LEN 4
+
+CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread);
+
+#endif /* HEADER_CURL_SMTP_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/sockaddr.h b/external/libcurl_android/jni/libcurl/lib/sockaddr.h
new file mode 100755
index 00000000..6a2151c9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/sockaddr.h
@@ -0,0 +1,43 @@
+#ifndef HEADER_CURL_SOCKADDR_H
+#define HEADER_CURL_SOCKADDR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+struct Curl_sockaddr_storage {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sa_in;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 sa_in6;
+#endif
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE
+ struct sockaddr_storage sa_stor;
+#else
+ char cbuf[256]; /* this should be big enough to fit a lot */
+#endif
+ } buffer;
+};
+
+#endif /* HEADER_CURL_SOCKADDR_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/socks.c b/external/libcurl_android/jni/libcurl/lib/socks.c
new file mode 100755
index 00000000..028475c9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/socks.c
@@ -0,0 +1,755 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_PROXY)
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "strequal.h"
+#include "select.h"
+#include "connect.h"
+#include "timeval.h"
+#include "socks.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Helper read-from-socket functions. Does the same as Curl_read() but it
+ * blocks until all bytes amount of buffersize will be read. No more, no less.
+ *
+ * This is STUPID BLOCKING behaviour which we frown upon, but right now this
+ * is what we have...
+ */
+int Curl_blockread_all(struct connectdata *conn, /* connection data */
+ curl_socket_t sockfd, /* read from this socket */
+ char *buf, /* store read data here */
+ ssize_t buffersize, /* max amount to read */
+ ssize_t *n) /* amount bytes read */
+{
+ ssize_t nread;
+ ssize_t allread = 0;
+ int result;
+ long timeleft;
+ *n = 0;
+ for(;;) {
+ timeleft = Curl_timeleft(conn->data, NULL, TRUE);
+ if(timeleft < 0) {
+ /* we already got the timeout */
+ result = CURLE_OPERATION_TIMEDOUT;
+ break;
+ }
+ if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, timeleft) <= 0) {
+ result = ~CURLE_OK;
+ break;
+ }
+ result = Curl_read_plain(sockfd, buf, buffersize, &nread);
+ if(CURLE_AGAIN == result)
+ continue;
+ else if(result)
+ break;
+
+ if(buffersize == nread) {
+ allread += nread;
+ *n = allread;
+ result = CURLE_OK;
+ break;
+ }
+ if(!nread) {
+ result = ~CURLE_OK;
+ break;
+ }
+
+ buffersize -= nread;
+ buf += nread;
+ allread += nread;
+ }
+ return result;
+}
+
+/*
+* This function logs in to a SOCKS4 proxy and sends the specifics to the final
+* destination server.
+*
+* Reference :
+* http://socks.permeo.com/protocol/socks4.protocol
+*
+* Note :
+* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
+* Nonsupport "Identification Protocol (RFC1413)"
+*/
+CURLcode Curl_SOCKS4(const char *proxy_name,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct connectdata *conn,
+ bool protocol4a)
+{
+#define SOCKS4REQLEN 262
+ unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
+ id */
+ int result;
+ CURLcode code;
+ curl_socket_t sock = conn->sock[sockindex];
+ struct SessionHandle *data = conn->data;
+
+ if(Curl_timeleft(data, NULL, TRUE) < 0) {
+ /* time-out, bail out, go home */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ curlx_nonblock(sock, FALSE);
+
+ infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
+
+ /*
+ * Compose socks4 request
+ *
+ * Request format
+ *
+ * +----+----+----+----+----+----+----+----+----+----+....+----+
+ * | VN | CD | DSTPORT | DSTIP | USERID |NULL|
+ * +----+----+----+----+----+----+----+----+----+----+....+----+
+ * # of bytes: 1 1 2 4 variable 1
+ */
+
+ socksreq[0] = 4; /* version (SOCKS4) */
+ socksreq[1] = 1; /* connect */
+ socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
+ socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */
+
+ /* DNS resolve only for SOCKS4, not SOCKS4a */
+ if(!protocol4a) {
+ struct Curl_dns_entry *dns;
+ Curl_addrinfo *hp=NULL;
+ int rc;
+
+ rc = Curl_resolv(conn, hostname, remote_port, &dns);
+
+ if(rc == CURLRESOLV_ERROR)
+ return CURLE_COULDNT_RESOLVE_PROXY;
+
+ if(rc == CURLRESOLV_PENDING)
+ /* ignores the return code, but 'dns' remains NULL on failure */
+ (void)Curl_resolver_wait_resolv(conn, &dns);
+
+ /*
+ * We cannot use 'hostent' as a struct that Curl_resolv() returns. It
+ * returns a Curl_addrinfo pointer that may not always look the same.
+ */
+ if(dns)
+ hp=dns->addr;
+ if(hp) {
+ char buf[64];
+ unsigned short ip[4];
+ Curl_printable_address(hp, buf, sizeof(buf));
+
+ if(4 == sscanf( buf, "%hu.%hu.%hu.%hu",
+ &ip[0], &ip[1], &ip[2], &ip[3])) {
+ /* Set DSTIP */
+ socksreq[4] = (unsigned char)ip[0];
+ socksreq[5] = (unsigned char)ip[1];
+ socksreq[6] = (unsigned char)ip[2];
+ socksreq[7] = (unsigned char)ip[3];
+ }
+ else
+ hp = NULL; /* fail! */
+
+ infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf);
+
+ Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+
+ }
+ if(!hp) {
+ failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
+ hostname);
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+ }
+
+ /*
+ * This is currently not supporting "Identification Protocol (RFC1413)".
+ */
+ socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
+ if(proxy_name) {
+ size_t plen = strlen(proxy_name);
+ if(plen >= sizeof(socksreq) - 8) {
+ failf(data, "Too long SOCKS proxy name, can't use!\n");
+ return CURLE_COULDNT_CONNECT;
+ }
+ /* copy the proxy name WITH trailing zero */
+ memcpy(socksreq + 8, proxy_name, plen+1);
+ }
+
+ /*
+ * Make connection
+ */
+ {
+ ssize_t actualread;
+ ssize_t written;
+ ssize_t hostnamelen = 0;
+ int packetsize = 9 +
+ (int)strlen((char*)socksreq + 8); /* size including NUL */
+
+ /* If SOCKS4a, set special invalid IP address 0.0.0.x */
+ if(protocol4a) {
+ socksreq[4] = 0;
+ socksreq[5] = 0;
+ socksreq[6] = 0;
+ socksreq[7] = 1;
+ /* If still enough room in buffer, also append hostname */
+ hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
+ if(packetsize + hostnamelen <= SOCKS4REQLEN)
+ strcpy((char*)socksreq + packetsize, hostname);
+ else
+ hostnamelen = 0; /* Flag: hostname did not fit in buffer */
+ }
+
+ /* Send request */
+ code = Curl_write_plain(conn, sock, (char *)socksreq,
+ packetsize + hostnamelen,
+ &written);
+ if((code != CURLE_OK) || (written != packetsize + hostnamelen)) {
+ failf(data, "Failed to send SOCKS4 connect request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(protocol4a && hostnamelen == 0) {
+ /* SOCKS4a with very long hostname - send that name separately */
+ hostnamelen = (ssize_t)strlen(hostname) + 1;
+ code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen,
+ &written);
+ if((code != CURLE_OK) || (written != hostnamelen)) {
+ failf(data, "Failed to send SOCKS4 connect request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ packetsize = 8; /* receive data size */
+
+ /* Receive response */
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
+ &actualread);
+ if((result != CURLE_OK) || (actualread != packetsize)) {
+ failf(data, "Failed to receive SOCKS4 connect request ack.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /*
+ * Response format
+ *
+ * +----+----+----+----+----+----+----+----+
+ * | VN | CD | DSTPORT | DSTIP |
+ * +----+----+----+----+----+----+----+----+
+ * # of bytes: 1 1 2 4
+ *
+ * VN is the version of the reply code and should be 0. CD is the result
+ * code with one of the following values:
+ *
+ * 90: request granted
+ * 91: request rejected or failed
+ * 92: request rejected because SOCKS server cannot connect to
+ * identd on the client
+ * 93: request rejected because the client program and identd
+ * report different user-ids
+ */
+
+ /* wrong version ? */
+ if(socksreq[0] != 0) {
+ failf(data,
+ "SOCKS4 reply has wrong version, version should be 4.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* Result */
+ switch(socksreq[1]) {
+ case 90:
+ infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":"");
+ break;
+ case 91:
+ failf(data,
+ "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+ ", request rejected or failed.",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ case 92:
+ failf(data,
+ "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+ ", request rejected because SOCKS server cannot connect to "
+ "identd on the client.",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ case 93:
+ failf(data,
+ "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+ ", request rejected because the client program and identd "
+ "report different user-ids.",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ default:
+ failf(data,
+ "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+ ", Unknown.",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ curlx_nonblock(sock, TRUE);
+
+ return CURLE_OK; /* Proxy was successful! */
+}
+
+/*
+ * This function logs in to a SOCKS5 proxy and sends the specifics to the final
+ * destination server.
+ */
+CURLcode Curl_SOCKS5(const char *proxy_name,
+ const char *proxy_password,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct connectdata *conn)
+{
+ /*
+ According to the RFC1928, section "6. Replies". This is what a SOCK5
+ replies:
+
+ +----+-----+-------+------+----------+----------+
+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+ +----+-----+-------+------+----------+----------+
+ | 1 | 1 | X'00' | 1 | Variable | 2 |
+ +----+-----+-------+------+----------+----------+
+
+ Where:
+
+ o VER protocol version: X'05'
+ o REP Reply field:
+ o X'00' succeeded
+ */
+
+ unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
+ ssize_t actualread;
+ ssize_t written;
+ int result;
+ CURLcode code;
+ curl_socket_t sock = conn->sock[sockindex];
+ struct SessionHandle *data = conn->data;
+ long timeout;
+ bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE;
+ const size_t hostname_len = strlen(hostname);
+ ssize_t len = 0;
+
+ /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
+ if(!socks5_resolve_local && hostname_len > 255) {
+ infof(conn->data,"SOCKS5: server resolving disabled for hostnames of "
+ "length > 255 [actual len=%zu]\n", hostname_len);
+ socks5_resolve_local = TRUE;
+ }
+
+ /* get timeout */
+ timeout = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout < 0) {
+ /* time-out, bail out, go home */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ curlx_nonblock(sock, TRUE);
+
+ /* wait until socket gets connected */
+ result = Curl_socket_ready(CURL_SOCKET_BAD, sock, timeout);
+
+ if(-1 == result) {
+ failf(conn->data, "SOCKS5: no connection here");
+ return CURLE_COULDNT_CONNECT;
+ }
+ else if(0 == result) {
+ failf(conn->data, "SOCKS5: connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ if(result & CURL_CSELECT_ERR) {
+ failf(conn->data, "SOCKS5: error occurred during connection");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ socksreq[0] = 5; /* version */
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ socksreq[1] = (char)(proxy_name ? 3 : 2); /* number of methods (below) */
+ socksreq[2] = 0; /* no authentication */
+ socksreq[3] = 1; /* GSS-API */
+ socksreq[4] = 2; /* username/password */
+#else
+ socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
+ socksreq[2] = 0; /* no authentication */
+ socksreq[3] = 2; /* username/password */
+#endif
+
+ curlx_nonblock(sock, FALSE);
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
+ &written);
+ if((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) {
+ failf(data, "Unable to send initial SOCKS5 request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ curlx_nonblock(sock, TRUE);
+
+ result = Curl_socket_ready(sock, CURL_SOCKET_BAD, timeout);
+
+ if(-1 == result) {
+ failf(conn->data, "SOCKS5 nothing to read");
+ return CURLE_COULDNT_CONNECT;
+ }
+ else if(0 == result) {
+ failf(conn->data, "SOCKS5 read timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ if(result & CURL_CSELECT_ERR) {
+ failf(conn->data, "SOCKS5 read error occurred");
+ return CURLE_RECV_ERROR;
+ }
+
+ curlx_nonblock(sock, FALSE);
+
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+ if((result != CURLE_OK) || (actualread != 2)) {
+ failf(data, "Unable to receive initial SOCKS5 response.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[0] != 5) {
+ failf(data, "Received invalid version in initial SOCKS5 response.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(socksreq[1] == 0) {
+ /* Nothing to do, no authentication needed */
+ ;
+ }
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ else if(socksreq[1] == 1) {
+ code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
+ if(code != CURLE_OK) {
+ failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+#endif
+ else if(socksreq[1] == 2) {
+ /* Needs user name and password */
+ size_t proxy_name_len, proxy_password_len;
+ if(proxy_name && proxy_password) {
+ proxy_name_len = strlen(proxy_name);
+ proxy_password_len = strlen(proxy_password);
+ }
+ else {
+ proxy_name_len = 0;
+ proxy_password_len = 0;
+ }
+
+ /* username/password request looks like
+ * +----+------+----------+------+----------+
+ * |VER | ULEN | UNAME | PLEN | PASSWD |
+ * +----+------+----------+------+----------+
+ * | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+ * +----+------+----------+------+----------+
+ */
+ len = 0;
+ socksreq[len++] = 1; /* username/pw subnegotiation version */
+ socksreq[len++] = (unsigned char) proxy_name_len;
+ if(proxy_name && proxy_name_len)
+ memcpy(socksreq + len, proxy_name, proxy_name_len);
+ len += proxy_name_len;
+ socksreq[len++] = (unsigned char) proxy_password_len;
+ if(proxy_password && proxy_password_len)
+ memcpy(socksreq + len, proxy_password, proxy_password_len);
+ len += proxy_password_len;
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
+ if((code != CURLE_OK) || (len != written)) {
+ failf(data, "Failed to send SOCKS5 sub-negotiation request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+ if((result != CURLE_OK) || (actualread != 2)) {
+ failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] != 0) { /* status */
+ failf(data, "User was rejected by the SOCKS5 server (%d %d).",
+ socksreq[0], socksreq[1]);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* Everything is good so far, user was authenticated! */
+ }
+ else {
+ /* error */
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(socksreq[1] == 255) {
+#else
+ if(socksreq[1] == 1) {
+ failf(data,
+ "SOCKS5 GSSAPI per-message authentication is not supported.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ else if(socksreq[1] == 255) {
+#endif
+ if(!proxy_name || !*proxy_name) {
+ failf(data,
+ "No authentication method was acceptable. (It is quite likely"
+ " that the SOCKS5 server wanted a username/password, since none"
+ " was supplied to the server on this connection.)");
+ }
+ else {
+ failf(data, "No authentication method was acceptable.");
+ }
+ return CURLE_COULDNT_CONNECT;
+ }
+ else {
+ failf(data,
+ "Undocumented SOCKS5 mode attempted to be used by server.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+
+ /* Authentication is complete, now specify destination to the proxy */
+ len = 0;
+ socksreq[len++] = 5; /* version (SOCKS5) */
+ socksreq[len++] = 1; /* connect */
+ socksreq[len++] = 0; /* must be zero */
+
+ if(!socks5_resolve_local) {
+ socksreq[len++] = 3; /* ATYP: domain name = 3 */
+ socksreq[len++] = (char) hostname_len; /* address length */
+ memcpy(&socksreq[len], hostname, hostname_len); /* address str w/o NULL */
+ len += hostname_len;
+ }
+ else {
+ struct Curl_dns_entry *dns;
+ Curl_addrinfo *hp = NULL;
+ int rc = Curl_resolv(conn, hostname, remote_port, &dns);
+
+ if(rc == CURLRESOLV_ERROR)
+ return CURLE_COULDNT_RESOLVE_HOST;
+
+ if(rc == CURLRESOLV_PENDING) {
+ /* this requires that we're in "wait for resolve" state */
+ code = Curl_resolver_wait_resolv(conn, &dns);
+ if(code != CURLE_OK)
+ return code;
+ }
+
+ /*
+ * We cannot use 'hostent' as a struct that Curl_resolv() returns. It
+ * returns a Curl_addrinfo pointer that may not always look the same.
+ */
+ if(dns)
+ hp=dns->addr;
+ if(hp) {
+ struct sockaddr_in *saddr_in;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *saddr_in6;
+#endif
+ int i;
+
+ if(hp->ai_family == AF_INET) {
+ socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
+
+ saddr_in = (struct sockaddr_in*)hp->ai_addr;
+ for(i = 0; i < 4; i++) {
+ socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i];
+ infof(data, "%d\n", socksreq[len-1]);
+ }
+ }
+#ifdef ENABLE_IPV6
+ else if(hp->ai_family == AF_INET6) {
+ socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
+
+ saddr_in6 = (struct sockaddr_in6*)hp->ai_addr;
+ for(i = 0; i < 16; i++) {
+ socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i];
+ }
+ }
+#endif
+ else
+ hp = NULL; /* fail! */
+
+ Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+ }
+ if(!hp) {
+ failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
+ hostname);
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+ }
+
+ socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
+ socksreq[len++] = (unsigned char)(remote_port & 0xff); /* PORT LSB */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(conn->socks5_gssapi_enctype) {
+ failf(data, "SOCKS5 GSS-API protection not yet implemented.");
+ }
+ else
+#endif
+ code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
+
+ if((code != CURLE_OK) || (len != written)) {
+ failf(data, "Failed to send SOCKS5 connect request.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ len = 10; /* minimum packet size is 10 */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(conn->socks5_gssapi_enctype) {
+ failf(data, "SOCKS5 GSS-API protection not yet implemented.");
+ }
+ else
+#endif
+ result = Curl_blockread_all(conn, sock, (char *)socksreq,
+ len, &actualread);
+
+ if((result != CURLE_OK) || (len != actualread)) {
+ failf(data, "Failed to receive SOCKS5 connect request ack.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[0] != 5) { /* version */
+ failf(data,
+ "SOCKS5 reply has wrong version, version should be 5.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+ if(socksreq[3] == 1) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ }
+ else if(socksreq[3] == 3) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %s:%d. (%d)",
+ hostname,
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ }
+ else if(socksreq[3] == 4) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:"
+ "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ (unsigned char)socksreq[8], (unsigned char)socksreq[9],
+ (unsigned char)socksreq[10], (unsigned char)socksreq[11],
+ (unsigned char)socksreq[12], (unsigned char)socksreq[13],
+ (unsigned char)socksreq[14], (unsigned char)socksreq[15],
+ (unsigned char)socksreq[16], (unsigned char)socksreq[17],
+ (unsigned char)socksreq[18], (unsigned char)socksreq[19],
+ ((socksreq[8] << 8) | socksreq[9]),
+ socksreq[1]);
+ }
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* Fix: in general, returned BND.ADDR is variable length parameter by RFC
+ 1928, so the reply packet should be read until the end to avoid errors at
+ subsequent protocol level.
+
+ +----+-----+-------+------+----------+----------+
+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+ +----+-----+-------+------+----------+----------+
+ | 1 | 1 | X'00' | 1 | Variable | 2 |
+ +----+-----+-------+------+----------+----------+
+
+ ATYP:
+ o IP v4 address: X'01', BND.ADDR = 4 byte
+ o domain name: X'03', BND.ADDR = [ 1 byte length, string ]
+ o IP v6 address: X'04', BND.ADDR = 16 byte
+ */
+
+ /* Calculate real packet size */
+ if(socksreq[3] == 3) {
+ /* domain name */
+ int addrlen = (int) socksreq[4];
+ len = 5 + addrlen + 2;
+ }
+ else if(socksreq[3] == 4) {
+ /* IPv6 */
+ len = 4 + 16 + 2;
+ }
+
+ /* At this point we already read first 10 bytes */
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ if(!conn->socks5_gssapi_enctype) {
+ /* decrypt_gssapi_blockread already read the whole packet */
+#endif
+ if(len > 10) {
+ len -= 10;
+ result = Curl_blockread_all(conn, sock, (char *)&socksreq[10],
+ len, &actualread);
+ if((result != CURLE_OK) || (len != actualread)) {
+ failf(data, "Failed to receive SOCKS5 connect request ack.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ }
+#endif
+
+ curlx_nonblock(sock, TRUE);
+ return CURLE_OK; /* Proxy was successful! */
+}
+
+#endif /* CURL_DISABLE_PROXY */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/socks.h b/external/libcurl_android/jni/libcurl/lib/socks.h
new file mode 100755
index 00000000..29e3bf03
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/socks.h
@@ -0,0 +1,77 @@
+#ifndef HEADER_CURL_SOCKS_H
+#define HEADER_CURL_SOCKS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef CURL_DISABLE_PROXY
+#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
+#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
+#else
+/*
+ * Helper read-from-socket functions. Does the same as Curl_read() but it
+ * blocks until all bytes amount of buffersize will be read. No more, no less.
+ *
+ * This is STUPID BLOCKING behaviour which we frown upon, but right now this
+ * is what we have...
+ */
+int Curl_blockread_all(struct connectdata *conn,
+ curl_socket_t sockfd,
+ char *buf,
+ ssize_t buffersize,
+ ssize_t *n);
+
+/*
+ * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
+ * final destination server.
+ */
+CURLcode Curl_SOCKS4(const char *proxy_name,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct connectdata *conn,
+ bool protocol4a);
+
+/*
+ * This function logs in to a SOCKS5 proxy and sends the specifics to the
+ * final destination server.
+ */
+CURLcode Curl_SOCKS5(const char *proxy_name,
+ const char *proxy_password,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct connectdata *conn);
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+/*
+ * This function handles the SOCKS5 GSS-API negotiation and initialisation
+ */
+CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+ struct connectdata *conn);
+#endif
+
+#endif /* CURL_DISABLE_PROXY */
+
+#endif /* HEADER_CURL_SOCKS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/socks_gssapi.c b/external/libcurl_android/jni/libcurl/lib/socks_gssapi.c
new file mode 100755
index 00000000..0eaa74c2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/socks_gssapi.c
@@ -0,0 +1,534 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
+ * Copyright (C) 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_PROXY
+
+#ifdef HAVE_GSSAPI
+#ifdef HAVE_OLD_GSSMIT
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#define NCOMPAT 1
+#endif
+#ifndef gss_nt_service_name
+#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
+#endif
+
+#include "curl_gssapi.h"
+#include "urldata.h"
+#include "sendf.h"
+#include "connect.h"
+#include "timeval.h"
+#include "socks.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
+
+/*
+ * Helper GSS-API error functions.
+ */
+static int check_gss_err(struct SessionHandle *data,
+ OM_uint32 major_status,
+ OM_uint32 minor_status,
+ const char* function)
+{
+ if(GSS_ERROR(major_status)) {
+ OM_uint32 maj_stat,min_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+ char buf[1024];
+ size_t len;
+
+ len = 0;
+ msg_ctx = 0;
+ while(!msg_ctx) {
+ /* convert major status code (GSS-API error) to text */
+ maj_stat = gss_display_status(&min_stat, major_status,
+ GSS_C_GSS_CODE,
+ GSS_C_NULL_OID,
+ &msg_ctx, &status_string);
+ if(maj_stat == GSS_S_COMPLETE) {
+ if(sizeof(buf) > len + status_string.length + 1) {
+ strcpy(buf+len, (char*) status_string.value);
+ len += status_string.length;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ break;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ }
+ if(sizeof(buf) > len + 3) {
+ strcpy(buf+len, ".\n");
+ len += 2;
+ }
+ msg_ctx = 0;
+ while(!msg_ctx) {
+ /* convert minor status code (underlying routine error) to text */
+ maj_stat = gss_display_status(&min_stat, minor_status,
+ GSS_C_MECH_CODE,
+ GSS_C_NULL_OID,
+ &msg_ctx, &status_string);
+ if(maj_stat == GSS_S_COMPLETE) {
+ if(sizeof(buf) > len + status_string.length)
+ strcpy(buf+len, (char*) status_string.value);
+ gss_release_buffer(&min_stat, &status_string);
+ break;
+ }
+ gss_release_buffer(&min_stat, &status_string);
+ }
+ failf(data, "GSS-API error: %s failed:\n%s", function, buf);
+ return(1);
+ }
+
+ return(0);
+}
+
+CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+ struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sock = conn->sock[sockindex];
+ CURLcode code;
+ ssize_t actualread;
+ ssize_t written;
+ int result;
+ OM_uint32 gss_major_status, gss_minor_status, gss_status;
+ OM_uint32 gss_ret_flags;
+ int gss_conf_state, gss_enc;
+ gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc gss_send_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc gss_recv_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc gss_w_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc* gss_token = GSS_C_NO_BUFFER;
+ gss_name_t server = GSS_C_NO_NAME;
+ gss_name_t gss_client_name = GSS_C_NO_NAME;
+ unsigned short us_length;
+ char *user=NULL;
+ unsigned char socksreq[4]; /* room for GSS-API exchange header only */
+ char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
+
+ /* GSS-API request looks like
+ * +----+------+-----+----------------+
+ * |VER | MTYP | LEN | TOKEN |
+ * +----+------+----------------------+
+ * | 1 | 1 | 2 | up to 2^16 - 1 |
+ * +----+------+-----+----------------+
+ */
+
+ /* prepare service name */
+ if(strchr(serviceptr,'/')) {
+ service.value = malloc(strlen(serviceptr));
+ if(!service.value)
+ return CURLE_OUT_OF_MEMORY;
+ service.length = strlen(serviceptr);
+ memcpy(service.value, serviceptr, service.length);
+
+ gss_major_status = gss_import_name(&gss_minor_status, &service,
+ (gss_OID) GSS_C_NULL_OID, &server);
+ }
+ else {
+ service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2);
+ if(!service.value)
+ return CURLE_OUT_OF_MEMORY;
+ service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1;
+ snprintf(service.value, service.length+1, "%s@%s",
+ serviceptr, conn->proxy.name);
+
+ gss_major_status = gss_import_name(&gss_minor_status, &service,
+ gss_nt_service_name, &server);
+ }
+
+ gss_release_buffer(&gss_status, &service); /* clear allocated memory */
+
+ if(check_gss_err(data,gss_major_status,
+ gss_minor_status,"gss_import_name()")) {
+ failf(data, "Failed to create service name.");
+ gss_release_name(&gss_status, &server);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* As long as we need to keep sending some context info, and there's no */
+ /* errors, keep sending it... */
+ for(;;) {
+ gss_major_status = Curl_gss_init_sec_context(data,
+ &gss_minor_status,
+ &gss_context,
+ server,
+ &Curl_krb5_mech_oid,
+ NULL,
+ gss_token,
+ &gss_send_token,
+ &gss_ret_flags);
+
+ if(gss_token != GSS_C_NO_BUFFER)
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ if(check_gss_err(data,gss_major_status,
+ gss_minor_status,"gss_init_sec_context")) {
+ gss_release_name(&gss_status, &server);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ failf(data, "Failed to initial GSS-API token.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(gss_send_token.length != 0) {
+ socksreq[0] = 1; /* GSS-API subnegotiation version */
+ socksreq[1] = 1; /* authentication message type */
+ us_length = htons((short)gss_send_token.length);
+ memcpy(socksreq+2,&us_length,sizeof(short));
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ if((code != CURLE_OK) || (4 != written)) {
+ failf(data, "Failed to send GSS-API authentication request.");
+ gss_release_name(&gss_status, &server);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ code = Curl_write_plain(conn, sock, (char *)gss_send_token.value,
+ gss_send_token.length, &written);
+
+ if((code != CURLE_OK) || ((ssize_t)gss_send_token.length != written)) {
+ failf(data, "Failed to send GSS-API authentication token.");
+ gss_release_name(&gss_status, &server);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ }
+
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ if(gss_major_status != GSS_S_CONTINUE_NEEDED) break;
+
+ /* analyse response */
+
+ /* GSS-API response looks like
+ * +----+------+-----+----------------+
+ * |VER | MTYP | LEN | TOKEN |
+ * +----+------+----------------------+
+ * | 1 | 1 | 2 | up to 2^16 - 1 |
+ * +----+------+-----+----------------+
+ */
+
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ if(result != CURLE_OK || actualread != 4) {
+ failf(data, "Failed to receive GSS-API authentication response.");
+ gss_release_name(&gss_status, &server);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] == 255) { /* status / message type */
+ failf(data, "User was rejected by the SOCKS5 server (%d %d).",
+ socksreq[0], socksreq[1]);
+ gss_release_name(&gss_status, &server);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[1] != 1) { /* status / messgae type */
+ failf(data, "Invalid GSS-API authentication response type (%d %d).",
+ socksreq[0], socksreq[1]);
+ gss_release_name(&gss_status, &server);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(&us_length, socksreq+2, sizeof(short));
+ us_length = ntohs(us_length);
+
+ gss_recv_token.length=us_length;
+ gss_recv_token.value=malloc(us_length);
+ if(!gss_recv_token.value) {
+ failf(data,
+ "Could not allocate memory for GSS-API authentication "
+ "response token.");
+ gss_release_name(&gss_status, &server);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ gss_recv_token.length, &actualread);
+
+ if(result != CURLE_OK || actualread != us_length) {
+ failf(data, "Failed to receive GSS-API authentication token.");
+ gss_release_name(&gss_status, &server);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ gss_token = &gss_recv_token;
+ }
+
+ gss_release_name(&gss_status, &server);
+
+ /* Everything is good so far, user was authenticated! */
+ gss_major_status = gss_inquire_context (&gss_minor_status, gss_context,
+ &gss_client_name, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if(check_gss_err(data,gss_major_status,
+ gss_minor_status,"gss_inquire_context")) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ gss_release_name(&gss_status, &gss_client_name);
+ failf(data, "Failed to determine user name.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ gss_major_status = gss_display_name(&gss_minor_status, gss_client_name,
+ &gss_send_token, NULL);
+ if(check_gss_err(data,gss_major_status,
+ gss_minor_status,"gss_display_name")) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ gss_release_name(&gss_status, &gss_client_name);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ failf(data, "Failed to determine user name.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ user=malloc(gss_send_token.length+1);
+ if(!user) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ gss_release_name(&gss_status, &gss_client_name);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ memcpy(user, gss_send_token.value, gss_send_token.length);
+ user[gss_send_token.length] = '\0';
+ gss_release_name(&gss_status, &gss_client_name);
+ gss_release_buffer(&gss_status, &gss_send_token);
+ infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user);
+ free(user);
+ user=NULL;
+
+ /* Do encryption */
+ socksreq[0] = 1; /* GSS-API subnegotiation version */
+ socksreq[1] = 2; /* encryption message type */
+
+ gss_enc = 0; /* no data protection */
+ /* do confidentiality protection if supported */
+ if(gss_ret_flags & GSS_C_CONF_FLAG)
+ gss_enc = 2;
+ /* else do integrity protection */
+ else if(gss_ret_flags & GSS_C_INTEG_FLAG)
+ gss_enc = 1;
+
+ infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
+ (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality"));
+ /* force for the moment to no data protection */
+ gss_enc = 0;
+ /*
+ * Sending the encryption type in clear seems wrong. It should be
+ * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
+ * The NEC reference implementations on which this is based is
+ * therefore at fault
+ *
+ * +------+------+------+.......................+
+ * + ver | mtyp | len | token |
+ * +------+------+------+.......................+
+ * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
+ * +------+------+------+.......................+
+ *
+ * Where:
+ *
+ * - "ver" is the protocol version number, here 1 to represent the
+ * first version of the SOCKS/GSS-API protocol
+ *
+ * - "mtyp" is the message type, here 2 to represent a protection
+ * -level negotiation message
+ *
+ * - "len" is the length of the "token" field in octets
+ *
+ * - "token" is the GSS-API encapsulated protection level
+ *
+ * The token is produced by encapsulating an octet containing the
+ * required protection level using gss_seal()/gss_wrap() with conf_req
+ * set to FALSE. The token is verified using gss_unseal()/
+ * gss_unwrap().
+ *
+ */
+ if(data->set.socks5_gssapi_nec) {
+ us_length = htons((short)1);
+ memcpy(socksreq+2,&us_length,sizeof(short));
+ }
+ else {
+ gss_send_token.length = 1;
+ gss_send_token.value = malloc(1);
+ if(!gss_send_token.value) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(gss_send_token.value, &gss_enc, 1);
+
+ gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0,
+ GSS_C_QOP_DEFAULT, &gss_send_token,
+ &gss_conf_state, &gss_w_token);
+
+ if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_wrap")) {
+ gss_release_buffer(&gss_status, &gss_send_token);
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ failf(data, "Failed to wrap GSS-API encryption value into token.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ gss_release_buffer(&gss_status, &gss_send_token);
+
+ us_length = htons((short)gss_w_token.length);
+ memcpy(socksreq+2,&us_length,sizeof(short));
+ }
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ if((code != CURLE_OK) || (4 != written)) {
+ failf(data, "Failed to send GSS-API encryption request.");
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(data->set.socks5_gssapi_nec) {
+ memcpy(socksreq, &gss_enc, 1);
+ code = Curl_write_plain(conn, sock, socksreq, 1, &written);
+ if((code != CURLE_OK) || ( 1 != written)) {
+ failf(data, "Failed to send GSS-API encryption type.");
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+ else {
+ code = Curl_write_plain(conn, sock, (char *)gss_w_token.value,
+ gss_w_token.length, &written);
+ if((code != CURLE_OK) || ((ssize_t)gss_w_token.length != written)) {
+ failf(data, "Failed to send GSS-API encryption type.");
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+ gss_release_buffer(&gss_status, &gss_w_token);
+ }
+
+ result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ if(result != CURLE_OK || actualread != 4) {
+ failf(data, "Failed to receive GSS-API encryption response.");
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] == 255) { /* status / message type */
+ failf(data, "User was rejected by the SOCKS5 server (%d %d).",
+ socksreq[0], socksreq[1]);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[1] != 2) { /* status / messgae type */
+ failf(data, "Invalid GSS-API encryption response type (%d %d).",
+ socksreq[0], socksreq[1]);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(&us_length, socksreq+2, sizeof(short));
+ us_length = ntohs(us_length);
+
+ gss_recv_token.length= us_length;
+ gss_recv_token.value=malloc(gss_recv_token.length);
+ if(!gss_recv_token.value) {
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ gss_recv_token.length, &actualread);
+
+ if(result != CURLE_OK || actualread != us_length) {
+ failf(data, "Failed to receive GSS-API encryptrion type.");
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(!data->set.socks5_gssapi_nec) {
+ gss_major_status = gss_unwrap(&gss_minor_status, gss_context,
+ &gss_recv_token, &gss_w_token,
+ 0, GSS_C_QOP_DEFAULT);
+
+ if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_unwrap")) {
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ failf(data, "Failed to unwrap GSS-API encryption value into token.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ gss_release_buffer(&gss_status, &gss_recv_token);
+
+ if(gss_w_token.length != 1) {
+ failf(data, "Invalid GSS-API encryption response length (%d).",
+ gss_w_token.length);
+ gss_release_buffer(&gss_status, &gss_w_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(socksreq,gss_w_token.value,gss_w_token.length);
+ gss_release_buffer(&gss_status, &gss_w_token);
+ }
+ else {
+ if(gss_recv_token.length != 1) {
+ failf(data, "Invalid GSS-API encryption response length (%d).",
+ gss_recv_token.length);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(socksreq,gss_recv_token.value,gss_recv_token.length);
+ gss_release_buffer(&gss_status, &gss_recv_token);
+ }
+
+ infof(data, "SOCKS5 access with%s protection granted.\n",
+ (socksreq[0]==0)?"out GSS-API data":
+ ((socksreq[0]==1)?" GSS-API integrity":" GSS-API confidentiality"));
+
+ conn->socks5_gssapi_enctype = socksreq[0];
+ if(socksreq[0] == 0)
+ gss_delete_sec_context(&gss_status, &gss_context, NULL);
+
+ return CURLE_OK;
+}
+#endif
+
+#endif /* CURL_DISABLE_PROXY */
diff --git a/external/libcurl_android/jni/libcurl/lib/socks_sspi.c b/external/libcurl_android/jni/libcurl/lib/socks_sspi.c
new file mode 100755
index 00000000..82684e0a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/socks_sspi.c
@@ -0,0 +1,604 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY)
+
+#include "urldata.h"
+#include "sendf.h"
+#include "connect.h"
+#include "strerror.h"
+#include "timeval.h"
+#include "socks.h"
+#include "curl_sspi.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use the internal *printf() functions */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * Helper sspi error functions.
+ */
+static int check_sspi_err(struct connectdata *conn,
+ SECURITY_STATUS status,
+ const char* function)
+{
+ if(status != SEC_E_OK &&
+ status != SEC_I_COMPLETE_AND_CONTINUE &&
+ status != SEC_I_COMPLETE_NEEDED &&
+ status != SEC_I_CONTINUE_NEEDED) {
+ failf(conn->data, "SSPI error: %s failed: %s", function,
+ Curl_sspi_strerror(conn, status));
+ return 1;
+ }
+ return 0;
+}
+
+/* This is the SSPI-using version of this function */
+CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
+ struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sock = conn->sock[sockindex];
+ CURLcode code;
+ ssize_t actualread;
+ ssize_t written;
+ int result;
+ /* Needs GSS-API authentication */
+ SECURITY_STATUS status;
+ unsigned long sspi_ret_flags = 0;
+ int gss_enc;
+ SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
+ SecBufferDesc input_desc, output_desc, wrap_desc;
+ SecPkgContext_Sizes sspi_sizes;
+ CredHandle cred_handle;
+ CtxtHandle sspi_context;
+ PCtxtHandle context_handle = NULL;
+ SecPkgCredentials_Names names;
+ TimeStamp expiry;
+ char *service_name = NULL;
+ unsigned short us_length;
+ unsigned long qop;
+ unsigned char socksreq[4]; /* room for GSS-API exchange header only */
+ char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
+
+ /* GSS-API request looks like
+ * +----+------+-----+----------------+
+ * |VER | MTYP | LEN | TOKEN |
+ * +----+------+----------------------+
+ * | 1 | 1 | 2 | up to 2^16 - 1 |
+ * +----+------+-----+----------------+
+ */
+
+ /* prepare service name */
+ if(strchr(service, '/')) {
+ service_name = malloc(strlen(service));
+ if(!service_name)
+ return CURLE_OUT_OF_MEMORY;
+ memcpy(service_name, service, strlen(service));
+ }
+ else {
+ service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2);
+ if(!service_name)
+ return CURLE_OUT_OF_MEMORY;
+ snprintf(service_name,strlen(service) +strlen(conn->proxy.name)+2,"%s/%s",
+ service,conn->proxy.name);
+ }
+
+ input_desc.cBuffers = 1;
+ input_desc.pBuffers = &sspi_recv_token;
+ input_desc.ulVersion = SECBUFFER_VERSION;
+
+ sspi_recv_token.BufferType = SECBUFFER_TOKEN;
+ sspi_recv_token.cbBuffer = 0;
+ sspi_recv_token.pvBuffer = NULL;
+
+ output_desc.cBuffers = 1;
+ output_desc.pBuffers = &sspi_send_token;
+ output_desc.ulVersion = SECBUFFER_VERSION;
+
+ sspi_send_token.BufferType = SECBUFFER_TOKEN;
+ sspi_send_token.cbBuffer = 0;
+ sspi_send_token.pvBuffer = NULL;
+
+ wrap_desc.cBuffers = 3;
+ wrap_desc.pBuffers = sspi_w_token;
+ wrap_desc.ulVersion = SECBUFFER_VERSION;
+
+ cred_handle.dwLower = 0;
+ cred_handle.dwUpper = 0;
+
+ status = s_pSecFn->AcquireCredentialsHandle(NULL,
+ (TCHAR *) TEXT("Kerberos"),
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &cred_handle,
+ &expiry);
+
+ if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) {
+ failf(data, "Failed to acquire credentials.");
+ Curl_safefree(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* As long as we need to keep sending some context info, and there's no */
+ /* errors, keep sending it... */
+ for(;;) {
+ TCHAR *sname;
+
+ sname = Curl_convert_UTF8_to_tchar(service_name);
+ if(!sname)
+ return CURLE_OUT_OF_MEMORY;
+
+ status = s_pSecFn->InitializeSecurityContext(&cred_handle,
+ context_handle,
+ sname,
+ ISC_REQ_MUTUAL_AUTH |
+ ISC_REQ_ALLOCATE_MEMORY |
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_REQ_REPLAY_DETECT,
+ 0,
+ SECURITY_NATIVE_DREP,
+ &input_desc,
+ 0,
+ &sspi_context,
+ &output_desc,
+ &sspi_ret_flags,
+ &expiry);
+
+ Curl_unicodefree(sname);
+
+ if(sspi_recv_token.pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ sspi_recv_token.pvBuffer = NULL;
+ sspi_recv_token.cbBuffer = 0;
+ }
+
+ if(check_sspi_err(conn, status, "InitializeSecurityContext")) {
+ Curl_safefree(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ if(sspi_recv_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ failf(data, "Failed to initialise security context.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(sspi_send_token.cbBuffer != 0) {
+ socksreq[0] = 1; /* GSS-API subnegotiation version */
+ socksreq[1] = 1; /* authentication message type */
+ us_length = htons((short)sspi_send_token.cbBuffer);
+ memcpy(socksreq+2, &us_length, sizeof(short));
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ if((code != CURLE_OK) || (4 != written)) {
+ failf(data, "Failed to send SSPI authentication request.");
+ Curl_safefree(service_name);
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ if(sspi_recv_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
+ sspi_send_token.cbBuffer, &written);
+ if((code != CURLE_OK) || (sspi_send_token.cbBuffer != (size_t)written)) {
+ failf(data, "Failed to send SSPI authentication token.");
+ Curl_safefree(service_name);
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ if(sspi_recv_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ }
+
+ if(sspi_send_token.pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ sspi_send_token.pvBuffer = NULL;
+ }
+ sspi_send_token.cbBuffer = 0;
+
+ if(sspi_recv_token.pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ sspi_recv_token.pvBuffer = NULL;
+ }
+ sspi_recv_token.cbBuffer = 0;
+
+ if(status != SEC_I_CONTINUE_NEEDED)
+ break;
+
+ /* analyse response */
+
+ /* GSS-API response looks like
+ * +----+------+-----+----------------+
+ * |VER | MTYP | LEN | TOKEN |
+ * +----+------+----------------------+
+ * | 1 | 1 | 2 | up to 2^16 - 1 |
+ * +----+------+-----+----------------+
+ */
+
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ if(result != CURLE_OK || actualread != 4) {
+ failf(data, "Failed to receive SSPI authentication response.");
+ Curl_safefree(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] == 255) { /* status / message type */
+ failf(data, "User was rejected by the SOCKS5 server (%u %u).",
+ (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
+ Curl_safefree(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[1] != 1) { /* status / messgae type */
+ failf(data, "Invalid SSPI authentication response type (%u %u).",
+ (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
+ Curl_safefree(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(&us_length, socksreq+2, sizeof(short));
+ us_length = ntohs(us_length);
+
+ sspi_recv_token.cbBuffer = us_length;
+ sspi_recv_token.pvBuffer = malloc(us_length);
+
+ if(!sspi_recv_token.pvBuffer) {
+ Curl_safefree(service_name);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
+ sspi_recv_token.cbBuffer, &actualread);
+
+ if(result != CURLE_OK || actualread != us_length) {
+ failf(data, "Failed to receive SSPI authentication token.");
+ Curl_safefree(service_name);
+ if(sspi_recv_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ context_handle = &sspi_context;
+ }
+
+ Curl_safefree(service_name);
+
+ /* Everything is good so far, user was authenticated! */
+ status = s_pSecFn->QueryCredentialsAttributes(&cred_handle,
+ SECPKG_CRED_ATTR_NAMES,
+ &names);
+ s_pSecFn->FreeCredentialsHandle(&cred_handle);
+ if(check_sspi_err(conn, status, "QueryCredentialAttributes")) {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ s_pSecFn->FreeContextBuffer(names.sUserName);
+ failf(data, "Failed to determine user name.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",
+ names.sUserName);
+ s_pSecFn->FreeContextBuffer(names.sUserName);
+
+ /* Do encryption */
+ socksreq[0] = 1; /* GSS-API subnegotiation version */
+ socksreq[1] = 2; /* encryption message type */
+
+ gss_enc = 0; /* no data protection */
+ /* do confidentiality protection if supported */
+ if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
+ gss_enc = 2;
+ /* else do integrity protection */
+ else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
+ gss_enc = 1;
+
+ infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
+ (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") );
+ /* force to no data protection, avoid encryption/decryption for now */
+ gss_enc = 0;
+ /*
+ * Sending the encryption type in clear seems wrong. It should be
+ * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
+ * The NEC reference implementations on which this is based is
+ * therefore at fault
+ *
+ * +------+------+------+.......................+
+ * + ver | mtyp | len | token |
+ * +------+------+------+.......................+
+ * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
+ * +------+------+------+.......................+
+ *
+ * Where:
+ *
+ * - "ver" is the protocol version number, here 1 to represent the
+ * first version of the SOCKS/GSS-API protocol
+ *
+ * - "mtyp" is the message type, here 2 to represent a protection
+ * -level negotiation message
+ *
+ * - "len" is the length of the "token" field in octets
+ *
+ * - "token" is the GSS-API encapsulated protection level
+ *
+ * The token is produced by encapsulating an octet containing the
+ * required protection level using gss_seal()/gss_wrap() with conf_req
+ * set to FALSE. The token is verified using gss_unseal()/
+ * gss_unwrap().
+ *
+ */
+
+ if(data->set.socks5_gssapi_nec) {
+ us_length = htons((short)1);
+ memcpy(socksreq+2, &us_length, sizeof(short));
+ }
+ else {
+ status = s_pSecFn->QueryContextAttributes(&sspi_context,
+ SECPKG_ATTR_SIZES,
+ &sspi_sizes);
+ if(check_sspi_err(conn, status, "QueryContextAttributes")) {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ failf(data, "Failed to query security context attributes.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
+ sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
+ sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer);
+
+ if(!sspi_w_token[0].pvBuffer) {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ sspi_w_token[1].cbBuffer = 1;
+ sspi_w_token[1].pvBuffer = malloc(1);
+ if(!sspi_w_token[1].pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ memcpy(sspi_w_token[1].pvBuffer,&gss_enc,1);
+ sspi_w_token[2].BufferType = SECBUFFER_PADDING;
+ sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
+ sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize);
+ if(!sspi_w_token[2].pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ status = s_pSecFn->EncryptMessage(&sspi_context,
+ KERB_WRAP_NO_ENCRYPT,
+ &wrap_desc,
+ 0);
+ if(check_sspi_err(conn, status, "EncryptMessage")) {
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ failf(data, "Failed to query security context attributes.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer
+ + sspi_w_token[1].cbBuffer
+ + sspi_w_token[2].cbBuffer;
+ sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer);
+ if(!sspi_send_token.pvBuffer) {
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer,
+ sspi_w_token[0].cbBuffer);
+ memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer,
+ sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
+ memcpy((PUCHAR) sspi_send_token.pvBuffer
+ +sspi_w_token[0].cbBuffer
+ +sspi_w_token[1].cbBuffer,
+ sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
+
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ sspi_w_token[0].pvBuffer = NULL;
+ sspi_w_token[0].cbBuffer = 0;
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ sspi_w_token[1].pvBuffer = NULL;
+ sspi_w_token[1].cbBuffer = 0;
+ s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
+ sspi_w_token[2].pvBuffer = NULL;
+ sspi_w_token[2].cbBuffer = 0;
+
+ us_length = htons((short)sspi_send_token.cbBuffer);
+ memcpy(socksreq+2,&us_length,sizeof(short));
+ }
+
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ if((code != CURLE_OK) || (4 != written)) {
+ failf(data, "Failed to send SSPI encryption request.");
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(data->set.socks5_gssapi_nec) {
+ memcpy(socksreq,&gss_enc,1);
+ code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written);
+ if((code != CURLE_OK) || (1 != written)) {
+ failf(data, "Failed to send SSPI encryption type.");
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+ }
+ else {
+ code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
+ sspi_send_token.cbBuffer, &written);
+ if((code != CURLE_OK) || (sspi_send_token.cbBuffer != (size_t)written)) {
+ failf(data, "Failed to send SSPI encryption type.");
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(sspi_send_token.pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
+ }
+
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ if(result != CURLE_OK || actualread != 4) {
+ failf(data, "Failed to receive SSPI encryption response.");
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ /* ignore the first (VER) byte */
+ if(socksreq[1] == 255) { /* status / message type */
+ failf(data, "User was rejected by the SOCKS5 server (%u %u).",
+ (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(socksreq[1] != 2) { /* status / message type */
+ failf(data, "Invalid SSPI encryption response type (%u %u).",
+ (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(&us_length, socksreq+2, sizeof(short));
+ us_length = ntohs(us_length);
+
+ sspi_w_token[0].cbBuffer = us_length;
+ sspi_w_token[0].pvBuffer = malloc(us_length);
+ if(!sspi_w_token[0].pvBuffer) {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
+ sspi_w_token[0].cbBuffer, &actualread);
+
+ if(result != CURLE_OK || actualread != us_length) {
+ failf(data, "Failed to receive SSPI encryption type.");
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+
+ if(!data->set.socks5_gssapi_nec) {
+ wrap_desc.cBuffers = 2;
+ sspi_w_token[0].BufferType = SECBUFFER_STREAM;
+ sspi_w_token[1].BufferType = SECBUFFER_DATA;
+ sspi_w_token[1].cbBuffer = 0;
+ sspi_w_token[1].pvBuffer = NULL;
+
+ status = s_pSecFn->DecryptMessage(&sspi_context,
+ &wrap_desc,
+ 0,
+ &qop);
+
+ if(check_sspi_err(conn, status, "DecryptMessage")) {
+ if(sspi_w_token[0].pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ if(sspi_w_token[1].pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ failf(data, "Failed to query security context attributes.");
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ if(sspi_w_token[1].cbBuffer != 1) {
+ failf(data, "Invalid SSPI encryption response length (%lu).",
+ (unsigned long)sspi_w_token[1].cbBuffer);
+ if(sspi_w_token[0].pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ if(sspi_w_token[1].pvBuffer)
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+
+ memcpy(socksreq,sspi_w_token[1].pvBuffer,sspi_w_token[1].cbBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
+ }
+ else {
+ if(sspi_w_token[0].cbBuffer != 1) {
+ failf(data, "Invalid SSPI encryption response length (%lu).",
+ (unsigned long)sspi_w_token[0].cbBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ return CURLE_COULDNT_CONNECT;
+ }
+ memcpy(socksreq,sspi_w_token[0].pvBuffer,sspi_w_token[0].cbBuffer);
+ s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
+ }
+
+ infof(data, "SOCKS5 access with%s protection granted.\n",
+ (socksreq[0]==0)?"out GSS-API data":
+ ((socksreq[0]==1)?" GSS-API integrity":" GSS-API confidentiality"));
+
+ /* For later use if encryption is required
+ conn->socks5_gssapi_enctype = socksreq[0];
+ if(socksreq[0] != 0)
+ conn->socks5_sspi_context = sspi_context;
+ else {
+ s_pSecFn->DeleteSecurityContext(&sspi_context);
+ conn->socks5_sspi_context = sspi_context;
+ }
+ */
+ return CURLE_OK;
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/speedcheck.c b/external/libcurl_android/jni/libcurl/lib/speedcheck.c
new file mode 100755
index 00000000..ac7447c4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/speedcheck.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "multiif.h"
+#include "speedcheck.h"
+
+void Curl_speedinit(struct SessionHandle *data)
+{
+ memset(&data->state.keeps_speed, 0, sizeof(struct timeval));
+}
+
+CURLcode Curl_speedcheck(struct SessionHandle *data,
+ struct timeval now)
+{
+ if((data->progress.current_speed >= 0) &&
+ data->set.low_speed_time &&
+ (Curl_tvlong(data->state.keeps_speed) != 0) &&
+ (data->progress.current_speed < data->set.low_speed_limit)) {
+ long howlong = Curl_tvdiff(now, data->state.keeps_speed);
+ long nextcheck = (data->set.low_speed_time * 1000) - howlong;
+
+ /* We are now below the "low speed limit". If we are below it
+ for "low speed time" seconds we consider that enough reason
+ to abort the download. */
+ if(nextcheck <= 0) {
+ /* we have been this slow for long enough, now die */
+ failf(data,
+ "Operation too slow. "
+ "Less than %ld bytes/sec transferred the last %ld seconds",
+ data->set.low_speed_limit,
+ data->set.low_speed_time);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ else {
+ /* wait complete low_speed_time */
+ Curl_expire_latest(data, nextcheck);
+ }
+ }
+ else {
+ /* we keep up the required speed all right */
+ data->state.keeps_speed = now;
+
+ if(data->set.low_speed_limit)
+ /* if there is a low speed limit enabled, we set the expire timer to
+ make this connection's speed get checked again no later than when
+ this time is up */
+ Curl_expire_latest(data, data->set.low_speed_time*1000);
+ }
+ return CURLE_OK;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/speedcheck.h b/external/libcurl_android/jni/libcurl/lib/speedcheck.h
new file mode 100755
index 00000000..786cd121
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/speedcheck.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_SPEEDCHECK_H
+#define HEADER_CURL_SPEEDCHECK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "timeval.h"
+
+void Curl_speedinit(struct SessionHandle *data);
+CURLcode Curl_speedcheck(struct SessionHandle *data,
+ struct timeval now);
+
+#endif /* HEADER_CURL_SPEEDCHECK_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/splay.c b/external/libcurl_android/jni/libcurl/lib/splay.c
new file mode 100755
index 00000000..5bb7065e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/splay.c
@@ -0,0 +1,288 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1997 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "splay.h"
+
+/*
+ * This macro compares two node keys i and j and returns:
+ *
+ * negative value: when i is smaller than j
+ * zero : when i is equal to j
+ * positive when : when i is larger than j
+ */
+#define compare(i,j) Curl_splaycomparekeys((i),(j))
+
+/*
+ * Splay using the key i (which may or may not be in the tree.) The starting
+ * root is t.
+ */
+struct Curl_tree *Curl_splay(struct timeval i,
+ struct Curl_tree *t)
+{
+ struct Curl_tree N, *l, *r, *y;
+ long comp;
+
+ if(t == NULL)
+ return t;
+ N.smaller = N.larger = NULL;
+ l = r = &N;
+
+ for(;;) {
+ comp = compare(i, t->key);
+ if(comp < 0) {
+ if(t->smaller == NULL)
+ break;
+ if(compare(i, t->smaller->key) < 0) {
+ y = t->smaller; /* rotate smaller */
+ t->smaller = y->larger;
+ y->larger = t;
+ t = y;
+ if(t->smaller == NULL)
+ break;
+ }
+ r->smaller = t; /* link smaller */
+ r = t;
+ t = t->smaller;
+ }
+ else if(comp > 0) {
+ if(t->larger == NULL)
+ break;
+ if(compare(i, t->larger->key) > 0) {
+ y = t->larger; /* rotate larger */
+ t->larger = y->smaller;
+ y->smaller = t;
+ t = y;
+ if(t->larger == NULL)
+ break;
+ }
+ l->larger = t; /* link larger */
+ l = t;
+ t = t->larger;
+ }
+ else
+ break;
+ }
+
+ l->larger = t->smaller; /* assemble */
+ r->smaller = t->larger;
+ t->smaller = N.larger;
+ t->larger = N.smaller;
+
+ return t;
+}
+
+/* Insert key i into the tree t. Return a pointer to the resulting tree or
+ * NULL if something went wrong.
+ *
+ * @unittest: 1309
+ */
+struct Curl_tree *Curl_splayinsert(struct timeval i,
+ struct Curl_tree *t,
+ struct Curl_tree *node)
+{
+ static const struct timeval KEY_NOTUSED = {-1,-1}; /* will *NEVER* appear */
+
+ if(node == NULL)
+ return t;
+
+ if(t != NULL) {
+ t = Curl_splay(i,t);
+ if(compare(i, t->key)==0) {
+ /* There already exists a node in the tree with the very same key. Build
+ a linked list of nodes. We make the new 'node' struct the new master
+ node and make the previous node the first one in the 'same' list. */
+
+ node->same = t;
+ node->key = i;
+ node->smaller = t->smaller;
+ node->larger = t->larger;
+
+ t->smaller = node; /* in the sub node for this same key, we use the
+ smaller pointer to point back to the master
+ node */
+
+ t->key = KEY_NOTUSED; /* and we set the key in the sub node to NOTUSED
+ to quickly identify this node as a subnode */
+
+ return node; /* new root node */
+ }
+ }
+
+ if(t == NULL) {
+ node->smaller = node->larger = NULL;
+ }
+ else if(compare(i, t->key) < 0) {
+ node->smaller = t->smaller;
+ node->larger = t;
+ t->smaller = NULL;
+
+ }
+ else {
+ node->larger = t->larger;
+ node->smaller = t;
+ t->larger = NULL;
+ }
+ node->key = i;
+
+ node->same = NULL; /* no identical node (yet) */
+ return node;
+}
+
+/* Finds and deletes the best-fit node from the tree. Return a pointer to the
+ resulting tree. best-fit means the node with the given or lower key */
+struct Curl_tree *Curl_splaygetbest(struct timeval i,
+ struct Curl_tree *t,
+ struct Curl_tree **removed)
+{
+ struct Curl_tree *x;
+
+ if(!t) {
+ *removed = NULL; /* none removed since there was no root */
+ return NULL;
+ }
+
+ t = Curl_splay(i,t);
+ if(compare(i, t->key) < 0) {
+ /* too big node, try the smaller chain */
+ if(t->smaller)
+ t=Curl_splay(t->smaller->key, t);
+ else {
+ /* fail */
+ *removed = NULL;
+ return t;
+ }
+ }
+
+ if(compare(i, t->key) >= 0) { /* found it */
+ /* FIRST! Check if there is a list with identical keys */
+ x = t->same;
+ if(x) {
+ /* there is, pick one from the list */
+
+ /* 'x' is the new root node */
+
+ x->key = t->key;
+ x->larger = t->larger;
+ x->smaller = t->smaller;
+
+ *removed = t;
+ return x; /* new root */
+ }
+
+ if(t->smaller == NULL) {
+ x = t->larger;
+ }
+ else {
+ x = Curl_splay(i, t->smaller);
+ x->larger = t->larger;
+ }
+ *removed = t;
+
+ return x;
+ }
+ else {
+ *removed = NULL; /* no match */
+ return t; /* It wasn't there */
+ }
+}
+
+
+/* Deletes the very node we point out from the tree if it's there. Stores a
+ * pointer to the new resulting tree in 'newroot'.
+ *
+ * Returns zero on success and non-zero on errors! TODO: document error codes.
+ * When returning error, it does not touch the 'newroot' pointer.
+ *
+ * NOTE: when the last node of the tree is removed, there's no tree left so
+ * 'newroot' will be made to point to NULL.
+ *
+ * @unittest: 1309
+ */
+int Curl_splayremovebyaddr(struct Curl_tree *t,
+ struct Curl_tree *removenode,
+ struct Curl_tree **newroot)
+{
+ static const struct timeval KEY_NOTUSED = {-1,-1}; /* will *NEVER* appear */
+ struct Curl_tree *x;
+
+ if(!t || !removenode)
+ return 1;
+
+ if(compare(KEY_NOTUSED, removenode->key) == 0) {
+ /* Key set to NOTUSED means it is a subnode within a 'same' linked list
+ and thus we can unlink it easily. The 'smaller' link of a subnode
+ links to the parent node. */
+ if(removenode->smaller == NULL)
+ return 3;
+
+ removenode->smaller->same = removenode->same;
+ if(removenode->same)
+ removenode->same->smaller = removenode->smaller;
+
+ /* Ensures that double-remove gets caught. */
+ removenode->smaller = NULL;
+
+ /* voila, we're done! */
+ *newroot = t; /* return the same root */
+ return 0;
+ }
+
+ t = Curl_splay(removenode->key, t);
+
+ /* First make sure that we got the same root node as the one we want
+ to remove, as otherwise we might be trying to remove a node that
+ isn't actually in the tree.
+
+ We cannot just compare the keys here as a double remove in quick
+ succession of a node with key != KEY_NOTUSED && same != NULL
+ could return the same key but a different node. */
+ if(t != removenode)
+ return 2;
+
+ /* Check if there is a list with identical sizes, as then we're trying to
+ remove the root node of a list of nodes with identical keys. */
+ x = t->same;
+ if(x) {
+ /* 'x' is the new root node, we just make it use the root node's
+ smaller/larger links */
+
+ x->key = t->key;
+ x->larger = t->larger;
+ x->smaller = t->smaller;
+ }
+ else {
+ /* Remove the root node */
+ if(t->smaller == NULL)
+ x = t->larger;
+ else {
+ x = Curl_splay(removenode->key, t->smaller);
+ x->larger = t->larger;
+ }
+ }
+
+ *newroot = x; /* store new root pointer */
+
+ return 0;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/lib/splay.h b/external/libcurl_android/jni/libcurl/lib/splay.h
new file mode 100755
index 00000000..5f9ef24c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/splay.h
@@ -0,0 +1,66 @@
+#ifndef HEADER_CURL_SPLAY_H
+#define HEADER_CURL_SPLAY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1997 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+struct Curl_tree {
+ struct Curl_tree *smaller; /* smaller node */
+ struct Curl_tree *larger; /* larger node */
+ struct Curl_tree *same; /* points to a node with identical key */
+ struct timeval key; /* this node's "sort" key */
+ void *payload; /* data the splay code doesn't care about */
+};
+
+struct Curl_tree *Curl_splay(struct timeval i,
+ struct Curl_tree *t);
+
+struct Curl_tree *Curl_splayinsert(struct timeval key,
+ struct Curl_tree *t,
+ struct Curl_tree *newnode);
+
+#if 0
+struct Curl_tree *Curl_splayremove(struct timeval key,
+ struct Curl_tree *t,
+ struct Curl_tree **removed);
+#endif
+
+struct Curl_tree *Curl_splaygetbest(struct timeval key,
+ struct Curl_tree *t,
+ struct Curl_tree **removed);
+
+int Curl_splayremovebyaddr(struct Curl_tree *t,
+ struct Curl_tree *removenode,
+ struct Curl_tree **newroot);
+
+#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \
+ ( ((i.tv_sec) > (j.tv_sec)) ? 1 : \
+ ( ((i.tv_usec) < (j.tv_usec)) ? -1 : \
+ ( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0 ))))
+
+#ifdef DEBUGBUILD
+void Curl_splayprint(struct Curl_tree * t, int d, char output);
+#else
+#define Curl_splayprint(x,y,z) Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_SPLAY_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/ssh.c b/external/libcurl_android/jni/libcurl/lib/ssh.c
new file mode 100755
index 00000000..887e10f2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/ssh.c
@@ -0,0 +1,3302 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* #define CURL_LIBSSH2_DEBUG */
+
+#include "curl_setup.h"
+
+#ifdef USE_LIBSSH2
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include <libssh2.h>
+#include <libssh2_sftp.h>
+
+#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
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "ssh.h"
+#include "url.h"
+#include "speedcheck.h"
+#include "getinfo.h"
+
+#include "strequal.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "inet_ntop.h"
+#include "parsedate.h" /* for the week day and month names */
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "strtoofft.h"
+#include "multiif.h"
+#include "select.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifdef WIN32
+# undef PATH_MAX
+# define PATH_MAX MAX_PATH
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* just an extra precaution since there are systems that
+ have their definition hidden well */
+#endif
+
+#define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s))
+
+#define sftp_libssh2_realpath(s,p,t,m) \
+ libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
+ (t), (m), LIBSSH2_SFTP_REALPATH)
+
+/* Local functions: */
+static const char *sftp_libssh2_strerror(int err);
+static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
+static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
+static LIBSSH2_FREE_FUNC(my_libssh2_free);
+
+static CURLcode get_pathname(const char **cpp, char **path);
+
+static CURLcode ssh_connect(struct connectdata *conn, bool *done);
+static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
+static CURLcode ssh_do(struct connectdata *conn, bool *done);
+
+static CURLcode ssh_getworkingpath(struct connectdata *conn,
+ char *homedir, /* when SFTP is used */
+ char **path);
+
+static CURLcode scp_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode scp_doing(struct connectdata *conn,
+ bool *dophase_done);
+static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
+
+static CURLcode sftp_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode sftp_doing(struct connectdata *conn,
+ bool *dophase_done);
+static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
+static
+CURLcode sftp_perform(struct connectdata *conn,
+ bool *connected,
+ bool *dophase_done);
+
+static int ssh_getsock(struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks number
+ of sockets */
+ int numsocks);
+
+static int ssh_perform_getsock(const struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks
+ number of sockets */
+ int numsocks);
+
+static CURLcode ssh_setup_connection(struct connectdata *conn);
+
+/*
+ * SCP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_scp = {
+ "SCP", /* scheme */
+ ssh_setup_connection, /* setup_connection */
+ ssh_do, /* do_it */
+ scp_done, /* done */
+ ZERO_NULL, /* do_more */
+ ssh_connect, /* connect_it */
+ ssh_multi_statemach, /* connecting */
+ scp_doing, /* doing */
+ ssh_getsock, /* proto_getsock */
+ ssh_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ssh_perform_getsock, /* perform_getsock */
+ scp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SSH, /* defport */
+ CURLPROTO_SCP, /* protocol */
+ PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
+ | PROTOPT_NOURLQUERY /* flags */
+};
+
+
+/*
+ * SFTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_sftp = {
+ "SFTP", /* scheme */
+ ssh_setup_connection, /* setup_connection */
+ ssh_do, /* do_it */
+ sftp_done, /* done */
+ ZERO_NULL, /* do_more */
+ ssh_connect, /* connect_it */
+ ssh_multi_statemach, /* connecting */
+ sftp_doing, /* doing */
+ ssh_getsock, /* proto_getsock */
+ ssh_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ssh_perform_getsock, /* perform_getsock */
+ sftp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_SSH, /* defport */
+ CURLPROTO_SFTP, /* protocol */
+ PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
+ | PROTOPT_NOURLQUERY /* flags */
+};
+
+static void
+kbd_callback(const char *name, int name_len, const char *instruction,
+ int instruction_len, int num_prompts,
+ const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
+ LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
+ void **abstract)
+{
+ struct connectdata *conn = (struct connectdata *)*abstract;
+
+#ifdef CURL_LIBSSH2_DEBUG
+ fprintf(stderr, "name=%s\n", name);
+ fprintf(stderr, "name_len=%d\n", name_len);
+ fprintf(stderr, "instruction=%s\n", instruction);
+ fprintf(stderr, "instruction_len=%d\n", instruction_len);
+ fprintf(stderr, "num_prompts=%d\n", num_prompts);
+#else
+ (void)name;
+ (void)name_len;
+ (void)instruction;
+ (void)instruction_len;
+#endif /* CURL_LIBSSH2_DEBUG */
+ if(num_prompts == 1) {
+ responses[0].text = strdup(conn->passwd);
+ responses[0].length = curlx_uztoui(strlen(conn->passwd));
+ }
+ (void)prompts;
+ (void)abstract;
+} /* kbd_callback */
+
+static CURLcode sftp_libssh2_error_to_CURLE(int err)
+{
+ switch (err) {
+ case LIBSSH2_FX_OK:
+ return CURLE_OK;
+
+ case LIBSSH2_FX_NO_SUCH_FILE:
+ case LIBSSH2_FX_NO_SUCH_PATH:
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+
+ case LIBSSH2_FX_PERMISSION_DENIED:
+ case LIBSSH2_FX_WRITE_PROTECT:
+ case LIBSSH2_FX_LOCK_CONFlICT:
+ return CURLE_REMOTE_ACCESS_DENIED;
+
+ case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
+ case LIBSSH2_FX_QUOTA_EXCEEDED:
+ return CURLE_REMOTE_DISK_FULL;
+
+ case LIBSSH2_FX_FILE_ALREADY_EXISTS:
+ return CURLE_REMOTE_FILE_EXISTS;
+
+ case LIBSSH2_FX_DIR_NOT_EMPTY:
+ return CURLE_QUOTE_ERROR;
+
+ default:
+ break;
+ }
+
+ return CURLE_SSH;
+}
+
+static CURLcode libssh2_session_error_to_CURLE(int err)
+{
+ switch (err) {
+ /* Ordered by order of appearance in libssh2.h */
+ case LIBSSH2_ERROR_NONE:
+ return CURLE_OK;
+
+ case LIBSSH2_ERROR_SOCKET_NONE:
+ return CURLE_COULDNT_CONNECT;
+
+ case LIBSSH2_ERROR_ALLOC:
+ return CURLE_OUT_OF_MEMORY;
+
+ case LIBSSH2_ERROR_SOCKET_SEND:
+ return CURLE_SEND_ERROR;
+
+ case LIBSSH2_ERROR_HOSTKEY_INIT:
+ case LIBSSH2_ERROR_HOSTKEY_SIGN:
+ case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
+ case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
+ return CURLE_PEER_FAILED_VERIFICATION;
+
+ case LIBSSH2_ERROR_PASSWORD_EXPIRED:
+ return CURLE_LOGIN_DENIED;
+
+ case LIBSSH2_ERROR_SOCKET_TIMEOUT:
+ case LIBSSH2_ERROR_TIMEOUT:
+ return CURLE_OPERATION_TIMEDOUT;
+
+ case LIBSSH2_ERROR_EAGAIN:
+ return CURLE_AGAIN;
+ }
+
+ /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
+ error code, and possibly add a few new SSH-related one. We must however
+ not return or even depend on libssh2 errors in the public libcurl API */
+
+ return CURLE_SSH;
+}
+
+static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
+{
+ (void)abstract; /* arg not used */
+ return malloc(count);
+}
+
+static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
+{
+ (void)abstract; /* arg not used */
+ return realloc(ptr, count);
+}
+
+static LIBSSH2_FREE_FUNC(my_libssh2_free)
+{
+ (void)abstract; /* arg not used */
+ if(ptr) /* ssh2 agent sometimes call free with null ptr */
+ free(ptr);
+}
+
+/*
+ * SSH State machine related code
+ */
+/* This is the ONLY way to change SSH state! */
+static void state(struct connectdata *conn, sshstate nowstate)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ /* for debug purposes */
+ static const char * const names[] = {
+ "SSH_STOP",
+ "SSH_INIT",
+ "SSH_S_STARTUP",
+ "SSH_HOSTKEY",
+ "SSH_AUTHLIST",
+ "SSH_AUTH_PKEY_INIT",
+ "SSH_AUTH_PKEY",
+ "SSH_AUTH_PASS_INIT",
+ "SSH_AUTH_PASS",
+ "SSH_AUTH_AGENT_INIT",
+ "SSH_AUTH_AGENT_LIST",
+ "SSH_AUTH_AGENT",
+ "SSH_AUTH_HOST_INIT",
+ "SSH_AUTH_HOST",
+ "SSH_AUTH_KEY_INIT",
+ "SSH_AUTH_KEY",
+ "SSH_AUTH_DONE",
+ "SSH_SFTP_INIT",
+ "SSH_SFTP_REALPATH",
+ "SSH_SFTP_QUOTE_INIT",
+ "SSH_SFTP_POSTQUOTE_INIT",
+ "SSH_SFTP_QUOTE",
+ "SSH_SFTP_NEXT_QUOTE",
+ "SSH_SFTP_QUOTE_STAT",
+ "SSH_SFTP_QUOTE_SETSTAT",
+ "SSH_SFTP_QUOTE_SYMLINK",
+ "SSH_SFTP_QUOTE_MKDIR",
+ "SSH_SFTP_QUOTE_RENAME",
+ "SSH_SFTP_QUOTE_RMDIR",
+ "SSH_SFTP_QUOTE_UNLINK",
+ "SSH_SFTP_TRANS_INIT",
+ "SSH_SFTP_UPLOAD_INIT",
+ "SSH_SFTP_CREATE_DIRS_INIT",
+ "SSH_SFTP_CREATE_DIRS",
+ "SSH_SFTP_CREATE_DIRS_MKDIR",
+ "SSH_SFTP_READDIR_INIT",
+ "SSH_SFTP_READDIR",
+ "SSH_SFTP_READDIR_LINK",
+ "SSH_SFTP_READDIR_BOTTOM",
+ "SSH_SFTP_READDIR_DONE",
+ "SSH_SFTP_DOWNLOAD_INIT",
+ "SSH_SFTP_DOWNLOAD_STAT",
+ "SSH_SFTP_CLOSE",
+ "SSH_SFTP_SHUTDOWN",
+ "SSH_SCP_TRANS_INIT",
+ "SSH_SCP_UPLOAD_INIT",
+ "SSH_SCP_DOWNLOAD_INIT",
+ "SSH_SCP_DONE",
+ "SSH_SCP_SEND_EOF",
+ "SSH_SCP_WAIT_EOF",
+ "SSH_SCP_WAIT_CLOSE",
+ "SSH_SCP_CHANNEL_FREE",
+ "SSH_SESSION_DISCONNECT",
+ "SSH_SESSION_FREE",
+ "QUIT"
+ };
+
+ if(sshc->state != nowstate) {
+ infof(conn->data, "SFTP %p state change from %s to %s\n",
+ (void *)sshc, names[sshc->state], names[nowstate]);
+ }
+#endif
+
+ sshc->state = nowstate;
+}
+
+/* figure out the path to work with in this particular request */
+static CURLcode ssh_getworkingpath(struct connectdata *conn,
+ char *homedir, /* when SFTP is used */
+ char **path) /* returns the allocated
+ real path to work with */
+{
+ struct SessionHandle *data = conn->data;
+ char *real_path = NULL;
+ char *working_path;
+ int working_path_len;
+
+ working_path = curl_easy_unescape(data, data->state.path, 0,
+ &working_path_len);
+ if(!working_path)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Check for /~/ , indicating relative to the user's home directory */
+ if(conn->handler->protocol & CURLPROTO_SCP) {
+ real_path = malloc(working_path_len+1);
+ if(real_path == NULL) {
+ free(working_path);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
+ /* It is referenced to the home directory, so strip the leading '/~/' */
+ memcpy(real_path, working_path+3, 4 + working_path_len-3);
+ else
+ memcpy(real_path, working_path, 1 + working_path_len);
+ }
+ else if(conn->handler->protocol & CURLPROTO_SFTP) {
+ if((working_path_len > 1) && (working_path[1] == '~')) {
+ size_t homelen = strlen(homedir);
+ real_path = malloc(homelen + working_path_len + 1);
+ if(real_path == NULL) {
+ free(working_path);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ /* It is referenced to the home directory, so strip the
+ leading '/' */
+ memcpy(real_path, homedir, homelen);
+ real_path[homelen] = '/';
+ real_path[homelen+1] = '\0';
+ if(working_path_len > 3) {
+ memcpy(real_path+homelen+1, working_path + 3,
+ 1 + working_path_len -3);
+ }
+ }
+ else {
+ real_path = malloc(working_path_len+1);
+ if(real_path == NULL) {
+ free(working_path);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(real_path, working_path, 1+working_path_len);
+ }
+ }
+
+ free(working_path);
+
+ /* store the pointer for the caller to receive */
+ *path = real_path;
+
+ return CURLE_OK;
+}
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+static int sshkeycallback(CURL *easy,
+ const struct curl_khkey *knownkey, /* known */
+ const struct curl_khkey *foundkey, /* found */
+ enum curl_khmatch match,
+ void *clientp)
+{
+ (void)easy;
+ (void)knownkey;
+ (void)foundkey;
+ (void)clientp;
+
+ /* we only allow perfect matches, and we reject everything else */
+ return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
+}
+#endif
+
+/*
+ * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
+ * with 32bit size_t.
+ */
+#ifdef HAVE_LIBSSH2_SFTP_SEEK64
+#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
+#else
+#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
+#endif
+
+/*
+ * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit
+ * architectures so we check of the necessary function is present.
+ */
+#ifndef HAVE_LIBSSH2_SCP_SEND64
+#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
+#else
+#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
+ (libssh2_uint64_t)d, 0, 0)
+#endif
+
+/*
+ * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64.
+ */
+#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
+#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
+#endif
+
+static CURLcode ssh_knownhost(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ struct SessionHandle *data = conn->data;
+
+ if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
+ /* we're asked to verify the host against a file */
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ int rc;
+ int keytype;
+ size_t keylen;
+ const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
+ &keylen, &keytype);
+ int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
+ int keybit = 0;
+
+ if(remotekey) {
+ /*
+ * A subject to figure out is what host name we need to pass in here.
+ * What host name does OpenSSH store in its file if an IDN name is
+ * used?
+ */
+ struct libssh2_knownhost *host;
+ enum curl_khmatch keymatch;
+ curl_sshkeycallback func =
+ data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
+ struct curl_khkey knownkey;
+ struct curl_khkey *knownkeyp = NULL;
+ struct curl_khkey foundkey;
+
+ keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
+ LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
+
+ keycheck = libssh2_knownhost_check(sshc->kh,
+ conn->host.name,
+ remotekey, keylen,
+ LIBSSH2_KNOWNHOST_TYPE_PLAIN|
+ LIBSSH2_KNOWNHOST_KEYENC_RAW|
+ keybit,
+ &host);
+
+ infof(data, "SSH host check: %d, key: %s\n", keycheck,
+ (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
+ host->key:"<none>");
+
+ /* setup 'knownkey' */
+ if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
+ knownkey.key = host->key;
+ knownkey.len = 0;
+ knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
+ CURLKHTYPE_RSA : CURLKHTYPE_DSS;
+ knownkeyp = &knownkey;
+ }
+
+ /* setup 'foundkey' */
+ foundkey.key = remotekey;
+ foundkey.len = keylen;
+ foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
+ CURLKHTYPE_RSA : CURLKHTYPE_DSS;
+
+ /*
+ * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
+ * curl_khmatch enum are ever modified, we need to introduce a
+ * translation table here!
+ */
+ keymatch = (enum curl_khmatch)keycheck;
+
+ /* Ask the callback how to behave */
+ rc = func(data, knownkeyp, /* from the knownhosts file */
+ &foundkey, /* from the remote host */
+ keymatch, data->set.ssh_keyfunc_userp);
+ }
+ else
+ /* no remotekey means failure! */
+ rc = CURLKHSTAT_REJECT;
+
+ switch(rc) {
+ default: /* unknown return codes will equal reject */
+ case CURLKHSTAT_REJECT:
+ state(conn, SSH_SESSION_FREE);
+ case CURLKHSTAT_DEFER:
+ /* DEFER means bail out but keep the SSH_HOSTKEY state */
+ result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
+ break;
+ case CURLKHSTAT_FINE:
+ case CURLKHSTAT_FINE_ADD_TO_FILE:
+ /* proceed */
+ if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
+ /* the found host+key didn't match but has been told to be fine
+ anyway so we add it in memory */
+ int addrc = libssh2_knownhost_add(sshc->kh,
+ conn->host.name, NULL,
+ remotekey, keylen,
+ LIBSSH2_KNOWNHOST_TYPE_PLAIN|
+ LIBSSH2_KNOWNHOST_KEYENC_RAW|
+ keybit, NULL);
+ if(addrc)
+ infof(data, "Warning adding the known host %s failed!\n",
+ conn->host.name);
+ else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
+ /* now we write the entire in-memory list of known hosts to the
+ known_hosts file */
+ int wrc =
+ libssh2_knownhost_writefile(sshc->kh,
+ data->set.str[STRING_SSH_KNOWNHOSTS],
+ LIBSSH2_KNOWNHOST_FILE_OPENSSH);
+ if(wrc) {
+ infof(data, "Warning, writing %s failed!\n",
+ data->set.str[STRING_SSH_KNOWNHOSTS]);
+ }
+ }
+ }
+ break;
+ }
+ }
+#else /* HAVE_LIBSSH2_KNOWNHOST_API */
+ (void)conn;
+#endif
+ return result;
+}
+
+static CURLcode ssh_check_fingerprint(struct connectdata *conn)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ struct SessionHandle *data = conn->data;
+ const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
+ char md5buffer[33];
+ int i;
+
+ const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
+ LIBSSH2_HOSTKEY_HASH_MD5);
+
+ if(fingerprint) {
+ /* The fingerprint points to static storage (!), don't free() it. */
+ for(i = 0; i < 16; i++)
+ snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
+ infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
+ }
+
+ /* Before we authenticate we check the hostkey's MD5 fingerprint
+ * against a known fingerprint, if available.
+ */
+ if(pubkey_md5 && strlen(pubkey_md5) == 32) {
+ if(!fingerprint || !strequal(md5buffer, pubkey_md5)) {
+ if(fingerprint)
+ failf(data,
+ "Denied establishing ssh session: mismatch md5 fingerprint. "
+ "Remote %s is not equal to %s", md5buffer, pubkey_md5);
+ else
+ failf(data,
+ "Denied establishing ssh session: md5 fingerprint not available");
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
+ return sshc->actualcode;
+ }
+ else {
+ infof(data, "MD5 checksum match!\n");
+ /* as we already matched, we skip the check for known hosts */
+ return CURLE_OK;
+ }
+ }
+ else
+ return ssh_knownhost(conn);
+}
+
+/*
+ * ssh_statemach_act() runs the SSH state machine as far as it can without
+ * blocking and without reaching the end. The data the pointer 'block' points
+ * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
+ * meaning it wants to be called again when the socket is ready
+ */
+
+static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct SSHPROTO *sftp_scp = data->req.protop;
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ char *new_readdir_line;
+ int rc = LIBSSH2_ERROR_NONE;
+ int err;
+ int seekerr = CURL_SEEKFUNC_OK;
+ *block = 0; /* we're not blocking by default */
+
+ do {
+
+ switch(sshc->state) {
+ case SSH_INIT:
+ sshc->secondCreateDirs = 0;
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_OK;
+
+ /* Set libssh2 to non-blocking, since everything internally is
+ non-blocking */
+ libssh2_session_set_blocking(sshc->ssh_session, 0);
+
+ state(conn, SSH_S_STARTUP);
+ /* fall-through */
+
+ case SSH_S_STARTUP:
+ rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ failf(data, "Failure establishing ssh session");
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_FAILED_INIT;
+ break;
+ }
+
+ state(conn, SSH_HOSTKEY);
+
+ /* fall-through */
+ case SSH_HOSTKEY:
+ /*
+ * Before we authenticate we should check the hostkey's fingerprint
+ * against our known hosts. How that is handled (reading from file,
+ * whatever) is up to us.
+ */
+ result = ssh_check_fingerprint(conn);
+ if(result == CURLE_OK)
+ state(conn, SSH_AUTHLIST);
+ /* ssh_check_fingerprint sets state appropriately on error */
+ break;
+
+ case SSH_AUTHLIST:
+ /*
+ * Figure out authentication methods
+ * NB: As soon as we have provided a username to an openssh server we
+ * must never change it later. Thus, always specify the correct username
+ * here, even though the libssh2 docs kind of indicate that it should be
+ * possible to get a 'generic' list (not user-specific) of authentication
+ * methods, presumably with a blank username. That won't work in my
+ * experience.
+ * So always specify it here.
+ */
+ sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(strlen(conn->user)));
+
+ if(!sshc->authlist) {
+ if(libssh2_userauth_authenticated(sshc->ssh_session)) {
+ sshc->authed = TRUE;
+ infof(data, "SSH user accepted with no authentication\n");
+ state(conn, SSH_AUTH_DONE);
+ break;
+ }
+ else if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = libssh2_session_error_to_CURLE(err);
+ break;
+ }
+ }
+ infof(data, "SSH authentication methods available: %s\n",
+ sshc->authlist);
+
+ state(conn, SSH_AUTH_PKEY_INIT);
+ break;
+
+ case SSH_AUTH_PKEY_INIT:
+ /*
+ * Check the supported auth types in the order I feel is most secure
+ * with the requested type of authentication
+ */
+ sshc->authed = FALSE;
+
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
+ (strstr(sshc->authlist, "publickey") != NULL)) {
+ char *home = NULL;
+ bool rsa_pub_empty_but_ok = FALSE;
+
+ sshc->rsa_pub = sshc->rsa = NULL;
+
+ /* To ponder about: should really the lib be messing about with the
+ HOME environment variable etc? */
+ home = curl_getenv("HOME");
+
+ if(data->set.str[STRING_SSH_PUBLIC_KEY] &&
+ !*data->set.str[STRING_SSH_PUBLIC_KEY])
+ rsa_pub_empty_but_ok = true;
+ else if(data->set.str[STRING_SSH_PUBLIC_KEY])
+ sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]);
+ else if(home)
+ sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home);
+ else
+ /* as a final resort, try current dir! */
+ sshc->rsa_pub = strdup("id_dsa.pub");
+
+ if(!rsa_pub_empty_but_ok && (sshc->rsa_pub == NULL)) {
+ Curl_safefree(home);
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ if(data->set.str[STRING_SSH_PRIVATE_KEY])
+ sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]);
+ else if(home)
+ sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
+ else
+ /* as a final resort, try current dir! */
+ sshc->rsa = strdup("id_dsa");
+
+ if(sshc->rsa == NULL) {
+ Curl_safefree(home);
+ Curl_safefree(sshc->rsa_pub);
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
+ if(!sshc->passphrase)
+ sshc->passphrase = "";
+
+ Curl_safefree(home);
+
+ infof(data, "Using ssh public key file %s\n", sshc->rsa_pub);
+ infof(data, "Using ssh private key file %s\n", sshc->rsa);
+
+ state(conn, SSH_AUTH_PKEY);
+ }
+ else {
+ state(conn, SSH_AUTH_PASS_INIT);
+ }
+ break;
+
+ case SSH_AUTH_PKEY:
+ /* The function below checks if the files exists, no need to stat() here.
+ */
+ rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(
+ strlen(conn->user)),
+ sshc->rsa_pub,
+ sshc->rsa, sshc->passphrase);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+
+ if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized SSH public key authentication\n");
+ state(conn, SSH_AUTH_DONE);
+ }
+ else {
+ char *err_msg;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "SSH public key authentication failed: %s\n", err_msg);
+ state(conn, SSH_AUTH_PASS_INIT);
+ }
+ break;
+
+ case SSH_AUTH_PASS_INIT:
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
+ (strstr(sshc->authlist, "password") != NULL)) {
+ state(conn, SSH_AUTH_PASS);
+ }
+ else {
+ state(conn, SSH_AUTH_HOST_INIT);
+ }
+ break;
+
+ case SSH_AUTH_PASS:
+ rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
+ curlx_uztoui(strlen(conn->user)),
+ conn->passwd,
+ curlx_uztoui(strlen(conn->passwd)),
+ NULL);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized password authentication\n");
+ state(conn, SSH_AUTH_DONE);
+ }
+ else {
+ state(conn, SSH_AUTH_HOST_INIT);
+ }
+ break;
+
+ case SSH_AUTH_HOST_INIT:
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
+ (strstr(sshc->authlist, "hostbased") != NULL)) {
+ state(conn, SSH_AUTH_HOST);
+ }
+ else {
+ state(conn, SSH_AUTH_AGENT_INIT);
+ }
+ break;
+
+ case SSH_AUTH_HOST:
+ state(conn, SSH_AUTH_AGENT_INIT);
+ break;
+
+ case SSH_AUTH_AGENT_INIT:
+#ifdef HAVE_LIBSSH2_AGENT_API
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
+ && (strstr(sshc->authlist, "publickey") != NULL)) {
+
+ /* Connect to the ssh-agent */
+ /* The agent could be shared by a curl thread i believe
+ but nothing obvious as keys can be added/removed at any time */
+ if(!sshc->ssh_agent) {
+ sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
+ if(!sshc->ssh_agent) {
+ infof(data, "Could not create agent object\n");
+
+ state(conn, SSH_AUTH_KEY_INIT);
+ break;
+ }
+ }
+
+ rc = libssh2_agent_connect(sshc->ssh_agent);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ break;
+ if(rc < 0) {
+ infof(data, "Failure connecting to agent\n");
+ state(conn, SSH_AUTH_KEY_INIT);
+ }
+ else {
+ state(conn, SSH_AUTH_AGENT_LIST);
+ }
+ }
+ else
+#endif /* HAVE_LIBSSH2_AGENT_API */
+ state(conn, SSH_AUTH_KEY_INIT);
+ break;
+
+ case SSH_AUTH_AGENT_LIST:
+#ifdef HAVE_LIBSSH2_AGENT_API
+ rc = libssh2_agent_list_identities(sshc->ssh_agent);
+
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ break;
+ if(rc < 0) {
+ infof(data, "Failure requesting identities to agent\n");
+ state(conn, SSH_AUTH_KEY_INIT);
+ }
+ else {
+ state(conn, SSH_AUTH_AGENT);
+ sshc->sshagent_prev_identity = NULL;
+ }
+#endif
+ break;
+
+ case SSH_AUTH_AGENT:
+#ifdef HAVE_LIBSSH2_AGENT_API
+ /* as prev_identity evolves only after an identity user auth finished we
+ can safely request it again as long as EAGAIN is returned here or by
+ libssh2_agent_userauth */
+ rc = libssh2_agent_get_identity(sshc->ssh_agent,
+ &sshc->sshagent_identity,
+ sshc->sshagent_prev_identity);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ break;
+
+ if(rc == 0) {
+ rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
+ sshc->sshagent_identity);
+
+ if(rc < 0) {
+ if(rc != LIBSSH2_ERROR_EAGAIN) {
+ /* tried and failed? go to next identity */
+ sshc->sshagent_prev_identity = sshc->sshagent_identity;
+ }
+ break;
+ }
+ }
+
+ if(rc < 0)
+ infof(data, "Failure requesting identities to agent\n");
+ else if(rc == 1)
+ infof(data, "No identity would match\n");
+
+ if(rc == LIBSSH2_ERROR_NONE) {
+ sshc->authed = TRUE;
+ infof(data, "Agent based authentication successful\n");
+ state(conn, SSH_AUTH_DONE);
+ }
+ else
+ state(conn, SSH_AUTH_KEY_INIT);
+#endif
+ break;
+
+ case SSH_AUTH_KEY_INIT:
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
+ && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
+ state(conn, SSH_AUTH_KEY);
+ }
+ else {
+ state(conn, SSH_AUTH_DONE);
+ }
+ break;
+
+ case SSH_AUTH_KEY:
+ /* Authentication failed. Continue with keyboard-interactive now. */
+ rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(
+ strlen(conn->user)),
+ &kbd_callback);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized keyboard interactive authentication\n");
+ }
+ state(conn, SSH_AUTH_DONE);
+ break;
+
+ case SSH_AUTH_DONE:
+ if(!sshc->authed) {
+ failf(data, "Authentication failure");
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_LOGIN_DENIED;
+ break;
+ }
+
+ /*
+ * At this point we have an authenticated ssh session.
+ */
+ infof(data, "Authentication complete\n");
+
+ Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
+
+ conn->sockfd = sock;
+ conn->writesockfd = CURL_SOCKET_BAD;
+
+ if(conn->handler->protocol == CURLPROTO_SFTP) {
+ state(conn, SSH_SFTP_INIT);
+ break;
+ }
+ infof(data, "SSH CONNECT phase done\n");
+ state(conn, SSH_STOP);
+ break;
+
+ case SSH_SFTP_INIT:
+ /*
+ * Start the libssh2 sftp session
+ */
+ sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
+ if(!sshc->sftp_session) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ char *err_msg;
+
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ failf(data, "Failure initializing sftp session: %s", err_msg);
+ state(conn, SSH_SESSION_FREE);
+ sshc->actualcode = CURLE_FAILED_INIT;
+ break;
+ }
+ }
+ state(conn, SSH_SFTP_REALPATH);
+ break;
+
+ case SSH_SFTP_REALPATH:
+ {
+ char tempHome[PATH_MAX];
+
+ /*
+ * Get the "home" directory
+ */
+ rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
+ tempHome, PATH_MAX-1);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc > 0) {
+ /* It seems that this string is not always NULL terminated */
+ tempHome[rc] = '\0';
+ sshc->homedir = strdup(tempHome);
+ if(!sshc->homedir) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+ }
+ else {
+ /* Return the error type */
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ result = sftp_libssh2_error_to_CURLE(err);
+ sshc->actualcode = result?result:CURLE_SSH;
+ DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
+ err, (int)result));
+ state(conn, SSH_STOP);
+ break;
+ }
+ }
+ /* This is the last step in the SFTP connect phase. Do note that while
+ we get the homedir here, we get the "workingpath" in the DO action
+ since the homedir will remain the same between request but the
+ working path will not. */
+ DEBUGF(infof(data, "SSH CONNECT phase done\n"));
+ state(conn, SSH_STOP);
+ break;
+
+ case SSH_SFTP_QUOTE_INIT:
+
+ result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ if(result) {
+ sshc->actualcode = result;
+ state(conn, SSH_STOP);
+ break;
+ }
+
+ if(data->set.quote) {
+ infof(data, "Sending quote commands\n");
+ sshc->quote_item = data->set.quote;
+ state(conn, SSH_SFTP_QUOTE);
+ }
+ else {
+ state(conn, SSH_SFTP_TRANS_INIT);
+ }
+ break;
+
+ case SSH_SFTP_POSTQUOTE_INIT:
+ if(data->set.postquote) {
+ infof(data, "Sending quote commands\n");
+ sshc->quote_item = data->set.postquote;
+ state(conn, SSH_SFTP_QUOTE);
+ }
+ else {
+ state(conn, SSH_STOP);
+ }
+ break;
+
+ case SSH_SFTP_QUOTE:
+ /* Send any quote commands */
+ {
+ const char *cp;
+
+ /*
+ * Support some of the "FTP" commands
+ */
+ char *cmd = sshc->quote_item->data;
+ sshc->acceptfail = FALSE;
+
+ /* if a command starts with an asterisk, which a legal SFTP command never
+ can, the command will be allowed to fail without it causing any
+ aborts or cancels etc. It will cause libcurl to act as if the command
+ is successful, whatever the server reponds. */
+
+ if(cmd[0] == '*') {
+ cmd++;
+ sshc->acceptfail = TRUE;
+ }
+
+ if(curl_strequal("pwd", cmd)) {
+ /* output debug output if that is requested */
+ char *tmp = aprintf("257 \"%s\" is current directory.\n",
+ sftp_scp->path);
+ if(!tmp) {
+ result = CURLE_OUT_OF_MEMORY;
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ break;
+ }
+ if(data->set.verbose) {
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+ }
+ /* this sends an FTP-like "header" to the header callback so that the
+ current directory can be read very similar to how it is read when
+ using ordinary FTP. */
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ free(tmp);
+ if(result) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ }
+ else
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+ }
+ else if(cmd) {
+ /*
+ * the arguments following the command must be separated from the
+ * command with a space so we can check for it unconditionally
+ */
+ cp = strchr(cmd, ' ');
+ if(cp == NULL) {
+ failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+
+ /*
+ * also, every command takes at least one argument so we get that
+ * first argument right now
+ */
+ result = get_pathname(&cp, &sshc->quote_path1);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error: Bad first parameter");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+
+ /*
+ * SFTP is a binary protocol, so we don't send text commands
+ * to the server. Instead, we scan for commands used by
+ * OpenSSH's sftp program and call the appropriate libssh2
+ * functions.
+ */
+ if(curl_strnequal(cmd, "chgrp ", 6) ||
+ curl_strnequal(cmd, "chmod ", 6) ||
+ curl_strnequal(cmd, "chown ", 6) ) {
+ /* attribute change */
+
+ /* sshc->quote_path1 contains the mode to set */
+ /* get the destination */
+ result = get_pathname(&cp, &sshc->quote_path2);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error in chgrp/chmod/chown: "
+ "Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+ memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+ state(conn, SSH_SFTP_QUOTE_STAT);
+ break;
+ }
+ else if(curl_strnequal(cmd, "ln ", 3) ||
+ curl_strnequal(cmd, "symlink ", 8)) {
+ /* symbolic linking */
+ /* sshc->quote_path1 is the source */
+ /* get the destination */
+ result = get_pathname(&cp, &sshc->quote_path2);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data,
+ "Syntax error in ln/symlink: Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+ state(conn, SSH_SFTP_QUOTE_SYMLINK);
+ break;
+ }
+ else if(curl_strnequal(cmd, "mkdir ", 6)) {
+ /* create dir */
+ state(conn, SSH_SFTP_QUOTE_MKDIR);
+ break;
+ }
+ else if(curl_strnequal(cmd, "rename ", 7)) {
+ /* rename file */
+ /* first param is the source path */
+ /* second param is the dest. path */
+ result = get_pathname(&cp, &sshc->quote_path2);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error in rename: Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+ state(conn, SSH_SFTP_QUOTE_RENAME);
+ break;
+ }
+ else if(curl_strnequal(cmd, "rmdir ", 6)) {
+ /* delete dir */
+ state(conn, SSH_SFTP_QUOTE_RMDIR);
+ break;
+ }
+ else if(curl_strnequal(cmd, "rm ", 3)) {
+ state(conn, SSH_SFTP_QUOTE_UNLINK);
+ break;
+ }
+
+ failf(data, "Unknown SFTP command");
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+ if(!sshc->quote_item) {
+ state(conn, SSH_SFTP_TRANS_INIT);
+ }
+ break;
+
+ case SSH_SFTP_NEXT_QUOTE:
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+
+ sshc->quote_item = sshc->quote_item->next;
+
+ if(sshc->quote_item) {
+ state(conn, SSH_SFTP_QUOTE);
+ }
+ else {
+ if(sshc->nextstate != SSH_NO_STATE) {
+ state(conn, sshc->nextstate);
+ sshc->nextstate = SSH_NO_STATE;
+ }
+ else {
+ state(conn, SSH_SFTP_TRANS_INIT);
+ }
+ }
+ break;
+
+ case SSH_SFTP_QUOTE_STAT:
+ {
+ char *cmd = sshc->quote_item->data;
+ sshc->acceptfail = FALSE;
+
+ /* if a command starts with an asterisk, which a legal SFTP command never
+ can, the command will be allowed to fail without it causing any
+ aborts or cancels etc. It will cause libcurl to act as if the command
+ is successful, whatever the server reponds. */
+
+ if(cmd[0] == '*') {
+ cmd++;
+ sshc->acceptfail = TRUE;
+ }
+
+ if(!curl_strnequal(cmd, "chmod", 5)) {
+ /* Since chown and chgrp only set owner OR group but libssh2 wants to
+ * set them both at once, we need to obtain the current ownership
+ * first. This takes an extra protocol round trip.
+ */
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_STAT,
+ &sshc->quote_attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Attempt to get SFTP stats failed: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+
+ /* Now set the new attributes... */
+ if(curl_strnequal(cmd, "chgrp", 5)) {
+ sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
+ sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ !sshc->acceptfail) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: chgrp gid not a number");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+ else if(curl_strnequal(cmd, "chmod", 5)) {
+ sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
+ sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+ /* permissions are octal */
+ if(sshc->quote_attrs.permissions == 0 &&
+ !ISDIGIT(sshc->quote_path1[0])) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: chmod permissions not a number");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+ else if(curl_strnequal(cmd, "chown", 5)) {
+ sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
+ sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ !sshc->acceptfail) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: chown uid not a number");
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ }
+
+ /* Now send the completed structure... */
+ state(conn, SSH_SFTP_QUOTE_SETSTAT);
+ break;
+ }
+
+ case SSH_SFTP_QUOTE_SETSTAT:
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_SETSTAT,
+ &sshc->quote_attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Attempt to set SFTP stats failed: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_SYMLINK:
+ rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_SYMLINK);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "symlink command failed: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_MKDIR:
+ rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ data->set.new_directory_perms);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_RENAME:
+ rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_RENAME_OVERWRITE |
+ LIBSSH2_SFTP_RENAME_ATOMIC |
+ LIBSSH2_SFTP_RENAME_NATIVE);
+
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_RMDIR:
+ rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)));
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_QUOTE_UNLINK:
+ rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)));
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc != 0 && !sshc->acceptfail) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ state(conn, SSH_SFTP_NEXT_QUOTE);
+ break;
+
+ case SSH_SFTP_TRANS_INIT:
+ if(data->set.upload)
+ state(conn, SSH_SFTP_UPLOAD_INIT);
+ else {
+ if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
+ state(conn, SSH_SFTP_READDIR_INIT);
+ else
+ state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ }
+ break;
+
+ case SSH_SFTP_UPLOAD_INIT:
+ {
+ unsigned long flags;
+ /*
+ * NOTE!!! libssh2 requires that the destination path is a full path
+ * that includes the destination file and name OR ends in a "/"
+ * If this is not done the destination file will be named the
+ * same name as the last directory in the path.
+ */
+
+ if(data->state.resume_from != 0) {
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+ if(data->state.resume_from < 0) {
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ LIBSSH2_SFTP_STAT, &attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ data->state.resume_from = 0;
+ }
+ else {
+ curl_off_t size = attrs.filesize;
+ if(size < 0) {
+ failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ data->state.resume_from = attrs.filesize;
+ }
+ }
+ }
+
+ if(data->set.ftp_append)
+ /* Try to open for append, but create if nonexisting */
+ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
+ else if(data->state.resume_from > 0)
+ /* If we have restart position then open for append */
+ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
+ else
+ /* Clear file before writing (normal behaviour) */
+ flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
+
+ sshc->sftp_handle =
+ libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ flags, data->set.new_file_perms,
+ LIBSSH2_SFTP_OPENFILE);
+
+ if(!sshc->sftp_handle) {
+ rc = libssh2_session_last_errno(sshc->ssh_session);
+
+ if(LIBSSH2_ERROR_EAGAIN == rc)
+ break;
+ else {
+ if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
+ /* only when there was an SFTP protocol error can we extract
+ the sftp error! */
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ else
+ err = -1; /* not an sftp error at all */
+
+ if(sshc->secondCreateDirs) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = err>= LIBSSH2_FX_OK?
+ sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
+ failf(data, "Creating the dir/file failed: %s",
+ sftp_libssh2_strerror(err));
+ break;
+ }
+ else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
+ (err == LIBSSH2_FX_FAILURE) ||
+ (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
+ (data->set.ftp_create_missing_dirs &&
+ (strlen(sftp_scp->path) > 1))) {
+ /* try to create the path remotely */
+ sshc->secondCreateDirs = 1;
+ state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+ break;
+ }
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = err>= LIBSSH2_FX_OK?
+ sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
+ if(!sshc->actualcode) {
+ /* Sometimes, for some reason libssh2_sftp_last_error() returns
+ zero even though libssh2_sftp_open() failed previously! We need
+ to work around that! */
+ sshc->actualcode = CURLE_SSH;
+ err=-1;
+ }
+ failf(data, "Upload failed: %s (%d/%d)",
+ err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
+ err, rc);
+ break;
+ }
+ }
+
+ /* If we have a restart point then we need to seek to the correct
+ position. */
+ if(data->state.resume_from > 0) {
+ /* Let's read off the proper amount of bytes from the input. */
+ if(conn->seek_func) {
+ seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+ SEEK_SET);
+ }
+
+ if(seekerr != CURL_SEEKFUNC_OK) {
+
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+ do {
+ size_t readthisamountnow =
+ (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
+ BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ conn->fread_func(data->state.buffer, 1, readthisamountnow,
+ conn->fread_in);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Failed to read data");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ } while(passed < data->state.resume_from);
+ }
+ }
+
+ /* now, decrease the size of the read */
+ if(data->state.infilesize > 0) {
+ data->state.infilesize -= data->state.resume_from;
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+
+ SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
+ }
+ if(data->state.infilesize > 0) {
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+ /* upload data */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+
+ /* not set by Curl_setup_transfer to preserve keepon bits */
+ conn->sockfd = conn->writesockfd;
+
+ if(result) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = result;
+ }
+ else {
+ /* store this original bitmask setup to use later on if we can't
+ figure out a "real" bitmask */
+ sshc->orig_waitfor = data->req.keepon;
+
+ /* we want to use the _sending_ function even when the socket turns
+ out readable as the underlying libssh2 sftp send function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_OUT;
+
+ /* since we don't really wait for anything at this point, we want the
+ state machine to move on as soon as possible so we set a very short
+ timeout here */
+ Curl_expire(data, 1);
+
+ state(conn, SSH_STOP);
+ }
+ break;
+ }
+
+ case SSH_SFTP_CREATE_DIRS_INIT:
+ if(strlen(sftp_scp->path) > 1) {
+ sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
+ state(conn, SSH_SFTP_CREATE_DIRS);
+ }
+ else {
+ state(conn, SSH_SFTP_UPLOAD_INIT);
+ }
+ break;
+
+ case SSH_SFTP_CREATE_DIRS:
+ if((sshc->slash_pos = strchr(sshc->slash_pos, '/')) != NULL) {
+ *sshc->slash_pos = 0;
+
+ infof(data, "Creating directory '%s'\n", sftp_scp->path);
+ state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+ break;
+ }
+ else {
+ state(conn, SSH_SFTP_UPLOAD_INIT);
+ }
+ break;
+
+ case SSH_SFTP_CREATE_DIRS_MKDIR:
+ /* 'mode' - parameter is preliminary - default to 0644 */
+ rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ data->set.new_directory_perms);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ *sshc->slash_pos = '/';
+ ++sshc->slash_pos;
+ if(rc == -1) {
+ /*
+ * Abort if failure wasn't that the dir already exists or the
+ * permission was denied (creation might succeed further down the
+ * path) - retry on unspecific FAILURE also
+ */
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
+ (err != LIBSSH2_FX_FAILURE) &&
+ (err != LIBSSH2_FX_PERMISSION_DENIED)) {
+ result = sftp_libssh2_error_to_CURLE(err);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = result?result:CURLE_SSH;
+ break;
+ }
+ }
+ state(conn, SSH_SFTP_CREATE_DIRS);
+ break;
+
+ case SSH_SFTP_READDIR_INIT:
+ Curl_pgrsSetDownloadSize(data, -1);
+ if(data->set.opt_no_body) {
+ state(conn, SSH_STOP);
+ break;
+ }
+
+ /*
+ * This is a directory that we are trying to get, so produce a directory
+ * listing
+ */
+ sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
+ sftp_scp->path,
+ curlx_uztoui(
+ strlen(sftp_scp->path)),
+ 0, 0, LIBSSH2_SFTP_OPENDIR);
+ if(!sshc->sftp_handle) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ failf(data, "Could not open directory for reading: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ result = sftp_libssh2_error_to_CURLE(err);
+ sshc->actualcode = result?result:CURLE_SSH;
+ break;
+ }
+ }
+ if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
+ Curl_safefree(sshc->readdir_filename);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ state(conn, SSH_SFTP_READDIR);
+ break;
+
+ case SSH_SFTP_READDIR:
+ sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
+ sshc->readdir_filename,
+ PATH_MAX,
+ sshc->readdir_longentry,
+ PATH_MAX,
+ &sshc->readdir_attrs);
+ if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ if(sshc->readdir_len > 0) {
+ sshc->readdir_filename[sshc->readdir_len] = '\0';
+
+ if(data->set.ftp_list_only) {
+ char *tmpLine;
+
+ tmpLine = aprintf("%s\n", sshc->readdir_filename);
+ if(tmpLine == NULL) {
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ tmpLine, sshc->readdir_len+1);
+ Curl_safefree(tmpLine);
+
+ if(result) {
+ state(conn, SSH_STOP);
+ break;
+ }
+ /* since this counts what we send to the client, we include the
+ newline in this counter */
+ data->req.bytecount += sshc->readdir_len+1;
+
+ /* output debug output if that is requested */
+ if(data->set.verbose) {
+ Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
+ sshc->readdir_len, conn);
+ }
+ }
+ else {
+ sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+ sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
+ sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
+ if(!sshc->readdir_line) {
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ memcpy(sshc->readdir_line, sshc->readdir_longentry,
+ sshc->readdir_currLen);
+ if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
+ ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFLNK)) {
+ sshc->readdir_linkPath = malloc(PATH_MAX + 1);
+ if(sshc->readdir_linkPath == NULL) {
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
+ sshc->readdir_filename);
+ state(conn, SSH_SFTP_READDIR_LINK);
+ break;
+ }
+ state(conn, SSH_SFTP_READDIR_BOTTOM);
+ break;
+ }
+ }
+ else if(sshc->readdir_len == 0) {
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_READDIR_DONE);
+ break;
+ }
+ else if(sshc->readdir_len <= 0) {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ result = sftp_libssh2_error_to_CURLE(err);
+ sshc->actualcode = result?result:CURLE_SSH;
+ failf(data, "Could not open remote file for reading: %s :: %d",
+ sftp_libssh2_strerror(err),
+ libssh2_session_last_errno(sshc->ssh_session));
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_CLOSE);
+ break;
+ }
+ break;
+
+ case SSH_SFTP_READDIR_LINK:
+ sshc->readdir_len =
+ libssh2_sftp_symlink_ex(sshc->sftp_session,
+ sshc->readdir_linkPath,
+ curlx_uztoui(strlen(sshc->readdir_linkPath)),
+ sshc->readdir_filename,
+ PATH_MAX, LIBSSH2_SFTP_READLINK);
+ if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ Curl_safefree(sshc->readdir_linkPath);
+
+ /* get room for the filename and extra output */
+ sshc->readdir_totalLen += 4 + sshc->readdir_len;
+ new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen);
+ if(!new_readdir_line) {
+ Curl_safefree(sshc->readdir_line);
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ sshc->readdir_line = new_readdir_line;
+
+ sshc->readdir_currLen += snprintf(sshc->readdir_line +
+ sshc->readdir_currLen,
+ sshc->readdir_totalLen -
+ sshc->readdir_currLen,
+ " -> %s",
+ sshc->readdir_filename);
+
+ state(conn, SSH_SFTP_READDIR_BOTTOM);
+ break;
+
+ case SSH_SFTP_READDIR_BOTTOM:
+ sshc->readdir_currLen += snprintf(sshc->readdir_line +
+ sshc->readdir_currLen,
+ sshc->readdir_totalLen -
+ sshc->readdir_currLen, "\n");
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ sshc->readdir_line,
+ sshc->readdir_currLen);
+
+ if(result == CURLE_OK) {
+
+ /* output debug output if that is requested */
+ if(data->set.verbose) {
+ Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
+ sshc->readdir_currLen, conn);
+ }
+ data->req.bytecount += sshc->readdir_currLen;
+ }
+ Curl_safefree(sshc->readdir_line);
+ if(result) {
+ state(conn, SSH_STOP);
+ }
+ else
+ state(conn, SSH_SFTP_READDIR);
+ break;
+
+ case SSH_SFTP_READDIR_DONE:
+ if(libssh2_sftp_closedir(sshc->sftp_handle) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ sshc->sftp_handle = NULL;
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ state(conn, SSH_STOP);
+ break;
+
+ case SSH_SFTP_DOWNLOAD_INIT:
+ /*
+ * Work on getting the specified file
+ */
+ sshc->sftp_handle =
+ libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ LIBSSH2_FXF_READ, data->set.new_file_perms,
+ LIBSSH2_SFTP_OPENFILE);
+ if(!sshc->sftp_handle) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ err = sftp_libssh2_last_error(sshc->sftp_session);
+ failf(data, "Could not open remote file for reading: %s",
+ sftp_libssh2_strerror(err));
+ state(conn, SSH_SFTP_CLOSE);
+ result = sftp_libssh2_error_to_CURLE(err);
+ sshc->actualcode = result?result:CURLE_SSH;
+ break;
+ }
+ }
+ state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ break;
+
+ case SSH_SFTP_DOWNLOAD_STAT:
+ {
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
+ curlx_uztoui(strlen(sftp_scp->path)),
+ LIBSSH2_SFTP_STAT, &attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ /*
+ * libssh2_sftp_open() didn't return an error, so maybe the server
+ * just doesn't support stat()
+ */
+ data->req.size = -1;
+ data->req.maxdownload = -1;
+ Curl_pgrsSetDownloadSize(data, -1);
+ }
+ else {
+ curl_off_t size = attrs.filesize;
+
+ if(size < 0) {
+ failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ if(conn->data->state.use_range) {
+ curl_off_t from, to;
+ char *ptr;
+ char *ptr2;
+
+ from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
+ while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+ ptr++;
+ to=curlx_strtoofft(ptr, &ptr2, 0);
+ if((ptr == ptr2) /* no "to" value given */
+ || (to >= size)) {
+ to = size - 1;
+ }
+ if(from < 0) {
+ /* from is relative to end of file */
+ from += size;
+ }
+ if(from >= size) {
+ failf(data, "Offset (%"
+ CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
+ CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ if(from > to) {
+ from = to;
+ size = 0;
+ }
+ else {
+ size = to - from + 1;
+ }
+
+ SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
+ }
+ data->req.size = size;
+ data->req.maxdownload = size;
+ Curl_pgrsSetDownloadSize(data, size);
+ }
+
+ /* We can resume if we can seek to the resume position */
+ if(data->state.resume_from) {
+ if(data->state.resume_from < 0) {
+ /* We're supposed to download the last abs(from) bytes */
+ if((curl_off_t)attrs.filesize < -data->state.resume_from) {
+ failf(data, "Offset (%"
+ CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
+ CURL_FORMAT_CURL_OFF_T ")",
+ data->state.resume_from, attrs.filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ /* download from where? */
+ data->state.resume_from += attrs.filesize;
+ }
+ else {
+ if((curl_off_t)attrs.filesize < data->state.resume_from) {
+ failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
+ ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
+ data->state.resume_from, attrs.filesize);
+ return CURLE_BAD_DOWNLOAD_RESUME;
+ }
+ }
+ /* Does a completed file need to be seeked and started or closed ? */
+ /* Now store the number of bytes we are expected to download */
+ data->req.size = attrs.filesize - data->state.resume_from;
+ data->req.maxdownload = attrs.filesize - data->state.resume_from;
+ Curl_pgrsSetDownloadSize(data,
+ attrs.filesize - data->state.resume_from);
+ SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
+ }
+ }
+
+ /* Setup the actual download */
+ if(data->req.size == 0) {
+ /* no data to transfer */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ infof(data, "File already completely downloaded\n");
+ state(conn, SSH_STOP);
+ break;
+ }
+ else {
+ Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
+ FALSE, NULL, -1, NULL);
+
+ /* not set by Curl_setup_transfer to preserve keepon bits */
+ conn->writesockfd = conn->sockfd;
+
+ /* we want to use the _receiving_ function even when the socket turns
+ out writableable as the underlying libssh2 recv function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_IN;
+ }
+ if(result) {
+ /* this should never occur; the close state should be entered
+ at the time the error occurs */
+ state(conn, SSH_SFTP_CLOSE);
+ sshc->actualcode = result;
+ }
+ else {
+ state(conn, SSH_STOP);
+ }
+ break;
+
+ case SSH_SFTP_CLOSE:
+ if(sshc->sftp_handle) {
+ rc = libssh2_sftp_close(sshc->sftp_handle);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to close libssh2 file\n");
+ }
+ sshc->sftp_handle = NULL;
+ }
+ if(sftp_scp)
+ Curl_safefree(sftp_scp->path);
+
+ DEBUGF(infof(data, "SFTP DONE done\n"));
+
+ /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
+ After nextstate is executed,the control should come back to
+ SSH_SFTP_CLOSE to pass the correct result back */
+ if(sshc->nextstate != SSH_NO_STATE &&
+ sshc->nextstate != SSH_SFTP_CLOSE) {
+ state(conn, sshc->nextstate);
+ sshc->nextstate = SSH_SFTP_CLOSE;
+ }
+ else {
+ state(conn, SSH_STOP);
+ result = sshc->actualcode;
+ }
+ break;
+
+ case SSH_SFTP_SHUTDOWN:
+ /* during times we get here due to a broken transfer and then the
+ sftp_handle might not have been taken down so make sure that is done
+ before we proceed */
+
+ if(sshc->sftp_handle) {
+ rc = libssh2_sftp_close(sshc->sftp_handle);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to close libssh2 file\n");
+ }
+ sshc->sftp_handle = NULL;
+ }
+ if(sshc->sftp_session) {
+ rc = libssh2_sftp_shutdown(sshc->sftp_session);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to stop libssh2 sftp subsystem\n");
+ }
+ sshc->sftp_session = NULL;
+ }
+
+ Curl_safefree(sshc->homedir);
+ conn->data->state.most_recent_ftp_entrypath = NULL;
+
+ state(conn, SSH_SESSION_DISCONNECT);
+ break;
+
+ case SSH_SCP_TRANS_INIT:
+ result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ if(result) {
+ sshc->actualcode = result;
+ state(conn, SSH_STOP);
+ break;
+ }
+
+ if(data->set.upload) {
+ if(data->state.infilesize < 0) {
+ failf(data, "SCP requires a known file size for upload");
+ sshc->actualcode = CURLE_UPLOAD_FAILED;
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ break;
+ }
+ state(conn, SSH_SCP_UPLOAD_INIT);
+ }
+ else {
+ state(conn, SSH_SCP_DOWNLOAD_INIT);
+ }
+ break;
+
+ case SSH_SCP_UPLOAD_INIT:
+ /*
+ * libssh2 requires that the destination path is a full path that
+ * includes the destination file and name OR ends in a "/" . If this is
+ * not done the destination file will be named the same name as the last
+ * directory in the path.
+ */
+ sshc->ssh_channel =
+ SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
+ data->state.infilesize);
+ if(!sshc->ssh_channel) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ int ssh_err;
+ char *err_msg;
+
+ ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0));
+ failf(conn->data, "%s", err_msg);
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
+ break;
+ }
+ }
+
+ /* upload data */
+ Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
+ FIRSTSOCKET, NULL);
+
+ /* not set by Curl_setup_transfer to preserve keepon bits */
+ conn->sockfd = conn->writesockfd;
+
+ if(result) {
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ sshc->actualcode = result;
+ }
+ else {
+ /* store this original bitmask setup to use later on if we can't
+ figure out a "real" bitmask */
+ sshc->orig_waitfor = data->req.keepon;
+
+ /* we want to use the _sending_ function even when the socket turns
+ out readable as the underlying libssh2 scp send function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_OUT;
+
+ state(conn, SSH_STOP);
+ }
+ break;
+
+ case SSH_SCP_DOWNLOAD_INIT:
+ {
+ /*
+ * We must check the remote file; if it is a directory no values will
+ * be set in sb
+ */
+ struct stat sb;
+ curl_off_t bytecount;
+
+ /* clear the struct scp recv will fill in */
+ memset(&sb, 0, sizeof(struct stat));
+
+ /* get a fresh new channel from the ssh layer */
+ sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
+ sftp_scp->path, &sb);
+ if(!sshc->ssh_channel) {
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ rc = LIBSSH2_ERROR_EAGAIN;
+ break;
+ }
+ else {
+ int ssh_err;
+ char *err_msg;
+
+ ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0));
+ failf(conn->data, "%s", err_msg);
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
+ break;
+ }
+ }
+
+ /* download data */
+ bytecount = (curl_off_t)sb.st_size;
+ data->req.maxdownload = (curl_off_t)sb.st_size;
+ Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
+
+ /* not set by Curl_setup_transfer to preserve keepon bits */
+ conn->writesockfd = conn->sockfd;
+
+ /* we want to use the _receiving_ function even when the socket turns
+ out writableable as the underlying libssh2 recv function will deal
+ with both accordingly */
+ conn->cselect_bits = CURL_CSELECT_IN;
+
+ if(result) {
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ sshc->actualcode = result;
+ }
+ else
+ state(conn, SSH_STOP);
+ }
+ break;
+
+ case SSH_SCP_DONE:
+ if(data->set.upload)
+ state(conn, SSH_SCP_SEND_EOF);
+ else
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ break;
+
+ case SSH_SCP_SEND_EOF:
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_send_eof(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ infof(data, "Failed to send libssh2 channel EOF\n");
+ }
+ }
+ state(conn, SSH_SCP_WAIT_EOF);
+ break;
+
+ case SSH_SCP_WAIT_EOF:
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_wait_eof(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ infof(data, "Failed to get channel EOF: %d\n", rc);
+ }
+ }
+ state(conn, SSH_SCP_WAIT_CLOSE);
+ break;
+
+ case SSH_SCP_WAIT_CLOSE:
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_wait_closed(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc) {
+ infof(data, "Channel failed to close: %d\n", rc);
+ }
+ }
+ state(conn, SSH_SCP_CHANNEL_FREE);
+ break;
+
+ case SSH_SCP_CHANNEL_FREE:
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_free(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to free libssh2 scp subsystem\n");
+ }
+ sshc->ssh_channel = NULL;
+ }
+ DEBUGF(infof(data, "SCP DONE phase complete\n"));
+#if 0 /* PREV */
+ state(conn, SSH_SESSION_DISCONNECT);
+#endif
+ state(conn, SSH_STOP);
+ result = sshc->actualcode;
+ break;
+
+ case SSH_SESSION_DISCONNECT:
+ /* during weird times when we've been prematurely aborted, the channel
+ is still alive when we reach this state and we MUST kill the channel
+ properly first */
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_free(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to free libssh2 scp subsystem\n");
+ }
+ sshc->ssh_channel = NULL;
+ }
+
+ if(sshc->ssh_session) {
+ rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to disconnect libssh2 session\n");
+ }
+ }
+
+ Curl_safefree(sshc->homedir);
+ conn->data->state.most_recent_ftp_entrypath = NULL;
+
+ state(conn, SSH_SESSION_FREE);
+ break;
+
+ case SSH_SESSION_FREE:
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ if(sshc->kh) {
+ libssh2_knownhost_free(sshc->kh);
+ sshc->kh = NULL;
+ }
+#endif
+
+#ifdef HAVE_LIBSSH2_AGENT_API
+ if(sshc->ssh_agent) {
+ rc = libssh2_agent_disconnect(sshc->ssh_agent);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to disconnect from libssh2 agent\n");
+ }
+ libssh2_agent_free (sshc->ssh_agent);
+ sshc->ssh_agent = NULL;
+
+ /* NB: there is no need to free identities, they are part of internal
+ agent stuff */
+ sshc->sshagent_identity = NULL;
+ sshc->sshagent_prev_identity = NULL;
+ }
+#endif
+
+ if(sshc->ssh_session) {
+ rc = libssh2_session_free(sshc->ssh_session);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+ else if(rc < 0) {
+ infof(data, "Failed to free libssh2 session\n");
+ }
+ sshc->ssh_session = NULL;
+ }
+
+ /* worst-case scenario cleanup */
+
+ DEBUGASSERT(sshc->ssh_session == NULL);
+ DEBUGASSERT(sshc->ssh_channel == NULL);
+ DEBUGASSERT(sshc->sftp_session == NULL);
+ DEBUGASSERT(sshc->sftp_handle == NULL);
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ DEBUGASSERT(sshc->kh == NULL);
+#endif
+#ifdef HAVE_LIBSSH2_AGENT_API
+ DEBUGASSERT(sshc->ssh_agent == NULL);
+#endif
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+
+ Curl_safefree(sshc->homedir);
+
+ Curl_safefree(sshc->readdir_filename);
+ Curl_safefree(sshc->readdir_longentry);
+ Curl_safefree(sshc->readdir_line);
+ Curl_safefree(sshc->readdir_linkPath);
+
+ /* the code we are about to return */
+ result = sshc->actualcode;
+
+ memset(sshc, 0, sizeof(struct ssh_conn));
+
+ connclose(conn, "SSH session free");
+ sshc->state = SSH_SESSION_FREE; /* current */
+ sshc->nextstate = SSH_NO_STATE;
+ state(conn, SSH_STOP);
+ break;
+
+ case SSH_QUIT:
+ /* fallthrough, just stop! */
+ default:
+ /* internal error */
+ sshc->nextstate = SSH_NO_STATE;
+ state(conn, SSH_STOP);
+ break;
+ }
+
+ } while(!rc && (sshc->state != SSH_STOP));
+
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ /* we would block, we need to wait for the socket to be ready (in the
+ right direction too)! */
+ *block = TRUE;
+ }
+
+ return result;
+}
+
+/* called by the multi interface to figure out what socket(s) to wait for and
+ for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
+static int ssh_perform_getsock(const struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks
+ number of sockets */
+ int numsocks)
+{
+#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+ int bitmap = GETSOCK_BLANK;
+ (void)numsocks;
+
+ sock[0] = conn->sock[FIRSTSOCKET];
+
+ if(conn->waitfor & KEEP_RECV)
+ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+
+ if(conn->waitfor & KEEP_SEND)
+ bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
+
+ return bitmap;
+#else
+ /* if we don't know the direction we can use the generic *_getsock()
+ function even for the protocol_connect and doing states */
+ return Curl_single_getsock(conn, sock, numsocks);
+#endif
+}
+
+/* Generic function called by the multi interface to figure out what socket(s)
+ to wait for and for what actions during the DOING and PROTOCONNECT states*/
+static int ssh_getsock(struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks number
+ of sockets */
+ int numsocks)
+{
+#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+ (void)conn;
+ (void)sock;
+ (void)numsocks;
+ /* if we don't know any direction we can just play along as we used to and
+ not provide any sensible info */
+ return GETSOCK_BLANK;
+#else
+ /* if we know the direction we can use the generic *_getsock() function even
+ for the protocol_connect and doing states */
+ return ssh_perform_getsock(conn, sock, numsocks);
+#endif
+}
+
+#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+/*
+ * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
+ * function is used to figure out in what direction and stores this info so
+ * that the multi interface can take advantage of it. Make sure to call this
+ * function in all cases so that when it _doesn't_ return EAGAIN we can
+ * restore the default wait bits.
+ */
+static void ssh_block2waitfor(struct connectdata *conn, bool block)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ int dir;
+ if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
+ /* translate the libssh2 define bits into our own bit defines */
+ conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
+ ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
+ }
+ else
+ /* It didn't block or libssh2 didn't reveal in which direction, put back
+ the original set */
+ conn->waitfor = sshc->orig_waitfor;
+}
+#else
+ /* no libssh2 directional support so we simply don't know */
+#define ssh_block2waitfor(x,y) Curl_nop_stmt
+#endif
+
+/* called repeatedly until done from multi.c */
+static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ CURLcode result = CURLE_OK;
+ bool block; /* we store the status and use that to provide a ssh_getsock()
+ implementation */
+
+ result = ssh_statemach_act(conn, &block);
+ *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
+ ssh_block2waitfor(conn, block);
+
+ return result;
+}
+
+static CURLcode ssh_block_statemach(struct connectdata *conn,
+ bool duringconnect)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ while((sshc->state != SSH_STOP) && !result) {
+ bool block;
+ long left;
+
+ result = ssh_statemach_act(conn, &block);
+ if(result)
+ break;
+
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ else {
+ struct timeval now = Curl_tvnow();
+ result = Curl_speedcheck(data, now);
+ if(result)
+ break;
+ }
+
+ left = Curl_timeleft(data, NULL, duringconnect);
+ if(left < 0) {
+ failf(data, "Operation timed out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
+ if((CURLE_OK == result) && block) {
+ int dir = libssh2_session_block_directions(sshc->ssh_session);
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ curl_socket_t fd_read = CURL_SOCKET_BAD;
+ curl_socket_t fd_write = CURL_SOCKET_BAD;
+ if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
+ fd_read = sock;
+ if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
+ fd_write = sock;
+ /* wait for the socket to become ready */
+ Curl_socket_ready(fd_read, fd_write,
+ left>1000?1000:left); /* ignore result */
+ }
+#endif
+
+ }
+
+ return result;
+}
+
+/*
+ * SSH setup and connection
+ */
+static CURLcode ssh_setup_connection(struct connectdata *conn)
+{
+ struct SSHPROTO *ssh;
+
+ conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ if(!ssh)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+static Curl_recv scp_recv, sftp_recv;
+static Curl_send scp_send, sftp_send;
+
+/*
+ * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
+ * do protocol-specific actions at connect-time.
+ */
+static CURLcode ssh_connect(struct connectdata *conn, bool *done)
+{
+#ifdef CURL_LIBSSH2_DEBUG
+ curl_socket_t sock;
+#endif
+ struct ssh_conn *ssh;
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+
+ /* initialize per-handle data if not already */
+ if(!data->req.protop)
+ ssh_setup_connection(conn);
+
+ /* We default to persistent connections. We set this already in this connect
+ function to make the re-use checks properly be able to check this bit. */
+ connkeep(conn, "SSH default");
+
+ if(conn->handler->protocol & CURLPROTO_SCP) {
+ conn->recv[FIRSTSOCKET] = scp_recv;
+ conn->send[FIRSTSOCKET] = scp_send;
+ }
+ else {
+ conn->recv[FIRSTSOCKET] = sftp_recv;
+ conn->send[FIRSTSOCKET] = sftp_send;
+ }
+ ssh = &conn->proto.sshc;
+
+#ifdef CURL_LIBSSH2_DEBUG
+ if(conn->user) {
+ infof(data, "User: %s\n", conn->user);
+ }
+ if(conn->passwd) {
+ infof(data, "Password: %s\n", conn->passwd);
+ }
+ sock = conn->sock[FIRSTSOCKET];
+#endif /* CURL_LIBSSH2_DEBUG */
+
+ ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
+ my_libssh2_free,
+ my_libssh2_realloc, conn);
+ if(ssh->ssh_session == NULL) {
+ failf(data, "Failure initialising ssh session");
+ return CURLE_FAILED_INIT;
+ }
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
+ int rc;
+ ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
+ if(!ssh->kh) {
+ /* eeek. TODO: free the ssh_session! */
+ return CURLE_FAILED_INIT;
+ }
+
+ /* read all known hosts from there */
+ rc = libssh2_knownhost_readfile(ssh->kh,
+ data->set.str[STRING_SSH_KNOWNHOSTS],
+ LIBSSH2_KNOWNHOST_FILE_OPENSSH);
+ if(rc < 0)
+ infof(data, "Failed to read known hosts from %s\n",
+ data->set.str[STRING_SSH_KNOWNHOSTS]);
+ }
+#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
+
+#ifdef CURL_LIBSSH2_DEBUG
+ libssh2_trace(ssh->ssh_session, ~0);
+ infof(data, "SSH socket: %d\n", (int)sock);
+#endif /* CURL_LIBSSH2_DEBUG */
+
+ state(conn, SSH_INIT);
+
+ result = ssh_multi_statemach(conn, done);
+
+ return result;
+}
+
+/*
+ ***********************************************************************
+ *
+ * scp_perform()
+ *
+ * This is the actual DO function for SCP. Get a file according to
+ * the options previously setup.
+ */
+
+static
+CURLcode scp_perform(struct connectdata *conn,
+ bool *connected,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* start the first command in the DO phase */
+ state(conn, SSH_SCP_TRANS_INIT);
+
+ /* run the state-machine */
+ result = ssh_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/* called from multi.c while DOing */
+static CURLcode scp_doing(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result;
+ result = ssh_multi_statemach(conn, dophase_done);
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+ return result;
+}
+
+/*
+ * The DO function is generic for both protocols. There was previously two
+ * separate ones but this way means less duplicated code.
+ */
+
+static CURLcode ssh_do(struct connectdata *conn, bool *done)
+{
+ CURLcode res;
+ bool connected = 0;
+ struct SessionHandle *data = conn->data;
+ struct ssh_conn *sshc = &conn->proto.sshc;
+
+ *done = FALSE; /* default to false */
+
+ data->req.size = -1; /* make sure this is unknown at this point */
+
+ sshc->actualcode = CURLE_OK; /* reset error code */
+ sshc->secondCreateDirs =0; /* reset the create dir attempt state
+ variable */
+
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+ Curl_pgrsSetUploadSize(data, -1);
+ Curl_pgrsSetDownloadSize(data, -1);
+
+ if(conn->handler->protocol & CURLPROTO_SCP)
+ res = scp_perform(conn, &connected, done);
+ else
+ res = sftp_perform(conn, &connected, done);
+
+ return res;
+}
+
+/* BLOCKING, but the function is using the state machine so the only reason
+ this is still blocking is that the multi interface code has no support for
+ disconnecting operations that takes a while */
+static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ CURLcode result = CURLE_OK;
+ struct ssh_conn *ssh = &conn->proto.sshc;
+ (void) dead_connection;
+
+ Curl_safefree(conn->data->req.protop);
+
+ if(ssh->ssh_session) {
+ /* only if there's a session still around to use! */
+
+ state(conn, SSH_SESSION_DISCONNECT);
+
+ result = ssh_block_statemach(conn, FALSE);
+ }
+
+ return result;
+}
+
+/* generic done function for both SCP and SFTP called from their specific
+ done functions */
+static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
+{
+ CURLcode result = CURLE_OK;
+ struct SSHPROTO *sftp_scp = conn->data->req.protop;
+
+ if(status == CURLE_OK) {
+ /* run the state-machine
+
+ TODO: when the multi interface is used, this _really_ should be using
+ the ssh_multi_statemach function but we have no general support for
+ non-blocking DONE operations, not in the multi state machine and with
+ Curl_done() invokes on several places in the code!
+ */
+ result = ssh_block_statemach(conn, FALSE);
+ }
+ else
+ result = status;
+
+ if(sftp_scp)
+ Curl_safefree(sftp_scp->path);
+ if(Curl_pgrsDone(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+
+ conn->data->req.keepon = 0; /* clear all bits */
+ return result;
+}
+
+
+static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ (void)premature; /* not used */
+
+ if(status == CURLE_OK)
+ state(conn, SSH_SCP_DONE);
+
+ return ssh_done(conn, status);
+
+}
+
+/* return number of received (decrypted) bytes */
+static ssize_t scp_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, CURLcode *err)
+{
+ ssize_t nwrite;
+ (void)sockindex; /* we only support SCP on the fixed known primary socket */
+
+ /* libssh2_channel_write() returns int! */
+ nwrite = (ssize_t)
+ libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
+
+ ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+
+ if(nwrite == LIBSSH2_ERROR_EAGAIN) {
+ *err = CURLE_AGAIN;
+ nwrite = 0;
+ }
+ else if(nwrite < LIBSSH2_ERROR_NONE) {
+ *err = libssh2_session_error_to_CURLE((int)nwrite);
+ nwrite = -1;
+ }
+
+ return nwrite;
+}
+
+/*
+ * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
+ * a regular CURLcode value.
+ */
+static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err)
+{
+ ssize_t nread;
+ (void)sockindex; /* we only support SCP on the fixed known primary socket */
+
+ /* libssh2_channel_read() returns int */
+ nread = (ssize_t)
+ libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
+
+ ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ if(nread == LIBSSH2_ERROR_EAGAIN) {
+ *err = CURLE_AGAIN;
+ nread = -1;
+ }
+
+ return nread;
+}
+
+/*
+ * =============== SFTP ===============
+ */
+
+/*
+ ***********************************************************************
+ *
+ * sftp_perform()
+ *
+ * This is the actual DO function for SFTP. Get a file/directory according to
+ * the options previously setup.
+ */
+
+static
+CURLcode sftp_perform(struct connectdata *conn,
+ bool *connected,
+ bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+
+ DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+ *dophase_done = FALSE; /* not done yet */
+
+ /* start the first command in the DO phase */
+ state(conn, SSH_SFTP_QUOTE_INIT);
+
+ /* run the state-machine */
+ result = ssh_multi_statemach(conn, dophase_done);
+
+ *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+
+ return result;
+}
+
+/* called from multi.c while DOing */
+static CURLcode sftp_doing(struct connectdata *conn,
+ bool *dophase_done)
+{
+ CURLcode result;
+ result = ssh_multi_statemach(conn, dophase_done);
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+ return result;
+}
+
+/* BLOCKING, but the function is using the state machine so the only reason
+ this is still blocking is that the multi interface code has no support for
+ disconnecting operations that takes a while */
+static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ CURLcode result = CURLE_OK;
+ (void) dead_connection;
+
+ DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+
+ Curl_safefree(conn->data->req.protop);
+
+ if(conn->proto.sshc.ssh_session) {
+ /* only if there's a session still around to use! */
+ state(conn, SSH_SFTP_SHUTDOWN);
+ result = ssh_block_statemach(conn, FALSE);
+ }
+
+ DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+
+ return result;
+
+}
+
+static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ struct ssh_conn *sshc = &conn->proto.sshc;
+
+ if(status == CURLE_OK) {
+ /* Post quote commands are executed after the SFTP_CLOSE state to avoid
+ errors that could happen due to open file handles during POSTQUOTE
+ operation */
+ if(!status && !premature && conn->data->set.postquote) {
+ sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
+ state(conn, SSH_SFTP_CLOSE);
+ }
+ else
+ state(conn, SSH_SFTP_CLOSE);
+ }
+ return ssh_done(conn, status);
+}
+
+/* return number of sent bytes */
+static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, CURLcode *err)
+{
+ ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
+ but is changed to ssize_t in 0.15. These days we don't
+ support libssh2 0.15*/
+ (void)sockindex;
+
+ nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
+
+ ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+
+ if(nwrite == LIBSSH2_ERROR_EAGAIN) {
+ *err = CURLE_AGAIN;
+ nwrite = 0;
+ }
+ else if(nwrite < LIBSSH2_ERROR_NONE) {
+ *err = libssh2_session_error_to_CURLE((int)nwrite);
+ nwrite = -1;
+ }
+
+ return nwrite;
+}
+
+/*
+ * Return number of received (decrypted) bytes
+ * or <0 on error
+ */
+static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err)
+{
+ ssize_t nread;
+ (void)sockindex;
+
+ nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
+
+ ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+
+ if(nread == LIBSSH2_ERROR_EAGAIN) {
+ *err = CURLE_AGAIN;
+ nread = -1;
+
+ }
+ else if(nread < 0) {
+ *err = libssh2_session_error_to_CURLE((int)nread);
+ }
+ return nread;
+}
+
+/* The get_pathname() function is being borrowed from OpenSSH sftp.c
+ version 4.6p1. */
+/*
+ * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+static CURLcode
+get_pathname(const char **cpp, char **path)
+{
+ const char *cp = *cpp, *end;
+ char quot;
+ unsigned int i, j;
+ static const char WHITESPACE[] = " \t\r\n";
+
+ cp += strspn(cp, WHITESPACE);
+ if(!*cp) {
+ *cpp = cp;
+ *path = NULL;
+ return CURLE_QUOTE_ERROR;
+ }
+
+ *path = malloc(strlen(cp) + 1);
+ if(*path == NULL)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Check for quoted filenames */
+ if(*cp == '\"' || *cp == '\'') {
+ quot = *cp++;
+
+ /* Search for terminating quote, unescape some chars */
+ for(i = j = 0; i <= strlen(cp); i++) {
+ if(cp[i] == quot) { /* Found quote */
+ i++;
+ (*path)[j] = '\0';
+ break;
+ }
+ if(cp[i] == '\0') { /* End of string */
+ /*error("Unterminated quote");*/
+ goto fail;
+ }
+ if(cp[i] == '\\') { /* Escaped characters */
+ i++;
+ if(cp[i] != '\'' && cp[i] != '\"' &&
+ cp[i] != '\\') {
+ /*error("Bad escaped character '\\%c'",
+ cp[i]);*/
+ goto fail;
+ }
+ }
+ (*path)[j++] = cp[i];
+ }
+
+ if(j == 0) {
+ /*error("Empty quotes");*/
+ goto fail;
+ }
+ *cpp = cp + i + strspn(cp + i, WHITESPACE);
+ }
+ else {
+ /* Read to end of filename */
+ end = strpbrk(cp, WHITESPACE);
+ if(end == NULL)
+ end = strchr(cp, '\0');
+ *cpp = end + strspn(end, WHITESPACE);
+
+ memcpy(*path, cp, end - cp);
+ (*path)[end - cp] = '\0';
+ }
+ return CURLE_OK;
+
+ fail:
+ Curl_safefree(*path);
+ return CURLE_QUOTE_ERROR;
+}
+
+
+static const char *sftp_libssh2_strerror(int err)
+{
+ switch (err) {
+ case LIBSSH2_FX_NO_SUCH_FILE:
+ return "No such file or directory";
+
+ case LIBSSH2_FX_PERMISSION_DENIED:
+ return "Permission denied";
+
+ case LIBSSH2_FX_FAILURE:
+ return "Operation failed";
+
+ case LIBSSH2_FX_BAD_MESSAGE:
+ return "Bad message from SFTP server";
+
+ case LIBSSH2_FX_NO_CONNECTION:
+ return "Not connected to SFTP server";
+
+ case LIBSSH2_FX_CONNECTION_LOST:
+ return "Connection to SFTP server lost";
+
+ case LIBSSH2_FX_OP_UNSUPPORTED:
+ return "Operation not supported by SFTP server";
+
+ case LIBSSH2_FX_INVALID_HANDLE:
+ return "Invalid handle";
+
+ case LIBSSH2_FX_NO_SUCH_PATH:
+ return "No such file or directory";
+
+ case LIBSSH2_FX_FILE_ALREADY_EXISTS:
+ return "File already exists";
+
+ case LIBSSH2_FX_WRITE_PROTECT:
+ return "File is write protected";
+
+ case LIBSSH2_FX_NO_MEDIA:
+ return "No media";
+
+ case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
+ return "Disk full";
+
+ case LIBSSH2_FX_QUOTA_EXCEEDED:
+ return "User quota exceeded";
+
+ case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
+ return "Unknown principle";
+
+ case LIBSSH2_FX_LOCK_CONFlICT:
+ return "File lock conflict";
+
+ case LIBSSH2_FX_DIR_NOT_EMPTY:
+ return "Directory not empty";
+
+ case LIBSSH2_FX_NOT_A_DIRECTORY:
+ return "Not a directory";
+
+ case LIBSSH2_FX_INVALID_FILENAME:
+ return "Invalid filename";
+
+ case LIBSSH2_FX_LINK_LOOP:
+ return "Link points to itself";
+ }
+ return "Unknown error in libssh2";
+}
+
+#endif /* USE_LIBSSH2 */
diff --git a/external/libcurl_android/jni/libcurl/lib/ssh.h b/external/libcurl_android/jni/libcurl/lib/ssh.h
new file mode 100755
index 00000000..ff2e16be
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/ssh.h
@@ -0,0 +1,183 @@
+#ifndef HEADER_CURL_SSH_H
+#define HEADER_CURL_SSH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIBSSH2_H
+#include <libssh2.h>
+#include <libssh2_sftp.h>
+#endif /* HAVE_LIBSSH2_H */
+
+/****************************************************************************
+ * SSH unique setup
+ ***************************************************************************/
+typedef enum {
+ SSH_NO_STATE = -1, /* Used for "nextState" so say there is none */
+ SSH_STOP = 0, /* do nothing state, stops the state machine */
+
+ SSH_INIT, /* First state in SSH-CONNECT */
+ SSH_S_STARTUP, /* Session startup */
+ SSH_HOSTKEY, /* verify hostkey */
+ SSH_AUTHLIST,
+ SSH_AUTH_PKEY_INIT,
+ SSH_AUTH_PKEY,
+ SSH_AUTH_PASS_INIT,
+ SSH_AUTH_PASS,
+ SSH_AUTH_AGENT_INIT,/* initialize then wait for connection to agent */
+ SSH_AUTH_AGENT_LIST,/* ask for list then wait for entire list to come */
+ SSH_AUTH_AGENT, /* attempt one key at a time */
+ SSH_AUTH_HOST_INIT,
+ SSH_AUTH_HOST,
+ SSH_AUTH_KEY_INIT,
+ SSH_AUTH_KEY,
+ SSH_AUTH_DONE,
+ SSH_SFTP_INIT,
+ SSH_SFTP_REALPATH, /* Last state in SSH-CONNECT */
+
+ SSH_SFTP_QUOTE_INIT, /* First state in SFTP-DO */
+ SSH_SFTP_POSTQUOTE_INIT, /* (Possibly) First state in SFTP-DONE */
+ SSH_SFTP_QUOTE,
+ SSH_SFTP_NEXT_QUOTE,
+ SSH_SFTP_QUOTE_STAT,
+ SSH_SFTP_QUOTE_SETSTAT,
+ SSH_SFTP_QUOTE_SYMLINK,
+ SSH_SFTP_QUOTE_MKDIR,
+ SSH_SFTP_QUOTE_RENAME,
+ SSH_SFTP_QUOTE_RMDIR,
+ SSH_SFTP_QUOTE_UNLINK,
+ SSH_SFTP_TRANS_INIT,
+ SSH_SFTP_UPLOAD_INIT,
+ SSH_SFTP_CREATE_DIRS_INIT,
+ SSH_SFTP_CREATE_DIRS,
+ SSH_SFTP_CREATE_DIRS_MKDIR,
+ SSH_SFTP_READDIR_INIT,
+ SSH_SFTP_READDIR,
+ SSH_SFTP_READDIR_LINK,
+ SSH_SFTP_READDIR_BOTTOM,
+ SSH_SFTP_READDIR_DONE,
+ SSH_SFTP_DOWNLOAD_INIT,
+ SSH_SFTP_DOWNLOAD_STAT, /* Last state in SFTP-DO */
+ SSH_SFTP_CLOSE, /* Last state in SFTP-DONE */
+ SSH_SFTP_SHUTDOWN, /* First state in SFTP-DISCONNECT */
+ SSH_SCP_TRANS_INIT, /* First state in SCP-DO */
+ SSH_SCP_UPLOAD_INIT,
+ SSH_SCP_DOWNLOAD_INIT,
+ SSH_SCP_DONE,
+ SSH_SCP_SEND_EOF,
+ SSH_SCP_WAIT_EOF,
+ SSH_SCP_WAIT_CLOSE,
+ SSH_SCP_CHANNEL_FREE, /* Last state in SCP-DONE */
+ SSH_SESSION_DISCONNECT, /* First state in SCP-DISCONNECT */
+ SSH_SESSION_FREE, /* Last state in SCP/SFTP-DISCONNECT */
+ SSH_QUIT,
+ SSH_LAST /* never used */
+} sshstate;
+
+/* this struct is used in the HandleData struct which is part of the
+ SessionHandle, which means this is used on a per-easy handle basis.
+ Everything that is strictly related to a connection is banned from this
+ struct. */
+struct SSHPROTO {
+ char *path; /* the path we operate on */
+};
+
+/* ssh_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct ssh_conn {
+ const char *authlist; /* List of auth. methods, managed by libssh2 */
+#ifdef USE_LIBSSH2
+ const char *passphrase; /* pass-phrase to use */
+ char *rsa_pub; /* path name */
+ char *rsa; /* path name */
+ bool authed; /* the connection has been authenticated fine */
+ sshstate state; /* always use ssh.c:state() to change state! */
+ sshstate nextstate; /* the state to goto after stopping */
+ CURLcode actualcode; /* the actual error code */
+ struct curl_slist *quote_item; /* for the quote option */
+ char *quote_path1; /* two generic pointers for the QUOTE stuff */
+ char *quote_path2;
+ LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
+ bool acceptfail; /* used by the SFTP_QUOTE (continue if
+ quote command fails) */
+ char *homedir; /* when doing SFTP we figure out home dir in the
+ connect phase */
+
+ /* Here's a set of struct members used by the SFTP_READDIR state */
+ LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
+ char *readdir_filename;
+ char *readdir_longentry;
+ int readdir_len, readdir_totalLen, readdir_currLen;
+ char *readdir_line;
+ char *readdir_linkPath;
+ /* end of READDIR stuff */
+
+ int secondCreateDirs; /* counter use by the code to see if the
+ second attempt has been made to change
+ to/create a directory */
+ char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
+ LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
+ LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
+ LIBSSH2_SFTP *sftp_session; /* SFTP handle */
+ LIBSSH2_SFTP_HANDLE *sftp_handle;
+ int orig_waitfor; /* default READ/WRITE bits wait for */
+
+#ifdef HAVE_LIBSSH2_AGENT_API
+ LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */
+ struct libssh2_agent_publickey *sshagent_identity,
+ *sshagent_prev_identity;
+#endif
+
+ /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
+ header */
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ LIBSSH2_KNOWNHOSTS *kh;
+#endif
+#endif /* USE_LIBSSH2 */
+};
+
+#ifdef USE_LIBSSH2
+
+#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000)
+# error "SCP/SFTP protocols require libssh2 0.16 or later"
+#endif
+
+#if defined(LIBSSH2_VERSION_NUM) && (LIBSSH2_VERSION_NUM >= 0x010000)
+# define HAVE_LIBSSH2_SFTP_SEEK64 1
+#else
+# undef HAVE_LIBSSH2_SFTP_SEEK64
+#endif
+
+#if defined(LIBSSH2_VERSION_NUM) && (LIBSSH2_VERSION_NUM >= 0x010206)
+# define HAVE_LIBSSH2_SCP_SEND64 1
+#else
+# undef HAVE_LIBSSH2_SCP_SEND64
+#endif
+
+
+extern const struct Curl_handler Curl_handler_scp;
+extern const struct Curl_handler Curl_handler_sftp;
+
+#endif /* USE_LIBSSH2 */
+
+#endif /* HEADER_CURL_SSH_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/stamp-h1 b/external/libcurl_android/jni/libcurl/lib/stamp-h1
new file mode 100755
index 00000000..8f5adb6e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/stamp-h1
@@ -0,0 +1 @@
+timestamp for lib/curl_config.h
diff --git a/external/libcurl_android/jni/libcurl/lib/strdup.c b/external/libcurl_android/jni/libcurl/lib/strdup.c
new file mode 100755
index 00000000..3b776b18
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strdup.c
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ * This file is 'mem-include-scan' clean. See test 1132.
+ */
+#include "curl_setup.h"
+
+#include "strdup.h"
+
+#ifndef HAVE_STRDUP
+char *curlx_strdup(const char *str)
+{
+ size_t len;
+ char *newstr;
+
+ if(!str)
+ return (char *)NULL;
+
+ len = strlen(str);
+
+ if(len >= ((size_t)-1) / sizeof(char))
+ return (char *)NULL;
+
+ newstr = malloc((len+1)*sizeof(char));
+ if(!newstr)
+ return (char *)NULL;
+
+ memcpy(newstr,str,(len+1)*sizeof(char));
+
+ return newstr;
+
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/strdup.h b/external/libcurl_android/jni/libcurl/lib/strdup.h
new file mode 100755
index 00000000..49af9117
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strdup.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_STRDUP_H
+#define HEADER_CURL_STRDUP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef HAVE_STRDUP
+extern char *curlx_strdup(const char *str);
+#endif
+
+#endif /* HEADER_CURL_STRDUP_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/strequal.c b/external/libcurl_android/jni/libcurl/lib/strequal.c
new file mode 100755
index 00000000..5f2f508e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strequal.c
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include "strequal.h"
+
+/*
+ * @unittest: 1301
+ */
+int curl_strequal(const char *first, const char *second)
+{
+#if defined(HAVE_STRCASECMP)
+ return !(strcasecmp)(first, second);
+#elif defined(HAVE_STRCMPI)
+ return !(strcmpi)(first, second);
+#elif defined(HAVE_STRICMP)
+ return !(stricmp)(first, second);
+#else
+ while(*first && *second) {
+ if(toupper(*first) != toupper(*second)) {
+ break;
+ }
+ first++;
+ second++;
+ }
+ return toupper(*first) == toupper(*second);
+#endif
+}
+
+/*
+ * @unittest: 1301
+ */
+int curl_strnequal(const char *first, const char *second, size_t max)
+{
+#if defined(HAVE_STRNCASECMP)
+ return !strncasecmp(first, second, max);
+#elif defined(HAVE_STRNCMPI)
+ return !strncmpi(first, second, max);
+#elif defined(HAVE_STRNICMP)
+ return !strnicmp(first, second, max);
+#else
+ while(*first && *second && max) {
+ if(toupper(*first) != toupper(*second)) {
+ break;
+ }
+ max--;
+ first++;
+ second++;
+ }
+ if(0 == max)
+ return 1; /* they are equal this far */
+
+ return toupper(*first) == toupper(*second);
+#endif
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/strequal.h b/external/libcurl_android/jni/libcurl/lib/strequal.h
new file mode 100755
index 00000000..117a305b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strequal.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_STREQUAL_H
+#define HEADER_CURL_STREQUAL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+#define strequal(a,b) curl_strequal(a,b)
+#define strnequal(a,b,c) curl_strnequal(a,b,c)
+
+#endif /* HEADER_CURL_STREQUAL_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/strerror.c b/external/libcurl_android/jni/libcurl/lib/strerror.c
new file mode 100755
index 00000000..66033f21
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strerror.c
@@ -0,0 +1,1127 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2004 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_STRERROR_R
+# if (!defined(HAVE_POSIX_STRERROR_R) && \
+ !defined(HAVE_GLIBC_STRERROR_R) && \
+ !defined(HAVE_VXWORKS_STRERROR_R)) || \
+ (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \
+ (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \
+ (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
+# error "strerror_r MUST be either POSIX, glibc or vxworks-style"
+# endif
+#endif
+
+#include <curl/curl.h>
+
+#ifdef USE_LIBIDN
+#include <idna.h>
+#endif
+
+#include "strerror.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+const char *
+curl_easy_strerror(CURLcode error)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch (error) {
+ case CURLE_OK:
+ return "No error";
+
+ case CURLE_UNSUPPORTED_PROTOCOL:
+ return "Unsupported protocol";
+
+ case CURLE_FAILED_INIT:
+ return "Failed initialization";
+
+ case CURLE_URL_MALFORMAT:
+ return "URL using bad/illegal format or missing URL";
+
+ case CURLE_NOT_BUILT_IN:
+ return "A requested feature, protocol or option was not found built-in in"
+ " this libcurl due to a build-time decision.";
+
+ case CURLE_COULDNT_RESOLVE_PROXY:
+ return "Couldn't resolve proxy name";
+
+ case CURLE_COULDNT_RESOLVE_HOST:
+ return "Couldn't resolve host name";
+
+ case CURLE_COULDNT_CONNECT:
+ return "Couldn't connect to server";
+
+ case CURLE_FTP_WEIRD_SERVER_REPLY:
+ return "FTP: weird server reply";
+
+ case CURLE_REMOTE_ACCESS_DENIED:
+ return "Access denied to remote resource";
+
+ case CURLE_FTP_ACCEPT_FAILED:
+ return "FTP: The server failed to connect to data port";
+
+ case CURLE_FTP_ACCEPT_TIMEOUT:
+ return "FTP: Accepting server connect has timed out";
+
+ case CURLE_FTP_PRET_FAILED:
+ return "FTP: The server did not accept the PRET command.";
+
+ case CURLE_FTP_WEIRD_PASS_REPLY:
+ return "FTP: unknown PASS reply";
+
+ case CURLE_FTP_WEIRD_PASV_REPLY:
+ return "FTP: unknown PASV reply";
+
+ case CURLE_FTP_WEIRD_227_FORMAT:
+ return "FTP: unknown 227 response format";
+
+ case CURLE_FTP_CANT_GET_HOST:
+ return "FTP: can't figure out the host in the PASV response";
+
+ case CURLE_HTTP2:
+ return "Error in the HTTP2 framing layer";
+
+ case CURLE_FTP_COULDNT_SET_TYPE:
+ return "FTP: couldn't set file type";
+
+ case CURLE_PARTIAL_FILE:
+ return "Transferred a partial file";
+
+ case CURLE_FTP_COULDNT_RETR_FILE:
+ return "FTP: couldn't retrieve (RETR failed) the specified file";
+
+ case CURLE_QUOTE_ERROR:
+ return "Quote command returned error";
+
+ case CURLE_HTTP_RETURNED_ERROR:
+ return "HTTP response code said error";
+
+ case CURLE_WRITE_ERROR:
+ return "Failed writing received data to disk/application";
+
+ case CURLE_UPLOAD_FAILED:
+ return "Upload failed (at start/before it took off)";
+
+ case CURLE_READ_ERROR:
+ return "Failed to open/read local data from file/application";
+
+ case CURLE_OUT_OF_MEMORY:
+ return "Out of memory";
+
+ case CURLE_OPERATION_TIMEDOUT:
+ return "Timeout was reached";
+
+ case CURLE_FTP_PORT_FAILED:
+ return "FTP: command PORT failed";
+
+ case CURLE_FTP_COULDNT_USE_REST:
+ return "FTP: command REST failed";
+
+ case CURLE_RANGE_ERROR:
+ return "Requested range was not delivered by the server";
+
+ case CURLE_HTTP_POST_ERROR:
+ return "Internal problem setting up the POST";
+
+ case CURLE_SSL_CONNECT_ERROR:
+ return "SSL connect error";
+
+ case CURLE_BAD_DOWNLOAD_RESUME:
+ return "Couldn't resume download";
+
+ case CURLE_FILE_COULDNT_READ_FILE:
+ return "Couldn't read a file:// file";
+
+ case CURLE_LDAP_CANNOT_BIND:
+ return "LDAP: cannot bind";
+
+ case CURLE_LDAP_SEARCH_FAILED:
+ return "LDAP: search failed";
+
+ case CURLE_FUNCTION_NOT_FOUND:
+ return "A required function in the library was not found";
+
+ case CURLE_ABORTED_BY_CALLBACK:
+ return "Operation was aborted by an application callback";
+
+ case CURLE_BAD_FUNCTION_ARGUMENT:
+ return "A libcurl function was given a bad argument";
+
+ case CURLE_INTERFACE_FAILED:
+ return "Failed binding local connection end";
+
+ case CURLE_TOO_MANY_REDIRECTS :
+ return "Number of redirects hit maximum amount";
+
+ case CURLE_UNKNOWN_OPTION:
+ return "An unknown option was passed in to libcurl";
+
+ case CURLE_TELNET_OPTION_SYNTAX :
+ return "Malformed telnet option";
+
+ case CURLE_PEER_FAILED_VERIFICATION:
+ return "SSL peer certificate or SSH remote key was not OK";
+
+ case CURLE_GOT_NOTHING:
+ return "Server returned nothing (no headers, no data)";
+
+ case CURLE_SSL_ENGINE_NOTFOUND:
+ return "SSL crypto engine not found";
+
+ case CURLE_SSL_ENGINE_SETFAILED:
+ return "Can not set SSL crypto engine as default";
+
+ case CURLE_SSL_ENGINE_INITFAILED:
+ return "Failed to initialise SSL crypto engine";
+
+ case CURLE_SEND_ERROR:
+ return "Failed sending data to the peer";
+
+ case CURLE_RECV_ERROR:
+ return "Failure when receiving data from the peer";
+
+ case CURLE_SSL_CERTPROBLEM:
+ return "Problem with the local SSL certificate";
+
+ case CURLE_SSL_CIPHER:
+ return "Couldn't use specified SSL cipher";
+
+ case CURLE_SSL_CACERT:
+ return "Peer certificate cannot be authenticated with given CA "
+ "certificates";
+
+ case CURLE_SSL_CACERT_BADFILE:
+ return "Problem with the SSL CA cert (path? access rights?)";
+
+ case CURLE_BAD_CONTENT_ENCODING:
+ return "Unrecognized or bad HTTP Content or Transfer-Encoding";
+
+ case CURLE_LDAP_INVALID_URL:
+ return "Invalid LDAP URL";
+
+ case CURLE_FILESIZE_EXCEEDED:
+ return "Maximum file size exceeded";
+
+ case CURLE_USE_SSL_FAILED:
+ return "Requested SSL level failed";
+
+ case CURLE_SSL_SHUTDOWN_FAILED:
+ return "Failed to shut down the SSL connection";
+
+ case CURLE_SSL_CRL_BADFILE:
+ return "Failed to load CRL file (path? access rights?, format?)";
+
+ case CURLE_SSL_ISSUER_ERROR:
+ return "Issuer check against peer certificate failed";
+
+ case CURLE_SEND_FAIL_REWIND:
+ return "Send failed since rewinding of the data stream failed";
+
+ case CURLE_LOGIN_DENIED:
+ return "Login denied";
+
+ case CURLE_TFTP_NOTFOUND:
+ return "TFTP: File Not Found";
+
+ case CURLE_TFTP_PERM:
+ return "TFTP: Access Violation";
+
+ case CURLE_REMOTE_DISK_FULL:
+ return "Disk full or allocation exceeded";
+
+ case CURLE_TFTP_ILLEGAL:
+ return "TFTP: Illegal operation";
+
+ case CURLE_TFTP_UNKNOWNID:
+ return "TFTP: Unknown transfer ID";
+
+ case CURLE_REMOTE_FILE_EXISTS:
+ return "Remote file already exists";
+
+ case CURLE_TFTP_NOSUCHUSER:
+ return "TFTP: No such user";
+
+ case CURLE_CONV_FAILED:
+ return "Conversion failed";
+
+ case CURLE_CONV_REQD:
+ return "Caller must register CURLOPT_CONV_ callback options";
+
+ case CURLE_REMOTE_FILE_NOT_FOUND:
+ return "Remote file not found";
+
+ case CURLE_SSH:
+ return "Error in the SSH layer";
+
+ case CURLE_AGAIN:
+ return "Socket not ready for send/recv";
+
+ case CURLE_RTSP_CSEQ_ERROR:
+ return "RTSP CSeq mismatch or invalid CSeq";
+
+ case CURLE_RTSP_SESSION_ERROR:
+ return "RTSP session error";
+
+ case CURLE_FTP_BAD_FILE_LIST:
+ return "Unable to parse FTP file list";
+
+ case CURLE_CHUNK_FAILED:
+ return "Chunk callback failed";
+
+ case CURLE_NO_CONNECTION_AVAILABLE:
+ return "The max connection limit is reached";
+
+ /* error codes not used by current libcurl */
+ case CURLE_OBSOLETE20:
+ case CURLE_OBSOLETE24:
+ case CURLE_OBSOLETE29:
+ case CURLE_OBSOLETE32:
+ case CURLE_OBSOLETE40:
+ case CURLE_OBSOLETE44:
+ case CURLE_OBSOLETE46:
+ case CURLE_OBSOLETE50:
+ case CURLE_OBSOLETE57:
+ case CURL_LAST:
+ break;
+ }
+ /*
+ * By using a switch, gcc -Wall will complain about enum values
+ * which do not appear, helping keep this function up-to-date.
+ * By using gcc -Wall -Werror, you can't forget.
+ *
+ * A table would not have the same benefit. Most compilers will
+ * generate code very similar to a table in any case, so there
+ * is little performance gain from a table. And something is broken
+ * for the user's application, anyways, so does it matter how fast
+ * it _doesn't_ work?
+ *
+ * The line number for the error will be near this comment, which
+ * is why it is here, and not at the start of the switch.
+ */
+ return "Unknown error";
+#else
+ if(error == CURLE_OK)
+ return "No error";
+ else
+ return "Error";
+#endif
+}
+
+const char *
+curl_multi_strerror(CURLMcode error)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch (error) {
+ case CURLM_CALL_MULTI_PERFORM:
+ return "Please call curl_multi_perform() soon";
+
+ case CURLM_OK:
+ return "No error";
+
+ case CURLM_BAD_HANDLE:
+ return "Invalid multi handle";
+
+ case CURLM_BAD_EASY_HANDLE:
+ return "Invalid easy handle";
+
+ case CURLM_OUT_OF_MEMORY:
+ return "Out of memory";
+
+ case CURLM_INTERNAL_ERROR:
+ return "Internal error";
+
+ case CURLM_BAD_SOCKET:
+ return "Invalid socket argument";
+
+ case CURLM_UNKNOWN_OPTION:
+ return "Unknown option";
+
+ case CURLM_ADDED_ALREADY:
+ return "The easy handle is already added to a multi handle";
+
+ case CURLM_LAST:
+ break;
+ }
+
+ return "Unknown error";
+#else
+ if(error == CURLM_OK)
+ return "No error";
+ else
+ return "Error";
+#endif
+}
+
+const char *
+curl_share_strerror(CURLSHcode error)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch (error) {
+ case CURLSHE_OK:
+ return "No error";
+
+ case CURLSHE_BAD_OPTION:
+ return "Unknown share option";
+
+ case CURLSHE_IN_USE:
+ return "Share currently in use";
+
+ case CURLSHE_INVALID:
+ return "Invalid share handle";
+
+ case CURLSHE_NOMEM:
+ return "Out of memory";
+
+ case CURLSHE_NOT_BUILT_IN:
+ return "Feature not enabled in this library";
+
+ case CURLSHE_LAST:
+ break;
+ }
+
+ return "CURLSHcode unknown";
+#else
+ if(error == CURLSHE_OK)
+ return "No error";
+ else
+ return "Error";
+#endif
+}
+
+#ifdef USE_WINSOCK
+
+/* This function handles most / all (?) Winsock errors cURL is able to produce.
+ */
+static const char *
+get_winsock_error (int err, char *buf, size_t len)
+{
+ const char *p;
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch (err) {
+ case WSAEINTR:
+ p = "Call interrupted";
+ break;
+ case WSAEBADF:
+ p = "Bad file";
+ break;
+ case WSAEACCES:
+ p = "Bad access";
+ break;
+ case WSAEFAULT:
+ p = "Bad argument";
+ break;
+ case WSAEINVAL:
+ p = "Invalid arguments";
+ break;
+ case WSAEMFILE:
+ p = "Out of file descriptors";
+ break;
+ case WSAEWOULDBLOCK:
+ p = "Call would block";
+ break;
+ case WSAEINPROGRESS:
+ case WSAEALREADY:
+ p = "Blocking call in progress";
+ break;
+ case WSAENOTSOCK:
+ p = "Descriptor is not a socket";
+ break;
+ case WSAEDESTADDRREQ:
+ p = "Need destination address";
+ break;
+ case WSAEMSGSIZE:
+ p = "Bad message size";
+ break;
+ case WSAEPROTOTYPE:
+ p = "Bad protocol";
+ break;
+ case WSAENOPROTOOPT:
+ p = "Protocol option is unsupported";
+ break;
+ case WSAEPROTONOSUPPORT:
+ p = "Protocol is unsupported";
+ break;
+ case WSAESOCKTNOSUPPORT:
+ p = "Socket is unsupported";
+ break;
+ case WSAEOPNOTSUPP:
+ p = "Operation not supported";
+ break;
+ case WSAEAFNOSUPPORT:
+ p = "Address family not supported";
+ break;
+ case WSAEPFNOSUPPORT:
+ p = "Protocol family not supported";
+ break;
+ case WSAEADDRINUSE:
+ p = "Address already in use";
+ break;
+ case WSAEADDRNOTAVAIL:
+ p = "Address not available";
+ break;
+ case WSAENETDOWN:
+ p = "Network down";
+ break;
+ case WSAENETUNREACH:
+ p = "Network unreachable";
+ break;
+ case WSAENETRESET:
+ p = "Network has been reset";
+ break;
+ case WSAECONNABORTED:
+ p = "Connection was aborted";
+ break;
+ case WSAECONNRESET:
+ p = "Connection was reset";
+ break;
+ case WSAENOBUFS:
+ p = "No buffer space";
+ break;
+ case WSAEISCONN:
+ p = "Socket is already connected";
+ break;
+ case WSAENOTCONN:
+ p = "Socket is not connected";
+ break;
+ case WSAESHUTDOWN:
+ p = "Socket has been shut down";
+ break;
+ case WSAETOOMANYREFS:
+ p = "Too many references";
+ break;
+ case WSAETIMEDOUT:
+ p = "Timed out";
+ break;
+ case WSAECONNREFUSED:
+ p = "Connection refused";
+ break;
+ case WSAELOOP:
+ p = "Loop??";
+ break;
+ case WSAENAMETOOLONG:
+ p = "Name too long";
+ break;
+ case WSAEHOSTDOWN:
+ p = "Host down";
+ break;
+ case WSAEHOSTUNREACH:
+ p = "Host unreachable";
+ break;
+ case WSAENOTEMPTY:
+ p = "Not empty";
+ break;
+ case WSAEPROCLIM:
+ p = "Process limit reached";
+ break;
+ case WSAEUSERS:
+ p = "Too many users";
+ break;
+ case WSAEDQUOT:
+ p = "Bad quota";
+ break;
+ case WSAESTALE:
+ p = "Something is stale";
+ break;
+ case WSAEREMOTE:
+ p = "Remote error";
+ break;
+#ifdef WSAEDISCON /* missing in SalfordC! */
+ case WSAEDISCON:
+ p = "Disconnected";
+ break;
+#endif
+ /* Extended Winsock errors */
+ case WSASYSNOTREADY:
+ p = "Winsock library is not ready";
+ break;
+ case WSANOTINITIALISED:
+ p = "Winsock library not initialised";
+ break;
+ case WSAVERNOTSUPPORTED:
+ p = "Winsock version not supported";
+ break;
+
+ /* getXbyY() errors (already handled in herrmsg):
+ * Authoritative Answer: Host not found */
+ case WSAHOST_NOT_FOUND:
+ p = "Host not found";
+ break;
+
+ /* Non-Authoritative: Host not found, or SERVERFAIL */
+ case WSATRY_AGAIN:
+ p = "Host not found, try again";
+ break;
+
+ /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+ case WSANO_RECOVERY:
+ p = "Unrecoverable error in call to nameserver";
+ break;
+
+ /* Valid name, no data record of requested type */
+ case WSANO_DATA:
+ p = "No data record of requested type";
+ break;
+
+ default:
+ return NULL;
+ }
+#else
+ if(err == CURLE_OK)
+ return NULL;
+ else
+ p = "error";
+#endif
+ strncpy (buf, p, len);
+ buf [len-1] = '\0';
+ return buf;
+}
+#endif /* USE_WINSOCK */
+
+/*
+ * Our thread-safe and smart strerror() replacement.
+ *
+ * The 'err' argument passed in to this function MUST be a true errno number
+ * as reported on this system. We do no range checking on the number before
+ * we pass it to the "number-to-message" conversion function and there might
+ * be systems that don't do proper range checking in there themselves.
+ *
+ * We don't do range checking (on systems other than Windows) since there is
+ * no good reliable and portable way to do it.
+ */
+const char *Curl_strerror(struct connectdata *conn, int err)
+{
+ char *buf, *p;
+ size_t max;
+ int old_errno = ERRNO;
+
+ DEBUGASSERT(conn);
+ DEBUGASSERT(err >= 0);
+
+ buf = conn->syserr_buf;
+ max = sizeof(conn->syserr_buf)-1;
+ *buf = '\0';
+
+#ifdef USE_WINSOCK
+
+#ifdef _WIN32_WCE
+ {
+ wchar_t wbuf[256];
+ wbuf[0] = L'\0';
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
+ LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL);
+ wcstombs(buf,wbuf,max);
+ }
+#else
+ /* 'sys_nerr' is the maximum errno number, it is not widely portable */
+ if(err >= 0 && err < sys_nerr)
+ strncpy(buf, strerror(err), max);
+ else {
+ if(!get_winsock_error(err, buf, max) &&
+ !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
+ LANG_NEUTRAL, buf, (DWORD)max, NULL))
+ snprintf(buf, max, "Unknown error %d (%#x)", err, err);
+ }
+#endif
+
+#else /* not USE_WINSOCK coming up */
+
+#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
+ /*
+ * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
+ * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
+ * message string, or EINVAL if 'errnum' is not a valid error number.
+ */
+ if(0 != strerror_r(err, buf, max)) {
+ if('\0' == buf[0])
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
+ /*
+ * The glibc-style strerror_r() only *might* use the buffer we pass to
+ * the function, but it always returns the error message as a pointer,
+ * so we must copy that string unconditionally (if non-NULL).
+ */
+ {
+ char buffer[256];
+ char *msg = strerror_r(err, buffer, sizeof(buffer));
+ if(msg)
+ strncpy(buf, msg, max);
+ else
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)
+ /*
+ * The vxworks-style strerror_r() does use the buffer we pass to the function.
+ * The buffer size should be at least NAME_MAX (256)
+ */
+ {
+ char buffer[256];
+ if(OK == strerror_r(err, buffer))
+ strncpy(buf, buffer, max);
+ else
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#else
+ {
+ char *msg = strerror(err);
+ if(msg)
+ strncpy(buf, msg, max);
+ else
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#endif
+
+#endif /* end of ! USE_WINSOCK */
+
+ buf[max] = '\0'; /* make sure the string is zero terminated */
+
+ /* strip trailing '\r\n' or '\n'. */
+ if((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2)
+ *p = '\0';
+ if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1)
+ *p = '\0';
+
+ if(old_errno != ERRNO)
+ SET_ERRNO(old_errno);
+
+ return buf;
+}
+
+#ifdef USE_LIBIDN
+/*
+ * Return error-string for libidn status as returned from idna_to_ascii_lz().
+ */
+const char *Curl_idn_strerror (struct connectdata *conn, int err)
+{
+#ifdef HAVE_IDNA_STRERROR
+ (void)conn;
+ return idna_strerror((Idna_rc) err);
+#else
+ const char *str;
+ char *buf;
+ size_t max;
+
+ DEBUGASSERT(conn);
+
+ buf = conn->syserr_buf;
+ max = sizeof(conn->syserr_buf)-1;
+ *buf = '\0';
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ switch ((Idna_rc)err) {
+ case IDNA_SUCCESS:
+ str = "No error";
+ break;
+ case IDNA_STRINGPREP_ERROR:
+ str = "Error in string preparation";
+ break;
+ case IDNA_PUNYCODE_ERROR:
+ str = "Error in Punycode operation";
+ break;
+ case IDNA_CONTAINS_NON_LDH:
+ str = "Illegal ASCII characters";
+ break;
+ case IDNA_CONTAINS_MINUS:
+ str = "Contains minus";
+ break;
+ case IDNA_INVALID_LENGTH:
+ str = "Invalid output length";
+ break;
+ case IDNA_NO_ACE_PREFIX:
+ str = "No ACE prefix (\"xn--\")";
+ break;
+ case IDNA_ROUNDTRIP_VERIFY_ERROR:
+ str = "Round trip verify error";
+ break;
+ case IDNA_CONTAINS_ACE_PREFIX:
+ str = "Already have ACE prefix (\"xn--\")";
+ break;
+ case IDNA_ICONV_ERROR:
+ str = "Locale conversion failed";
+ break;
+ case IDNA_MALLOC_ERROR:
+ str = "Allocation failed";
+ break;
+ case IDNA_DLOPEN_ERROR:
+ str = "dlopen() error";
+ break;
+ default:
+ snprintf(buf, max, "error %d", err);
+ str = NULL;
+ break;
+ }
+#else
+ if((Idna_rc)err == IDNA_SUCCESS)
+ str = "No error";
+ else
+ str = "Error";
+#endif
+ if(str)
+ strncpy(buf, str, max);
+ buf[max] = '\0';
+ return (buf);
+#endif
+}
+#endif /* USE_LIBIDN */
+
+#ifdef USE_WINDOWS_SSPI
+const char *Curl_sspi_strerror (struct connectdata *conn, int err)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ char txtbuf[80];
+ char msgbuf[sizeof(conn->syserr_buf)];
+ char *p, *str, *msg = NULL;
+ bool msg_formatted = FALSE;
+ int old_errno;
+#endif
+ const char *txt;
+ char *outbuf;
+ size_t outmax;
+
+ DEBUGASSERT(conn);
+
+ outbuf = conn->syserr_buf;
+ outmax = sizeof(conn->syserr_buf)-1;
+ *outbuf = '\0';
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+
+ old_errno = ERRNO;
+
+ switch (err) {
+ case SEC_E_OK:
+ txt = "No error";
+ break;
+ case SEC_E_ALGORITHM_MISMATCH:
+ txt = "SEC_E_ALGORITHM_MISMATCH";
+ break;
+ case SEC_E_BAD_BINDINGS:
+ txt = "SEC_E_BAD_BINDINGS";
+ break;
+ case SEC_E_BAD_PKGID:
+ txt = "SEC_E_BAD_PKGID";
+ break;
+ case SEC_E_BUFFER_TOO_SMALL:
+ txt = "SEC_E_BUFFER_TOO_SMALL";
+ break;
+ case SEC_E_CANNOT_INSTALL:
+ txt = "SEC_E_CANNOT_INSTALL";
+ break;
+ case SEC_E_CANNOT_PACK:
+ txt = "SEC_E_CANNOT_PACK";
+ break;
+ case SEC_E_CERT_EXPIRED:
+ txt = "SEC_E_CERT_EXPIRED";
+ break;
+ case SEC_E_CERT_UNKNOWN:
+ txt = "SEC_E_CERT_UNKNOWN";
+ break;
+ case SEC_E_CERT_WRONG_USAGE:
+ txt = "SEC_E_CERT_WRONG_USAGE";
+ break;
+ case SEC_E_CONTEXT_EXPIRED:
+ txt = "SEC_E_CONTEXT_EXPIRED";
+ break;
+ case SEC_E_CROSSREALM_DELEGATION_FAILURE:
+ txt = "SEC_E_CROSSREALM_DELEGATION_FAILURE";
+ break;
+ case SEC_E_CRYPTO_SYSTEM_INVALID:
+ txt = "SEC_E_CRYPTO_SYSTEM_INVALID";
+ break;
+ case SEC_E_DECRYPT_FAILURE:
+ txt = "SEC_E_DECRYPT_FAILURE";
+ break;
+ case SEC_E_DELEGATION_POLICY:
+ txt = "SEC_E_DELEGATION_POLICY";
+ break;
+ case SEC_E_DELEGATION_REQUIRED:
+ txt = "SEC_E_DELEGATION_REQUIRED";
+ break;
+ case SEC_E_DOWNGRADE_DETECTED:
+ txt = "SEC_E_DOWNGRADE_DETECTED";
+ break;
+ case SEC_E_ENCRYPT_FAILURE:
+ txt = "SEC_E_ENCRYPT_FAILURE";
+ break;
+ case SEC_E_ILLEGAL_MESSAGE:
+ txt = "SEC_E_ILLEGAL_MESSAGE";
+ break;
+ case SEC_E_INCOMPLETE_CREDENTIALS:
+ txt = "SEC_E_INCOMPLETE_CREDENTIALS";
+ break;
+ case SEC_E_INCOMPLETE_MESSAGE:
+ txt = "SEC_E_INCOMPLETE_MESSAGE";
+ break;
+ case SEC_E_INSUFFICIENT_MEMORY:
+ txt = "SEC_E_INSUFFICIENT_MEMORY";
+ break;
+ case SEC_E_INTERNAL_ERROR:
+ txt = "SEC_E_INTERNAL_ERROR";
+ break;
+ case SEC_E_INVALID_HANDLE:
+ txt = "SEC_E_INVALID_HANDLE";
+ break;
+ case SEC_E_INVALID_PARAMETER:
+ txt = "SEC_E_INVALID_PARAMETER";
+ break;
+ case SEC_E_INVALID_TOKEN:
+ txt = "SEC_E_INVALID_TOKEN";
+ break;
+ case SEC_E_ISSUING_CA_UNTRUSTED:
+ txt = "SEC_E_ISSUING_CA_UNTRUSTED";
+ break;
+ case SEC_E_ISSUING_CA_UNTRUSTED_KDC:
+ txt = "SEC_E_ISSUING_CA_UNTRUSTED_KDC";
+ break;
+ case SEC_E_KDC_CERT_EXPIRED:
+ txt = "SEC_E_KDC_CERT_EXPIRED";
+ break;
+ case SEC_E_KDC_CERT_REVOKED:
+ txt = "SEC_E_KDC_CERT_REVOKED";
+ break;
+ case SEC_E_KDC_INVALID_REQUEST:
+ txt = "SEC_E_KDC_INVALID_REQUEST";
+ break;
+ case SEC_E_KDC_UNABLE_TO_REFER:
+ txt = "SEC_E_KDC_UNABLE_TO_REFER";
+ break;
+ case SEC_E_KDC_UNKNOWN_ETYPE:
+ txt = "SEC_E_KDC_UNKNOWN_ETYPE";
+ break;
+ case SEC_E_LOGON_DENIED:
+ txt = "SEC_E_LOGON_DENIED";
+ break;
+ case SEC_E_MAX_REFERRALS_EXCEEDED:
+ txt = "SEC_E_MAX_REFERRALS_EXCEEDED";
+ break;
+ case SEC_E_MESSAGE_ALTERED:
+ txt = "SEC_E_MESSAGE_ALTERED";
+ break;
+ case SEC_E_MULTIPLE_ACCOUNTS:
+ txt = "SEC_E_MULTIPLE_ACCOUNTS";
+ break;
+ case SEC_E_MUST_BE_KDC:
+ txt = "SEC_E_MUST_BE_KDC";
+ break;
+ case SEC_E_NOT_OWNER:
+ txt = "SEC_E_NOT_OWNER";
+ break;
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ txt = "SEC_E_NO_AUTHENTICATING_AUTHORITY";
+ break;
+ case SEC_E_NO_CREDENTIALS:
+ txt = "SEC_E_NO_CREDENTIALS";
+ break;
+ case SEC_E_NO_IMPERSONATION:
+ txt = "SEC_E_NO_IMPERSONATION";
+ break;
+ case SEC_E_NO_IP_ADDRESSES:
+ txt = "SEC_E_NO_IP_ADDRESSES";
+ break;
+ case SEC_E_NO_KERB_KEY:
+ txt = "SEC_E_NO_KERB_KEY";
+ break;
+ case SEC_E_NO_PA_DATA:
+ txt = "SEC_E_NO_PA_DATA";
+ break;
+ case SEC_E_NO_S4U_PROT_SUPPORT:
+ txt = "SEC_E_NO_S4U_PROT_SUPPORT";
+ break;
+ case SEC_E_NO_TGT_REPLY:
+ txt = "SEC_E_NO_TGT_REPLY";
+ break;
+ case SEC_E_OUT_OF_SEQUENCE:
+ txt = "SEC_E_OUT_OF_SEQUENCE";
+ break;
+ case SEC_E_PKINIT_CLIENT_FAILURE:
+ txt = "SEC_E_PKINIT_CLIENT_FAILURE";
+ break;
+ case SEC_E_PKINIT_NAME_MISMATCH:
+ txt = "SEC_E_PKINIT_NAME_MISMATCH";
+ break;
+ case SEC_E_POLICY_NLTM_ONLY:
+ txt = "SEC_E_POLICY_NLTM_ONLY";
+ break;
+ case SEC_E_QOP_NOT_SUPPORTED:
+ txt = "SEC_E_QOP_NOT_SUPPORTED";
+ break;
+ case SEC_E_REVOCATION_OFFLINE_C:
+ txt = "SEC_E_REVOCATION_OFFLINE_C";
+ break;
+ case SEC_E_REVOCATION_OFFLINE_KDC:
+ txt = "SEC_E_REVOCATION_OFFLINE_KDC";
+ break;
+ case SEC_E_SECPKG_NOT_FOUND:
+ txt = "SEC_E_SECPKG_NOT_FOUND";
+ break;
+ case SEC_E_SECURITY_QOS_FAILED:
+ txt = "SEC_E_SECURITY_QOS_FAILED";
+ break;
+ case SEC_E_SHUTDOWN_IN_PROGRESS:
+ txt = "SEC_E_SHUTDOWN_IN_PROGRESS";
+ break;
+ case SEC_E_SMARTCARD_CERT_EXPIRED:
+ txt = "SEC_E_SMARTCARD_CERT_EXPIRED";
+ break;
+ case SEC_E_SMARTCARD_CERT_REVOKED:
+ txt = "SEC_E_SMARTCARD_CERT_REVOKED";
+ break;
+ case SEC_E_SMARTCARD_LOGON_REQUIRED:
+ txt = "SEC_E_SMARTCARD_LOGON_REQUIRED";
+ break;
+ case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
+ txt = "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED";
+ break;
+ case SEC_E_TARGET_UNKNOWN:
+ txt = "SEC_E_TARGET_UNKNOWN";
+ break;
+ case SEC_E_TIME_SKEW:
+ txt = "SEC_E_TIME_SKEW";
+ break;
+ case SEC_E_TOO_MANY_PRINCIPALS:
+ txt = "SEC_E_TOO_MANY_PRINCIPALS";
+ break;
+ case SEC_E_UNFINISHED_CONTEXT_DELETED:
+ txt = "SEC_E_UNFINISHED_CONTEXT_DELETED";
+ break;
+ case SEC_E_UNKNOWN_CREDENTIALS:
+ txt = "SEC_E_UNKNOWN_CREDENTIALS";
+ break;
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ txt = "SEC_E_UNSUPPORTED_FUNCTION";
+ break;
+ case SEC_E_UNSUPPORTED_PREAUTH:
+ txt = "SEC_E_UNSUPPORTED_PREAUTH";
+ break;
+ case SEC_E_UNTRUSTED_ROOT:
+ txt = "SEC_E_UNTRUSTED_ROOT";
+ break;
+ case SEC_E_WRONG_CREDENTIAL_HANDLE:
+ txt = "SEC_E_WRONG_CREDENTIAL_HANDLE";
+ break;
+ case SEC_E_WRONG_PRINCIPAL:
+ txt = "SEC_E_WRONG_PRINCIPAL";
+ break;
+ case SEC_I_COMPLETE_AND_CONTINUE:
+ txt = "SEC_I_COMPLETE_AND_CONTINUE";
+ break;
+ case SEC_I_COMPLETE_NEEDED:
+ txt = "SEC_I_COMPLETE_NEEDED";
+ break;
+ case SEC_I_CONTEXT_EXPIRED:
+ txt = "SEC_I_CONTEXT_EXPIRED";
+ break;
+ case SEC_I_CONTINUE_NEEDED:
+ txt = "SEC_I_CONTINUE_NEEDED";
+ break;
+ case SEC_I_INCOMPLETE_CREDENTIALS:
+ txt = "SEC_I_INCOMPLETE_CREDENTIALS";
+ break;
+ case SEC_I_LOCAL_LOGON:
+ txt = "SEC_I_LOCAL_LOGON";
+ break;
+ case SEC_I_NO_LSA_CONTEXT:
+ txt = "SEC_I_NO_LSA_CONTEXT";
+ break;
+ case SEC_I_RENEGOTIATE:
+ txt = "SEC_I_RENEGOTIATE";
+ break;
+ case SEC_I_SIGNATURE_NEEDED:
+ txt = "SEC_I_SIGNATURE_NEEDED";
+ break;
+ default:
+ txt = "Unknown error";
+ }
+
+ if(err == SEC_E_OK)
+ strncpy(outbuf, txt, outmax);
+ else {
+ str = txtbuf;
+ snprintf(txtbuf, sizeof(txtbuf), "%s (0x%04X%04X)",
+ txt, (err >> 16) & 0xffff, err & 0xffff);
+ txtbuf[sizeof(txtbuf)-1] = '\0';
+
+#ifdef _WIN32_WCE
+ {
+ wchar_t wbuf[256];
+ wbuf[0] = L'\0';
+
+ if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, LANG_NEUTRAL,
+ wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
+ wcstombs(msgbuf,wbuf,sizeof(msgbuf)-1);
+ msg_formatted = TRUE;
+ }
+ }
+#else
+ if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, LANG_NEUTRAL,
+ msgbuf, sizeof(msgbuf)-1, NULL)) {
+ msg_formatted = TRUE;
+ }
+#endif
+ if(msg_formatted) {
+ msgbuf[sizeof(msgbuf)-1] = '\0';
+ /* strip trailing '\r\n' or '\n' */
+ if((p = strrchr(msgbuf,'\n')) != NULL && (p - msgbuf) >= 2)
+ *p = '\0';
+ if((p = strrchr(msgbuf,'\r')) != NULL && (p - msgbuf) >= 1)
+ *p = '\0';
+ msg = msgbuf;
+ }
+ if(msg)
+ snprintf(outbuf, outmax, "%s - %s", str, msg);
+ else
+ strncpy(outbuf, str, outmax);
+ }
+
+ if(old_errno != ERRNO)
+ SET_ERRNO(old_errno);
+
+#else
+
+ if(err == SEC_E_OK)
+ txt = "No error";
+ else
+ txt = "Error";
+
+ strncpy(outbuf, txt, outmax);
+
+#endif
+
+ outbuf[outmax] = '\0';
+
+ return outbuf;
+}
+#endif /* USE_WINDOWS_SSPI */
diff --git a/external/libcurl_android/jni/libcurl/lib/strerror.h b/external/libcurl_android/jni/libcurl/lib/strerror.h
new file mode 100755
index 00000000..f1b22210
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strerror.h
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_STRERROR_H
+#define HEADER_CURL_STRERROR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "urldata.h"
+
+const char *Curl_strerror (struct connectdata *conn, int err);
+
+#ifdef USE_LIBIDN
+const char *Curl_idn_strerror (struct connectdata *conn, int err);
+#endif
+
+#ifdef USE_WINDOWS_SSPI
+const char *Curl_sspi_strerror (struct connectdata *conn, int err);
+#endif
+
+#endif /* HEADER_CURL_STRERROR_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/strtok.c b/external/libcurl_android/jni/libcurl/lib/strtok.c
new file mode 100755
index 00000000..0d31351f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strtok.c
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef HAVE_STRTOK_R
+#include <stddef.h>
+
+#include "strtok.h"
+
+char *
+Curl_strtok_r(char *ptr, const char *sep, char **end)
+{
+ if(!ptr)
+ /* we got NULL input so then we get our last position instead */
+ ptr = *end;
+
+ /* pass all letters that are including in the separator string */
+ while(*ptr && strchr(sep, *ptr))
+ ++ptr;
+
+ if(*ptr) {
+ /* so this is where the next piece of string starts */
+ char *start = ptr;
+
+ /* set the end pointer to the first byte after the start */
+ *end = start + 1;
+
+ /* scan through the string to find where it ends, it ends on a
+ null byte or a character that exists in the separator string */
+ while(**end && !strchr(sep, **end))
+ ++*end;
+
+ if(**end) {
+ /* the end is not a null byte */
+ **end = '\0'; /* zero terminate it! */
+ ++*end; /* advance the last pointer to beyond the null byte */
+ }
+
+ return start; /* return the position where the string starts */
+ }
+
+ /* we ended up on a null byte, there are no more strings to find! */
+ return NULL;
+}
+
+#endif /* this was only compiled if strtok_r wasn't present */
diff --git a/external/libcurl_android/jni/libcurl/lib/strtok.h b/external/libcurl_android/jni/libcurl/lib/strtok.h
new file mode 100755
index 00000000..1147d70d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strtok.h
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_STRTOK_H
+#define HEADER_CURL_STRTOK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+#include <stddef.h>
+
+#ifndef HAVE_STRTOK_R
+char *Curl_strtok_r(char *s, const char *delim, char **last);
+#define strtok_r Curl_strtok_r
+#else
+#include <string.h>
+#endif
+
+#endif /* HEADER_CURL_STRTOK_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/strtoofft.c b/external/libcurl_android/jni/libcurl/lib/strtoofft.c
new file mode 100755
index 00000000..03a97e8c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strtoofft.c
@@ -0,0 +1,188 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "strtoofft.h"
+
+/*
+ * NOTE:
+ *
+ * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we
+ * could use in case strtoll() doesn't exist... See
+ * http://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
+ */
+
+#ifdef NEED_CURL_STRTOLL
+
+/* Range tests can be used for alphanum decoding if characters are consecutive,
+ like in ASCII. Else an array is scanned. Determine this condition now. */
+
+#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
+
+#define NO_RANGE_TEST
+
+static const char valchars[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+#endif
+
+static int get_char(char c, int base);
+
+/**
+ * Emulated version of the strtoll function. This extracts a long long
+ * value from the given input string and returns it.
+ */
+curl_off_t
+curlx_strtoll(const char *nptr, char **endptr, int base)
+{
+ char *end;
+ int is_negative = 0;
+ int overflow;
+ int i;
+ curl_off_t value = 0;
+ curl_off_t newval;
+
+ /* Skip leading whitespace. */
+ end = (char *)nptr;
+ while(ISSPACE(end[0])) {
+ end++;
+ }
+
+ /* Handle the sign, if any. */
+ if(end[0] == '-') {
+ is_negative = 1;
+ end++;
+ }
+ else if(end[0] == '+') {
+ end++;
+ }
+ else if(end[0] == '\0') {
+ /* We had nothing but perhaps some whitespace -- there was no number. */
+ if(endptr) {
+ *endptr = end;
+ }
+ return 0;
+ }
+
+ /* Handle special beginnings, if present and allowed. */
+ if(end[0] == '0' && end[1] == 'x') {
+ if(base == 16 || base == 0) {
+ end += 2;
+ base = 16;
+ }
+ }
+ else if(end[0] == '0') {
+ if(base == 8 || base == 0) {
+ end++;
+ base = 8;
+ }
+ }
+
+ /* Matching strtol, if the base is 0 and it doesn't look like
+ * the number is octal or hex, we assume it's base 10.
+ */
+ if(base == 0) {
+ base = 10;
+ }
+
+ /* Loop handling digits. */
+ value = 0;
+ overflow = 0;
+ for(i = get_char(end[0], base);
+ i != -1;
+ end++, i = get_char(end[0], base)) {
+ newval = base * value + i;
+ if(newval < value) {
+ /* We've overflowed. */
+ overflow = 1;
+ break;
+ }
+ else
+ value = newval;
+ }
+
+ if(!overflow) {
+ if(is_negative) {
+ /* Fix the sign. */
+ value *= -1;
+ }
+ }
+ else {
+ if(is_negative)
+ value = CURL_OFF_T_MIN;
+ else
+ value = CURL_OFF_T_MAX;
+
+ SET_ERRNO(ERANGE);
+ }
+
+ if(endptr)
+ *endptr = end;
+
+ return value;
+}
+
+/**
+ * Returns the value of c in the given base, or -1 if c cannot
+ * be interpreted properly in that base (i.e., is out of range,
+ * is a null, etc.).
+ *
+ * @param c the character to interpret according to base
+ * @param base the base in which to interpret c
+ *
+ * @return the value of c in base, or -1 if c isn't in range
+ */
+static int get_char(char c, int base)
+{
+#ifndef NO_RANGE_TEST
+ int value = -1;
+ if(c <= '9' && c >= '0') {
+ value = c - '0';
+ }
+ else if(c <= 'Z' && c >= 'A') {
+ value = c - 'A' + 10;
+ }
+ else if(c <= 'z' && c >= 'a') {
+ value = c - 'a' + 10;
+ }
+#else
+ const char * cp;
+ int value;
+
+ cp = memchr(valchars, c, 10 + 26 + 26);
+
+ if(!cp)
+ return -1;
+
+ value = cp - valchars;
+
+ if(value >= 10 + 26)
+ value -= 26; /* Lowercase. */
+#endif
+
+ if(value >= base) {
+ value = -1;
+ }
+
+ return value;
+}
+#endif /* Only present if we need strtoll, but don't have it. */
diff --git a/external/libcurl_android/jni/libcurl/lib/strtoofft.h b/external/libcurl_android/jni/libcurl/lib/strtoofft.h
new file mode 100755
index 00000000..b812a67a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/strtoofft.h
@@ -0,0 +1,68 @@
+#ifndef HEADER_CURL_STRTOOFFT_H
+#define HEADER_CURL_STRTOOFFT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+/*
+ * Determine which string to integral data type conversion function we use
+ * to implement string conversion to our curl_off_t integral data type.
+ *
+ * Notice that curl_off_t might be 64 or 32 bit wide, and that it might use
+ * an underlying data type which might be 'long', 'int64_t', 'long long' or
+ * '__int64' and more remotely other data types.
+ *
+ * On systems where the size of curl_off_t is greater than the size of 'long'
+ * the conversion function to use is strtoll() if it is available, otherwise,
+ * we emulate its functionality with our own clone.
+ *
+ * On systems where the size of curl_off_t is smaller or equal than the size
+ * of 'long' the conversion function to use is strtol().
+ */
+
+#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+# ifdef HAVE_STRTOLL
+# define curlx_strtoofft strtoll
+# else
+# if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
+ _CRTIMP __int64 __cdecl _strtoi64(const char *, char **, int);
+# define curlx_strtoofft _strtoi64
+# else
+ curl_off_t curlx_strtoll(const char *nptr, char **endptr, int base);
+# define curlx_strtoofft curlx_strtoll
+# define NEED_CURL_STRTOLL 1
+# endif
+# endif
+#else
+# define curlx_strtoofft strtol
+#endif
+
+#if (CURL_SIZEOF_CURL_OFF_T == 4)
+# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
+#else
+ /* assume CURL_SIZEOF_CURL_OFF_T == 8 */
+# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
+#endif
+#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
+
+#endif /* HEADER_CURL_STRTOOFFT_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/telnet.c b/external/libcurl_android/jni/libcurl/lib/telnet.c
new file mode 100755
index 00000000..1f03a00f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/telnet.c
@@ -0,0 +1,1680 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_TELNET
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+#include "telnet.h"
+#include "connect.h"
+#include "progress.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#define TELOPTS
+#define TELCMDS
+
+#include "arpa_telnet.h"
+#include "curl_memory.h"
+#include "select.h"
+#include "strequal.h"
+#include "rawstr.h"
+#include "warnless.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#define SUBBUFSIZE 512
+
+#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer
+#define CURL_SB_TERM(x) \
+ do { \
+ x->subend = x->subpointer; \
+ CURL_SB_CLEAR(x); \
+ } WHILE_FALSE
+#define CURL_SB_ACCUM(x,c) \
+ do { \
+ if(x->subpointer < (x->subbuffer+sizeof x->subbuffer)) \
+ *x->subpointer++ = (c); \
+ } WHILE_FALSE
+
+#define CURL_SB_GET(x) ((*x->subpointer++)&0xff)
+#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
+#define CURL_SB_EOF(x) (x->subpointer >= x->subend)
+#define CURL_SB_LEN(x) (x->subend - x->subpointer)
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+#define printoption(a,b,c,d) Curl_nop_stmt
+#endif
+
+#ifdef USE_WINSOCK
+typedef FARPROC WSOCK2_FUNC;
+static CURLcode check_wsock2 ( struct SessionHandle *data );
+#endif
+
+static
+CURLcode telrcv(struct connectdata *,
+ const unsigned char *inbuf, /* Data received from socket */
+ ssize_t count); /* Number of bytes received */
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void printoption(struct SessionHandle *data,
+ const char *direction,
+ int cmd, int option);
+#endif
+
+static void negotiate(struct connectdata *);
+static void send_negotiation(struct connectdata *, int cmd, int option);
+static void set_local_option(struct connectdata *, int cmd, int option);
+static void set_remote_option(struct connectdata *, int cmd, int option);
+
+static void printsub(struct SessionHandle *data,
+ int direction, unsigned char *pointer,
+ size_t length);
+static void suboption(struct connectdata *);
+static void sendsuboption(struct connectdata *conn, int option);
+
+static CURLcode telnet_do(struct connectdata *conn, bool *done);
+static CURLcode telnet_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode send_telnet_data(struct connectdata *conn,
+ char *buffer, ssize_t nread);
+
+/* For negotiation compliant to RFC 1143 */
+#define CURL_NO 0
+#define CURL_YES 1
+#define CURL_WANTYES 2
+#define CURL_WANTNO 3
+
+#define CURL_EMPTY 0
+#define CURL_OPPOSITE 1
+
+/*
+ * Telnet receiver states for fsm
+ */
+typedef enum
+{
+ CURL_TS_DATA = 0,
+ CURL_TS_IAC,
+ CURL_TS_WILL,
+ CURL_TS_WONT,
+ CURL_TS_DO,
+ CURL_TS_DONT,
+ CURL_TS_CR,
+ CURL_TS_SB, /* sub-option collection */
+ CURL_TS_SE /* looking for sub-option end */
+} TelnetReceive;
+
+struct TELNET {
+ int please_negotiate;
+ int already_negotiated;
+ int us[256];
+ int usq[256];
+ int us_preferred[256];
+ int him[256];
+ int himq[256];
+ int him_preferred[256];
+ int subnegotiation[256];
+ char subopt_ttype[32]; /* Set with suboption TTYPE */
+ char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */
+ unsigned short subopt_wsx; /* Set with suboption NAWS */
+ unsigned short subopt_wsy; /* Set with suboption NAWS */
+ struct curl_slist *telnet_vars; /* Environment variables */
+
+ /* suboptions */
+ unsigned char subbuffer[SUBBUFSIZE];
+ unsigned char *subpointer, *subend; /* buffer for sub-options */
+
+ TelnetReceive telrcv_state;
+};
+
+
+/*
+ * TELNET protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_telnet = {
+ "TELNET", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ telnet_do, /* do_it */
+ telnet_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_TELNET, /* defport */
+ CURLPROTO_TELNET, /* protocol */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
+};
+
+
+#ifdef USE_WINSOCK
+static CURLcode
+check_wsock2 ( struct SessionHandle *data )
+{
+ int err;
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ DEBUGASSERT(data);
+
+ /* telnet requires at least WinSock 2.0 so ask for it. */
+ wVersionRequested = MAKEWORD(2, 0);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+
+ /* We must've called this once already, so this call */
+ /* should always succeed. But, just in case... */
+ if(err != 0) {
+ failf(data,"WSAStartup failed (%d)",err);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* We have to have a WSACleanup call for every successful */
+ /* WSAStartup call. */
+ WSACleanup();
+
+ /* Check that our version is supported */
+ if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
+ HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) {
+ /* Our version isn't supported */
+ failf(data,"insufficient winsock version to support "
+ "telnet");
+ return CURLE_FAILED_INIT;
+ }
+
+ /* Our version is supported */
+ return CURLE_OK;
+}
+#endif
+
+static
+CURLcode init_telnet(struct connectdata *conn)
+{
+ struct TELNET *tn;
+
+ tn = calloc(1, sizeof(struct TELNET));
+ if(!tn)
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->data->req.protop = tn; /* make us known */
+
+ tn->telrcv_state = CURL_TS_DATA;
+
+ /* Init suboptions */
+ CURL_SB_CLEAR(tn);
+
+ /* Set the options we want by default */
+ tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES;
+ tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES;
+
+ /* To be compliant with previous releases of libcurl
+ we enable this option by default. This behaviour
+ can be changed thanks to the "BINARY" option in
+ CURLOPT_TELNETOPTIONS
+ */
+ tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES;
+ tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES;
+
+ /* We must allow the server to echo what we sent
+ but it is not necessary to request the server
+ to do so (it might forces the server to close
+ the connection). Hence, we ignore ECHO in the
+ negotiate function
+ */
+ tn->him_preferred[CURL_TELOPT_ECHO] = CURL_YES;
+
+ /* Set the subnegotiation fields to send information
+ just after negotiation passed (do/will)
+
+ Default values are (0,0) initialized by calloc.
+ According to the RFC1013 it is valid:
+ A value equal to zero is acceptable for the width (or height),
+ and means that no character width (or height) is being sent.
+ In this case, the width (or height) that will be assumed by the
+ Telnet server is operating system specific (it will probably be
+ based upon the terminal type information that may have been sent
+ using the TERMINAL TYPE Telnet option). */
+ tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES;
+ return CURLE_OK;
+}
+
+static void negotiate(struct connectdata *conn)
+{
+ int i;
+ struct TELNET *tn = (struct TELNET *) conn->data->req.protop;
+
+ for(i = 0;i < CURL_NTELOPTS;i++) {
+ if(i==CURL_TELOPT_ECHO)
+ continue;
+
+ if(tn->us_preferred[i] == CURL_YES)
+ set_local_option(conn, i, CURL_YES);
+
+ if(tn->him_preferred[i] == CURL_YES)
+ set_remote_option(conn, i, CURL_YES);
+ }
+}
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void printoption(struct SessionHandle *data,
+ const char *direction, int cmd, int option)
+{
+ const char *fmt;
+ const char *opt;
+
+ if(data->set.verbose) {
+ if(cmd == CURL_IAC) {
+ if(CURL_TELCMD_OK(option))
+ infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option));
+ else
+ infof(data, "%s IAC %d\n", direction, option);
+ }
+ else {
+ fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" :
+ (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0;
+ if(fmt) {
+ if(CURL_TELOPT_OK(option))
+ opt = CURL_TELOPT(option);
+ else if(option == CURL_TELOPT_EXOPL)
+ opt = "EXOPL";
+ else
+ opt = NULL;
+
+ if(opt)
+ infof(data, "%s %s %s\n", direction, fmt, opt);
+ else
+ infof(data, "%s %s %d\n", direction, fmt, option);
+ }
+ else
+ infof(data, "%s %d %d\n", direction, cmd, option);
+ }
+ }
+}
+#endif
+
+static void send_negotiation(struct connectdata *conn, int cmd, int option)
+{
+ unsigned char buf[3];
+ ssize_t bytes_written;
+ int err;
+ struct SessionHandle *data = conn->data;
+
+ buf[0] = CURL_IAC;
+ buf[1] = (unsigned char)cmd;
+ buf[2] = (unsigned char)option;
+
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
+
+ printoption(conn->data, "SENT", cmd, option);
+}
+
+static
+void set_remote_option(struct connectdata *conn, int option, int newstate)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ if(newstate == CURL_YES) {
+ switch(tn->him[option]) {
+ case CURL_NO:
+ tn->him[option] = CURL_WANTYES;
+ send_negotiation(conn, CURL_DO, option);
+ break;
+
+ case CURL_YES:
+ /* Already enabled */
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ /* Already negotiating for CURL_YES, queue the request */
+ tn->himq[option] = CURL_OPPOSITE;
+ break;
+ case CURL_OPPOSITE:
+ /* Error: already queued an enable request */
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ /* Error: already negotiating for enable */
+ break;
+ case CURL_OPPOSITE:
+ tn->himq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+ }
+ }
+ else { /* NO */
+ switch(tn->him[option]) {
+ case CURL_NO:
+ /* Already disabled */
+ break;
+
+ case CURL_YES:
+ tn->him[option] = CURL_WANTNO;
+ send_negotiation(conn, CURL_DONT, option);
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ /* Already negotiating for NO */
+ break;
+ case CURL_OPPOSITE:
+ tn->himq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ tn->himq[option] = CURL_OPPOSITE;
+ break;
+ case CURL_OPPOSITE:
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static
+void rec_will(struct connectdata *conn, int option)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ switch(tn->him[option]) {
+ case CURL_NO:
+ if(tn->him_preferred[option] == CURL_YES) {
+ tn->him[option] = CURL_YES;
+ send_negotiation(conn, CURL_DO, option);
+ }
+ else
+ send_negotiation(conn, CURL_DONT, option);
+
+ break;
+
+ case CURL_YES:
+ /* Already enabled */
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ /* Error: DONT answered by WILL */
+ tn->him[option] = CURL_NO;
+ break;
+ case CURL_OPPOSITE:
+ /* Error: DONT answered by WILL */
+ tn->him[option] = CURL_YES;
+ tn->himq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ tn->him[option] = CURL_YES;
+ break;
+ case CURL_OPPOSITE:
+ tn->him[option] = CURL_WANTNO;
+ tn->himq[option] = CURL_EMPTY;
+ send_negotiation(conn, CURL_DONT, option);
+ break;
+ }
+ break;
+ }
+}
+
+static
+void rec_wont(struct connectdata *conn, int option)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ switch(tn->him[option]) {
+ case CURL_NO:
+ /* Already disabled */
+ break;
+
+ case CURL_YES:
+ tn->him[option] = CURL_NO;
+ send_negotiation(conn, CURL_DONT, option);
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ tn->him[option] = CURL_NO;
+ break;
+
+ case CURL_OPPOSITE:
+ tn->him[option] = CURL_WANTYES;
+ tn->himq[option] = CURL_EMPTY;
+ send_negotiation(conn, CURL_DO, option);
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->himq[option]) {
+ case CURL_EMPTY:
+ tn->him[option] = CURL_NO;
+ break;
+ case CURL_OPPOSITE:
+ tn->him[option] = CURL_NO;
+ tn->himq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+ }
+}
+
+static void
+set_local_option(struct connectdata *conn, int option, int newstate)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ if(newstate == CURL_YES) {
+ switch(tn->us[option]) {
+ case CURL_NO:
+ tn->us[option] = CURL_WANTYES;
+ send_negotiation(conn, CURL_WILL, option);
+ break;
+
+ case CURL_YES:
+ /* Already enabled */
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ /* Already negotiating for CURL_YES, queue the request */
+ tn->usq[option] = CURL_OPPOSITE;
+ break;
+ case CURL_OPPOSITE:
+ /* Error: already queued an enable request */
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ /* Error: already negotiating for enable */
+ break;
+ case CURL_OPPOSITE:
+ tn->usq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+ }
+ }
+ else { /* NO */
+ switch(tn->us[option]) {
+ case CURL_NO:
+ /* Already disabled */
+ break;
+
+ case CURL_YES:
+ tn->us[option] = CURL_WANTNO;
+ send_negotiation(conn, CURL_WONT, option);
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ /* Already negotiating for NO */
+ break;
+ case CURL_OPPOSITE:
+ tn->usq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ tn->usq[option] = CURL_OPPOSITE;
+ break;
+ case CURL_OPPOSITE:
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static
+void rec_do(struct connectdata *conn, int option)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ switch(tn->us[option]) {
+ case CURL_NO:
+ if(tn->us_preferred[option] == CURL_YES) {
+ tn->us[option] = CURL_YES;
+ send_negotiation(conn, CURL_WILL, option);
+ if(tn->subnegotiation[option] == CURL_YES)
+ /* transmission of data option */
+ sendsuboption(conn, option);
+ }
+ else if(tn->subnegotiation[option] == CURL_YES) {
+ /* send information to achieve this option*/
+ tn->us[option] = CURL_YES;
+ send_negotiation(conn, CURL_WILL, option);
+ sendsuboption(conn, option);
+ }
+ else
+ send_negotiation(conn, CURL_WONT, option);
+ break;
+
+ case CURL_YES:
+ /* Already enabled */
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ /* Error: DONT answered by WILL */
+ tn->us[option] = CURL_NO;
+ break;
+ case CURL_OPPOSITE:
+ /* Error: DONT answered by WILL */
+ tn->us[option] = CURL_YES;
+ tn->usq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ tn->us[option] = CURL_YES;
+ if(tn->subnegotiation[option] == CURL_YES) {
+ /* transmission of data option */
+ sendsuboption(conn, option);
+ }
+ break;
+ case CURL_OPPOSITE:
+ tn->us[option] = CURL_WANTNO;
+ tn->himq[option] = CURL_EMPTY;
+ send_negotiation(conn, CURL_WONT, option);
+ break;
+ }
+ break;
+ }
+}
+
+static
+void rec_dont(struct connectdata *conn, int option)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ switch(tn->us[option]) {
+ case CURL_NO:
+ /* Already disabled */
+ break;
+
+ case CURL_YES:
+ tn->us[option] = CURL_NO;
+ send_negotiation(conn, CURL_WONT, option);
+ break;
+
+ case CURL_WANTNO:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ tn->us[option] = CURL_NO;
+ break;
+
+ case CURL_OPPOSITE:
+ tn->us[option] = CURL_WANTYES;
+ tn->usq[option] = CURL_EMPTY;
+ send_negotiation(conn, CURL_WILL, option);
+ break;
+ }
+ break;
+
+ case CURL_WANTYES:
+ switch(tn->usq[option]) {
+ case CURL_EMPTY:
+ tn->us[option] = CURL_NO;
+ break;
+ case CURL_OPPOSITE:
+ tn->us[option] = CURL_NO;
+ tn->usq[option] = CURL_EMPTY;
+ break;
+ }
+ break;
+ }
+}
+
+
+static void printsub(struct SessionHandle *data,
+ int direction, /* '<' or '>' */
+ unsigned char *pointer, /* where suboption data is */
+ size_t length) /* length of suboption data */
+{
+ unsigned int i = 0;
+ unsigned short *pval;
+
+ if(data->set.verbose) {
+ if(direction) {
+ infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
+ if(length >= 3) {
+ int j;
+
+ i = pointer[length-2];
+ j = pointer[length-1];
+
+ if(i != CURL_IAC || j != CURL_SE) {
+ infof(data, "(terminated by ");
+ if(CURL_TELOPT_OK(i))
+ infof(data, "%s ", CURL_TELOPT(i));
+ else if(CURL_TELCMD_OK(i))
+ infof(data, "%s ", CURL_TELCMD(i));
+ else
+ infof(data, "%u ", i);
+ if(CURL_TELOPT_OK(j))
+ infof(data, "%s", CURL_TELOPT(j));
+ else if(CURL_TELCMD_OK(j))
+ infof(data, "%s", CURL_TELCMD(j));
+ else
+ infof(data, "%d", j);
+ infof(data, ", not IAC SE!) ");
+ }
+ }
+ length -= 2;
+ }
+ if(length < 1) {
+ infof(data, "(Empty suboption?)");
+ return;
+ }
+
+ if(CURL_TELOPT_OK(pointer[0])) {
+ switch(pointer[0]) {
+ case CURL_TELOPT_TTYPE:
+ case CURL_TELOPT_XDISPLOC:
+ case CURL_TELOPT_NEW_ENVIRON:
+ case CURL_TELOPT_NAWS:
+ infof(data, "%s", CURL_TELOPT(pointer[0]));
+ break;
+ default:
+ infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0]));
+ break;
+ }
+ }
+ else
+ infof(data, "%d (unknown)", pointer[i]);
+
+ switch(pointer[0]) {
+ case CURL_TELOPT_NAWS:
+ pval = (unsigned short*)(pointer+1);
+ infof(data, "Width: %hu ; Height: %hu",
+ ntohs(pval[0]), ntohs(pval[1]));
+ break;
+ default:
+ switch(pointer[1]) {
+ case CURL_TELQUAL_IS:
+ infof(data, " IS");
+ break;
+ case CURL_TELQUAL_SEND:
+ infof(data, " SEND");
+ break;
+ case CURL_TELQUAL_INFO:
+ infof(data, " INFO/REPLY");
+ break;
+ case CURL_TELQUAL_NAME:
+ infof(data, " NAME");
+ break;
+ }
+
+ switch(pointer[0]) {
+ case CURL_TELOPT_TTYPE:
+ case CURL_TELOPT_XDISPLOC:
+ pointer[length] = 0;
+ infof(data, " \"%s\"", &pointer[2]);
+ break;
+ case CURL_TELOPT_NEW_ENVIRON:
+ if(pointer[1] == CURL_TELQUAL_IS) {
+ infof(data, " ");
+ for(i = 3;i < length;i++) {
+ switch(pointer[i]) {
+ case CURL_NEW_ENV_VAR:
+ infof(data, ", ");
+ break;
+ case CURL_NEW_ENV_VALUE:
+ infof(data, " = ");
+ break;
+ default:
+ infof(data, "%c", pointer[i]);
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ for(i = 2; i < length; i++)
+ infof(data, " %.2x", pointer[i]);
+ break;
+ }
+ }
+ if(direction)
+ infof(data, "\n");
+ }
+}
+
+static CURLcode check_telnet_options(struct connectdata *conn)
+{
+ struct curl_slist *head;
+ struct curl_slist *beg;
+ char option_keyword[128] = "";
+ char option_arg[256] = "";
+ struct SessionHandle *data = conn->data;
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ CURLcode result = CURLE_OK;
+ int binary_option;
+
+ /* Add the user name as an environment variable if it
+ was given on the command line */
+ if(conn->bits.user_passwd) {
+ snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
+ beg = curl_slist_append(tn->telnet_vars, option_arg);
+ if(!beg) {
+ curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ tn->telnet_vars = beg;
+ tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
+ }
+
+ for(head = data->set.telnet_options; head; head=head->next) {
+ if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
+ option_keyword, option_arg) == 2) {
+
+ /* Terminal type */
+ if(Curl_raw_equal(option_keyword, "TTYPE")) {
+ strncpy(tn->subopt_ttype, option_arg, 31);
+ tn->subopt_ttype[31] = 0; /* String termination */
+ tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
+ continue;
+ }
+
+ /* Display variable */
+ if(Curl_raw_equal(option_keyword, "XDISPLOC")) {
+ strncpy(tn->subopt_xdisploc, option_arg, 127);
+ tn->subopt_xdisploc[127] = 0; /* String termination */
+ tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
+ continue;
+ }
+
+ /* Environment variable */
+ if(Curl_raw_equal(option_keyword, "NEW_ENV")) {
+ beg = curl_slist_append(tn->telnet_vars, option_arg);
+ if(!beg) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ tn->telnet_vars = beg;
+ tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
+ continue;
+ }
+
+ /* Window Size */
+ if(Curl_raw_equal(option_keyword, "WS")) {
+ if(sscanf(option_arg, "%hu%*[xX]%hu",
+ &tn->subopt_wsx, &tn->subopt_wsy) == 2)
+ tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
+ else {
+ failf(data, "Syntax error in telnet option: %s", head->data);
+ result = CURLE_TELNET_OPTION_SYNTAX;
+ break;
+ }
+ continue;
+ }
+
+ /* To take care or not of the 8th bit in data exchange */
+ if(Curl_raw_equal(option_keyword, "BINARY")) {
+ binary_option=atoi(option_arg);
+ if(binary_option!=1) {
+ tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
+ tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO;
+ }
+ continue;
+ }
+
+ failf(data, "Unknown telnet option %s", head->data);
+ result = CURLE_UNKNOWN_TELNET_OPTION;
+ break;
+ }
+ else {
+ failf(data, "Syntax error in telnet option: %s", head->data);
+ result = CURLE_TELNET_OPTION_SYNTAX;
+ break;
+ }
+ }
+
+ if(result) {
+ curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
+ }
+
+ return result;
+}
+
+/*
+ * suboption()
+ *
+ * Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ */
+
+static void suboption(struct connectdata *conn)
+{
+ struct curl_slist *v;
+ unsigned char temp[2048];
+ ssize_t bytes_written;
+ size_t len;
+ size_t tmplen;
+ int err;
+ char varname[128] = "";
+ char varval[128] = "";
+ struct SessionHandle *data = conn->data;
+ struct TELNET *tn = (struct TELNET *)data->req.protop;
+
+ printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
+ switch (CURL_SB_GET(tn)) {
+ case CURL_TELOPT_TTYPE:
+ len = strlen(tn->subopt_ttype) + 4 + 2;
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
+ CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
+ printsub(data, '>', &temp[2], len-2);
+ break;
+ case CURL_TELOPT_XDISPLOC:
+ len = strlen(tn->subopt_xdisploc) + 4 + 2;
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
+ CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
+ printsub(data, '>', &temp[2], len-2);
+ break;
+ case CURL_TELOPT_NEW_ENVIRON:
+ snprintf((char *)temp, sizeof(temp),
+ "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
+ CURL_TELQUAL_IS);
+ len = 4;
+
+ for(v = tn->telnet_vars;v;v = v->next) {
+ tmplen = (strlen(v->data) + 1);
+ /* Add the variable only if it fits */
+ if(len + tmplen < (int)sizeof(temp)-6) {
+ if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
+ snprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
+ CURL_NEW_ENV_VALUE, varval);
+ len += tmplen;
+ }
+ }
+ }
+ snprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%c", CURL_IAC, CURL_SE);
+ len += 2;
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
+ printsub(data, '>', &temp[2], len-2);
+ break;
+ }
+ return;
+}
+
+
+/*
+ * sendsuboption()
+ *
+ * Send suboption information to the server side.
+ */
+
+static void sendsuboption(struct connectdata *conn, int option)
+{
+ ssize_t bytes_written;
+ int err;
+ unsigned short x, y;
+ unsigned char*uc1, *uc2;
+
+ struct SessionHandle *data = conn->data;
+ struct TELNET *tn = (struct TELNET *)data->req.protop;
+
+ switch (option) {
+ case CURL_TELOPT_NAWS:
+ /* We prepare data to be sent */
+ CURL_SB_CLEAR(tn);
+ CURL_SB_ACCUM(tn, CURL_IAC);
+ CURL_SB_ACCUM(tn, CURL_SB);
+ CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS);
+ /* We must deal either with litte or big endien processors */
+ /* Window size must be sent according to the 'network order' */
+ x=htons(tn->subopt_wsx);
+ y=htons(tn->subopt_wsy);
+ uc1 = (unsigned char*)&x;
+ uc2 = (unsigned char*)&y;
+ CURL_SB_ACCUM(tn, uc1[0]);
+ CURL_SB_ACCUM(tn, uc1[1]);
+ CURL_SB_ACCUM(tn, uc2[0]);
+ CURL_SB_ACCUM(tn, uc2[1]);
+
+ CURL_SB_ACCUM(tn, CURL_IAC);
+ CURL_SB_ACCUM(tn, CURL_SE);
+ CURL_SB_TERM(tn);
+ /* data suboption is now ready */
+
+ printsub(data, '>', (unsigned char *)tn->subbuffer+2,
+ CURL_SB_LEN(tn)-2);
+
+ /* we send the header of the suboption... */
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data, "Sending data failed (%d)", err);
+ }
+ /* ... then the window size with the send_telnet_data() function
+ to deal with 0xFF cases ... */
+ send_telnet_data(conn, (char *)tn->subbuffer+3, 4);
+ /* ... and the footer */
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer+7, 2);
+ if(bytes_written < 0) {
+ err = SOCKERRNO;
+ failf(data, "Sending data failed (%d)", err);
+ }
+ break;
+ }
+}
+
+
+static
+CURLcode telrcv(struct connectdata *conn,
+ const unsigned char *inbuf, /* Data received from socket */
+ ssize_t count) /* Number of bytes received */
+{
+ unsigned char c;
+ CURLcode result;
+ int in = 0;
+ int startwrite=-1;
+ struct SessionHandle *data = conn->data;
+ struct TELNET *tn = (struct TELNET *)data->req.protop;
+
+#define startskipping() \
+ if(startwrite >= 0) { \
+ result = Curl_client_write(conn, \
+ CLIENTWRITE_BODY, \
+ (char *)&inbuf[startwrite], \
+ in-startwrite); \
+ if(result != CURLE_OK) \
+ return result; \
+ } \
+ startwrite = -1
+
+#define writebyte() \
+ if(startwrite < 0) \
+ startwrite = in
+
+#define bufferflush() startskipping()
+
+ while(count--) {
+ c = inbuf[in];
+
+ switch (tn->telrcv_state) {
+ case CURL_TS_CR:
+ tn->telrcv_state = CURL_TS_DATA;
+ if(c == '\0') {
+ startskipping();
+ break; /* Ignore \0 after CR */
+ }
+ writebyte();
+ break;
+
+ case CURL_TS_DATA:
+ if(c == CURL_IAC) {
+ tn->telrcv_state = CURL_TS_IAC;
+ startskipping();
+ break;
+ }
+ else if(c == '\r')
+ tn->telrcv_state = CURL_TS_CR;
+ writebyte();
+ break;
+
+ case CURL_TS_IAC:
+ process_iac:
+ DEBUGASSERT(startwrite < 0);
+ switch (c) {
+ case CURL_WILL:
+ tn->telrcv_state = CURL_TS_WILL;
+ break;
+ case CURL_WONT:
+ tn->telrcv_state = CURL_TS_WONT;
+ break;
+ case CURL_DO:
+ tn->telrcv_state = CURL_TS_DO;
+ break;
+ case CURL_DONT:
+ tn->telrcv_state = CURL_TS_DONT;
+ break;
+ case CURL_SB:
+ CURL_SB_CLEAR(tn);
+ tn->telrcv_state = CURL_TS_SB;
+ break;
+ case CURL_IAC:
+ tn->telrcv_state = CURL_TS_DATA;
+ writebyte();
+ break;
+ case CURL_DM:
+ case CURL_NOP:
+ case CURL_GA:
+ default:
+ tn->telrcv_state = CURL_TS_DATA;
+ printoption(data, "RCVD", CURL_IAC, c);
+ break;
+ }
+ break;
+
+ case CURL_TS_WILL:
+ printoption(data, "RCVD", CURL_WILL, c);
+ tn->please_negotiate = 1;
+ rec_will(conn, c);
+ tn->telrcv_state = CURL_TS_DATA;
+ break;
+
+ case CURL_TS_WONT:
+ printoption(data, "RCVD", CURL_WONT, c);
+ tn->please_negotiate = 1;
+ rec_wont(conn, c);
+ tn->telrcv_state = CURL_TS_DATA;
+ break;
+
+ case CURL_TS_DO:
+ printoption(data, "RCVD", CURL_DO, c);
+ tn->please_negotiate = 1;
+ rec_do(conn, c);
+ tn->telrcv_state = CURL_TS_DATA;
+ break;
+
+ case CURL_TS_DONT:
+ printoption(data, "RCVD", CURL_DONT, c);
+ tn->please_negotiate = 1;
+ rec_dont(conn, c);
+ tn->telrcv_state = CURL_TS_DATA;
+ break;
+
+ case CURL_TS_SB:
+ if(c == CURL_IAC)
+ tn->telrcv_state = CURL_TS_SE;
+ else
+ CURL_SB_ACCUM(tn,c);
+ break;
+
+ case CURL_TS_SE:
+ if(c != CURL_SE) {
+ if(c != CURL_IAC) {
+ /*
+ * This is an error. We only expect to get "IAC IAC" or "IAC SE".
+ * Several things may have happened. An IAC was not doubled, the
+ * IAC SE was left off, or another option got inserted into the
+ * suboption are all possibilities. If we assume that the IAC was
+ * not doubled, and really the IAC SE was left off, we could get
+ * into an infinate loop here. So, instead, we terminate the
+ * suboption, and process the partial suboption if we can.
+ */
+ CURL_SB_ACCUM(tn, CURL_IAC);
+ CURL_SB_ACCUM(tn, c);
+ tn->subpointer -= 2;
+ CURL_SB_TERM(tn);
+
+ printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
+ suboption(conn); /* handle sub-option */
+ tn->telrcv_state = CURL_TS_IAC;
+ goto process_iac;
+ }
+ CURL_SB_ACCUM(tn,c);
+ tn->telrcv_state = CURL_TS_SB;
+ }
+ else
+ {
+ CURL_SB_ACCUM(tn, CURL_IAC);
+ CURL_SB_ACCUM(tn, CURL_SE);
+ tn->subpointer -= 2;
+ CURL_SB_TERM(tn);
+ suboption(conn); /* handle sub-option */
+ tn->telrcv_state = CURL_TS_DATA;
+ }
+ break;
+ }
+ ++in;
+ }
+ bufferflush();
+ return CURLE_OK;
+}
+
+/* Escape and send a telnet data block */
+/* TODO: write large chunks of data instead of one byte at a time */
+static CURLcode send_telnet_data(struct connectdata *conn,
+ char *buffer, ssize_t nread)
+{
+ unsigned char outbuf[2];
+ ssize_t bytes_written, total_written;
+ int out_count;
+ CURLcode rc = CURLE_OK;
+
+ while(rc == CURLE_OK && nread--) {
+ outbuf[0] = *buffer++;
+ out_count = 1;
+ if(outbuf[0] == CURL_IAC)
+ outbuf[out_count++] = CURL_IAC;
+
+ total_written = 0;
+ do {
+ /* Make sure socket is writable to avoid EWOULDBLOCK condition */
+ struct pollfd pfd[1];
+ pfd[0].fd = conn->sock[FIRSTSOCKET];
+ pfd[0].events = POLLOUT;
+ switch (Curl_poll(pfd, 1, -1)) {
+ case -1: /* error, abort writing */
+ case 0: /* timeout (will never happen) */
+ rc = CURLE_SEND_ERROR;
+ break;
+ default: /* write! */
+ bytes_written = 0;
+ rc = Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf+total_written,
+ out_count-total_written, &bytes_written);
+ total_written += bytes_written;
+ break;
+ }
+ /* handle partial write */
+ } while(rc == CURLE_OK && total_written < out_count);
+ }
+ return rc;
+}
+
+static CURLcode telnet_done(struct connectdata *conn,
+ CURLcode status, bool premature)
+{
+ struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ (void)status; /* unused */
+ (void)premature; /* not used */
+
+ if(!tn)
+ return CURLE_OK;
+
+ curl_slist_free_all(tn->telnet_vars);
+ tn->telnet_vars = NULL;
+
+ Curl_safefree(conn->data->req.protop);
+
+ return CURLE_OK;
+}
+
+static CURLcode telnet_do(struct connectdata *conn, bool *done)
+{
+ CURLcode code;
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+#ifdef USE_WINSOCK
+ HMODULE wsock2;
+ WSOCK2_FUNC close_event_func;
+ WSOCK2_FUNC create_event_func;
+ WSOCK2_FUNC event_select_func;
+ WSOCK2_FUNC enum_netevents_func;
+ WSAEVENT event_handle;
+ WSANETWORKEVENTS events;
+ HANDLE stdin_handle;
+ HANDLE objs[2];
+ DWORD obj_count;
+ DWORD wait_timeout;
+ DWORD waitret;
+ DWORD readfile_read;
+ int err;
+#else
+ int interval_ms;
+ struct pollfd pfd[2];
+ int poll_cnt;
+ curl_off_t total_dl = 0;
+ curl_off_t total_ul = 0;
+#endif
+ ssize_t nread;
+ struct timeval now;
+ bool keepon = TRUE;
+ char *buf = data->state.buffer;
+ struct TELNET *tn;
+
+ *done = TRUE; /* unconditionally */
+
+ code = init_telnet(conn);
+ if(code)
+ return code;
+
+ tn = (struct TELNET *)data->req.protop;
+
+ code = check_telnet_options(conn);
+ if(code)
+ return code;
+
+#ifdef USE_WINSOCK
+ /*
+ ** This functionality only works with WinSock >= 2.0. So,
+ ** make sure have it.
+ */
+ code = check_wsock2(data);
+ if(code)
+ return code;
+
+ /* OK, so we have WinSock 2.0. We need to dynamically */
+ /* load ws2_32.dll and get the function pointers we need. */
+ wsock2 = LoadLibrary(TEXT("WS2_32.DLL"));
+ if(wsock2 == NULL) {
+ failf(data,"failed to load WS2_32.DLL (%d)", ERRNO);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* Grab a pointer to WSACreateEvent */
+ create_event_func = GetProcAddress(wsock2,"WSACreateEvent");
+ if(create_event_func == NULL) {
+ failf(data,"failed to find WSACreateEvent function (%d)",
+ ERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* And WSACloseEvent */
+ close_event_func = GetProcAddress(wsock2,"WSACloseEvent");
+ if(close_event_func == NULL) {
+ failf(data,"failed to find WSACloseEvent function (%d)",
+ ERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* And WSAEventSelect */
+ event_select_func = GetProcAddress(wsock2,"WSAEventSelect");
+ if(event_select_func == NULL) {
+ failf(data,"failed to find WSAEventSelect function (%d)",
+ ERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* And WSAEnumNetworkEvents */
+ enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents");
+ if(enum_netevents_func == NULL) {
+ failf(data,"failed to find WSAEnumNetworkEvents function (%d)",
+ ERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* We want to wait for both stdin and the socket. Since
+ ** the select() function in winsock only works on sockets
+ ** we have to use the WaitForMultipleObjects() call.
+ */
+
+ /* First, create a sockets event object */
+ event_handle = (WSAEVENT)create_event_func();
+ if(event_handle == WSA_INVALID_EVENT) {
+ failf(data,"WSACreateEvent failed (%d)", SOCKERRNO);
+ FreeLibrary(wsock2);
+ return CURLE_FAILED_INIT;
+ }
+
+ /* Tell winsock what events we want to listen to */
+ if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) ==
+ SOCKET_ERROR) {
+ close_event_func(event_handle);
+ FreeLibrary(wsock2);
+ return CURLE_OK;
+ }
+
+ /* The get the Windows file handle for stdin */
+ stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
+
+ /* Create the list of objects to wait for */
+ objs[0] = event_handle;
+ objs[1] = stdin_handle;
+
+ /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it,
+ else use the old WaitForMultipleObjects() way */
+ if(GetFileType(stdin_handle) == FILE_TYPE_PIPE ||
+ data->set.is_fread_set) {
+ /* Don't wait for stdin_handle, just wait for event_handle */
+ obj_count = 1;
+ /* Check stdin_handle per 100 milliseconds */
+ wait_timeout = 100;
+ }
+ else {
+ obj_count = 2;
+ wait_timeout = 1000;
+ }
+
+ /* Keep on listening and act on events */
+ while(keepon) {
+ waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
+ switch(waitret) {
+ case WAIT_TIMEOUT:
+ {
+ for(;;) {
+ if(obj_count == 1) {
+ /* read from user-supplied method */
+ code = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in);
+ if(code == CURL_READFUNC_ABORT) {
+ keepon = FALSE;
+ code = CURLE_READ_ERROR;
+ break;
+ }
+
+ if(code == CURL_READFUNC_PAUSE)
+ break;
+
+ if(code == 0) /* no bytes */
+ break;
+
+ readfile_read = code; /* fall thru with number of bytes read */
+ }
+ else {
+ /* read from stdin */
+ if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL,
+ &readfile_read, NULL)) {
+ keepon = FALSE;
+ code = CURLE_READ_ERROR;
+ break;
+ }
+
+ if(!readfile_read)
+ break;
+
+ if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
+ &readfile_read, NULL)) {
+ keepon = FALSE;
+ code = CURLE_READ_ERROR;
+ break;
+ }
+ }
+
+ code = send_telnet_data(conn, buf, readfile_read);
+ if(code) {
+ keepon = FALSE;
+ break;
+ }
+ }
+ }
+ break;
+
+ case WAIT_OBJECT_0 + 1:
+ {
+ if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
+ &readfile_read, NULL)) {
+ keepon = FALSE;
+ code = CURLE_READ_ERROR;
+ break;
+ }
+
+ code = send_telnet_data(conn, buf, readfile_read);
+ if(code) {
+ keepon = FALSE;
+ break;
+ }
+ }
+ break;
+
+ case WAIT_OBJECT_0:
+
+ events.lNetworkEvents = 0;
+ if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
+ if((err = SOCKERRNO) != EINPROGRESS) {
+ infof(data,"WSAEnumNetworkEvents failed (%d)", err);
+ keepon = FALSE;
+ code = CURLE_READ_ERROR;
+ }
+ break;
+ }
+ if(events.lNetworkEvents & FD_READ) {
+ /* read data from network */
+ code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
+ /* read would've blocked. Loop again */
+ if(code == CURLE_AGAIN)
+ break;
+ /* returned not-zero, this an error */
+ else if(code) {
+ keepon = FALSE;
+ break;
+ }
+ /* returned zero but actually received 0 or less here,
+ the server closed the connection and we bail out */
+ else if(nread <= 0) {
+ keepon = FALSE;
+ break;
+ }
+
+ code = telrcv(conn, (unsigned char *)buf, nread);
+ if(code) {
+ keepon = FALSE;
+ break;
+ }
+
+ /* Negotiate if the peer has started negotiating,
+ otherwise don't. We don't want to speak telnet with
+ non-telnet servers, like POP or SMTP. */
+ if(tn->please_negotiate && !tn->already_negotiated) {
+ negotiate(conn);
+ tn->already_negotiated = 1;
+ }
+ }
+ if(events.lNetworkEvents & FD_CLOSE) {
+ keepon = FALSE;
+ }
+ break;
+
+ }
+
+ if(data->set.timeout) {
+ now = Curl_tvnow();
+ if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
+ failf(data, "Time-out");
+ code = CURLE_OPERATION_TIMEDOUT;
+ keepon = FALSE;
+ }
+ }
+ }
+
+ /* We called WSACreateEvent, so call WSACloseEvent */
+ if(!close_event_func(event_handle)) {
+ infof(data,"WSACloseEvent failed (%d)", SOCKERRNO);
+ }
+
+ /* "Forget" pointers into the library we're about to free */
+ create_event_func = NULL;
+ close_event_func = NULL;
+ event_select_func = NULL;
+ enum_netevents_func = NULL;
+
+ /* We called LoadLibrary, so call FreeLibrary */
+ if(!FreeLibrary(wsock2))
+ infof(data,"FreeLibrary(wsock2) failed (%d)", ERRNO);
+#else
+ pfd[0].fd = sockfd;
+ pfd[0].events = POLLIN;
+
+ if(conn->fread_func != (curl_read_callback)fread) {
+ poll_cnt = 1;
+ interval_ms = 100; /* poll user-supplied read function */
+ }
+ else {
+ /* really using fread, so infile is a FILE* */
+ pfd[1].fd = fileno((FILE *)conn->fread_in);
+ pfd[1].events = POLLIN;
+ poll_cnt = 2;
+ interval_ms = 1 * 1000;
+ }
+
+ while(keepon) {
+ switch (Curl_poll(pfd, poll_cnt, interval_ms)) {
+ case -1: /* error, stop reading */
+ keepon = FALSE;
+ continue;
+ case 0: /* timeout */
+ pfd[0].revents = 0;
+ pfd[1].revents = 0;
+ /* fall through */
+ default: /* read! */
+ if(pfd[0].revents & POLLIN) {
+ /* read data from network */
+ code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
+ /* read would've blocked. Loop again */
+ if(code == CURLE_AGAIN)
+ break;
+ /* returned not-zero, this an error */
+ else if(code) {
+ keepon = FALSE;
+ break;
+ }
+ /* returned zero but actually received 0 or less here,
+ the server closed the connection and we bail out */
+ else if(nread <= 0) {
+ keepon = FALSE;
+ break;
+ }
+
+ total_dl += nread;
+ Curl_pgrsSetDownloadCounter(data, total_dl);
+ code = telrcv(conn, (unsigned char *)buf, nread);
+ if(code) {
+ keepon = FALSE;
+ break;
+ }
+
+ /* Negotiate if the peer has started negotiating,
+ otherwise don't. We don't want to speak telnet with
+ non-telnet servers, like POP or SMTP. */
+ if(tn->please_negotiate && !tn->already_negotiated) {
+ negotiate(conn);
+ tn->already_negotiated = 1;
+ }
+ }
+
+ nread = 0;
+ if(poll_cnt == 2) {
+ if(pfd[1].revents & POLLIN) { /* read from in file */
+ nread = read(pfd[1].fd, buf, BUFSIZE - 1);
+ }
+ }
+ else {
+ /* read from user-supplied method */
+ nread = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in);
+ if(nread == CURL_READFUNC_ABORT) {
+ keepon = FALSE;
+ break;
+ }
+ if(nread == CURL_READFUNC_PAUSE)
+ break;
+ }
+
+ if(nread > 0) {
+ code = send_telnet_data(conn, buf, nread);
+ if(code) {
+ keepon = FALSE;
+ break;
+ }
+ total_ul += nread;
+ Curl_pgrsSetUploadCounter(data, total_ul);
+ }
+ else if(nread < 0)
+ keepon = FALSE;
+
+ break;
+ } /* poll switch statement */
+
+ if(data->set.timeout) {
+ now = Curl_tvnow();
+ if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
+ failf(data, "Time-out");
+ code = CURLE_OPERATION_TIMEDOUT;
+ keepon = FALSE;
+ }
+ }
+
+ if(Curl_pgrsUpdate(conn)) {
+ code = CURLE_ABORTED_BY_CALLBACK;
+ break;
+ }
+ }
+#endif
+ /* mark this as "no further transfer wanted" */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+
+ return code;
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/telnet.h b/external/libcurl_android/jni/libcurl/lib/telnet.h
new file mode 100755
index 00000000..ddb9e547
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/telnet.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TELNET_H
+#define HEADER_CURL_TELNET_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_TELNET
+extern const struct Curl_handler Curl_handler_telnet;
+#endif
+
+#endif /* HEADER_CURL_TELNET_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/tftp.c b/external/libcurl_android/jni/libcurl/lib/tftp.c
new file mode 100755
index 00000000..e499c451
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/tftp.c
@@ -0,0 +1,1375 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_TFTP
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "transfer.h"
+#include "sendf.h"
+#include "tftp.h"
+#include "progress.h"
+#include "connect.h"
+#include "strerror.h"
+#include "sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "multiif.h"
+#include "url.h"
+#include "rawstr.h"
+#include "speedcheck.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+#include "select.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* RFC2348 allows the block size to be negotiated */
+#define TFTP_BLKSIZE_DEFAULT 512
+#define TFTP_BLKSIZE_MIN 8
+#define TFTP_BLKSIZE_MAX 65464
+#define TFTP_OPTION_BLKSIZE "blksize"
+
+/* from RFC2349: */
+#define TFTP_OPTION_TSIZE "tsize"
+#define TFTP_OPTION_INTERVAL "timeout"
+
+typedef enum {
+ TFTP_MODE_NETASCII=0,
+ TFTP_MODE_OCTET
+} tftp_mode_t;
+
+typedef enum {
+ TFTP_STATE_START=0,
+ TFTP_STATE_RX,
+ TFTP_STATE_TX,
+ TFTP_STATE_FIN
+} tftp_state_t;
+
+typedef enum {
+ TFTP_EVENT_NONE = -1,
+ TFTP_EVENT_INIT = 0,
+ TFTP_EVENT_RRQ = 1,
+ TFTP_EVENT_WRQ = 2,
+ TFTP_EVENT_DATA = 3,
+ TFTP_EVENT_ACK = 4,
+ TFTP_EVENT_ERROR = 5,
+ TFTP_EVENT_OACK = 6,
+ TFTP_EVENT_TIMEOUT
+} tftp_event_t;
+
+typedef enum {
+ TFTP_ERR_UNDEF=0,
+ TFTP_ERR_NOTFOUND,
+ TFTP_ERR_PERM,
+ TFTP_ERR_DISKFULL,
+ TFTP_ERR_ILLEGAL,
+ TFTP_ERR_UNKNOWNID,
+ TFTP_ERR_EXISTS,
+ TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */
+
+ /* The remaining error codes are internal to curl */
+ TFTP_ERR_NONE = -100,
+ TFTP_ERR_TIMEOUT,
+ TFTP_ERR_NORESPONSE
+} tftp_error_t;
+
+typedef struct tftp_packet {
+ unsigned char *data;
+} tftp_packet_t;
+
+typedef struct tftp_state_data {
+ tftp_state_t state;
+ tftp_mode_t mode;
+ tftp_error_t error;
+ tftp_event_t event;
+ struct connectdata *conn;
+ curl_socket_t sockfd;
+ int retries;
+ int retry_time;
+ int retry_max;
+ time_t start_time;
+ time_t max_time;
+ time_t rx_time;
+ unsigned short block;
+ struct Curl_sockaddr_storage local_addr;
+ struct Curl_sockaddr_storage remote_addr;
+ curl_socklen_t remote_addrlen;
+ int rbytes;
+ int sbytes;
+ int blksize;
+ int requested_blksize;
+ tftp_packet_t rpacket;
+ tftp_packet_t spacket;
+} tftp_state_data_t;
+
+
+/* Forward declarations */
+static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
+static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
+static CURLcode tftp_connect(struct connectdata *conn, bool *done);
+static CURLcode tftp_disconnect(struct connectdata *conn,
+ bool dead_connection);
+static CURLcode tftp_do(struct connectdata *conn, bool *done);
+static CURLcode tftp_done(struct connectdata *conn,
+ CURLcode, bool premature);
+static CURLcode tftp_setup_connection(struct connectdata * conn);
+static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done);
+static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done);
+static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+static CURLcode tftp_translate_code(tftp_error_t error);
+
+
+/*
+ * TFTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_tftp = {
+ "TFTP", /* scheme */
+ tftp_setup_connection, /* setup_connection */
+ tftp_do, /* do_it */
+ tftp_done, /* done */
+ ZERO_NULL, /* do_more */
+ tftp_connect, /* connect_it */
+ tftp_multi_statemach, /* connecting */
+ tftp_doing, /* doing */
+ tftp_getsock, /* proto_getsock */
+ tftp_getsock, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ tftp_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ PORT_TFTP, /* defport */
+ CURLPROTO_TFTP, /* protocol */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
+};
+
+/**********************************************************
+ *
+ * tftp_set_timeouts -
+ *
+ * Set timeouts based on state machine state.
+ * Use user provided connect timeouts until DATA or ACK
+ * packet is received, then use user-provided transfer timeouts
+ *
+ *
+ **********************************************************/
+static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
+{
+ time_t maxtime, timeout;
+ long timeout_ms;
+ bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
+
+ time(&state->start_time);
+
+ /* Compute drop-dead time */
+ timeout_ms = Curl_timeleft(state->conn->data, NULL, start);
+
+ if(timeout_ms < 0) {
+ /* time-out, bail out, go home */
+ failf(state->conn->data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ if(start) {
+
+ maxtime = (time_t)(timeout_ms + 500) / 1000;
+ state->max_time = state->start_time+maxtime;
+
+ /* Set per-block timeout to total */
+ timeout = maxtime ;
+
+ /* Average restart after 5 seconds */
+ state->retry_max = (int)timeout/5;
+
+ if(state->retry_max < 1)
+ /* avoid division by zero below */
+ state->retry_max = 1;
+
+ /* Compute the re-start interval to suit the timeout */
+ state->retry_time = (int)timeout/state->retry_max;
+ if(state->retry_time<1)
+ state->retry_time=1;
+
+ }
+ else {
+ if(timeout_ms > 0)
+ maxtime = (time_t)(timeout_ms + 500) / 1000;
+ else
+ maxtime = 3600;
+
+ state->max_time = state->start_time+maxtime;
+
+ /* Set per-block timeout to total */
+ timeout = maxtime;
+
+ /* Average reposting an ACK after 5 seconds */
+ state->retry_max = (int)timeout/5;
+ }
+ /* But bound the total number */
+ if(state->retry_max<3)
+ state->retry_max=3;
+
+ if(state->retry_max>50)
+ state->retry_max=50;
+
+ /* Compute the re-ACK interval to suit the timeout */
+ state->retry_time = (int)(timeout/state->retry_max);
+ if(state->retry_time<1)
+ state->retry_time=1;
+
+ infof(state->conn->data,
+ "set timeouts for state %d; Total %ld, retry %d maxtry %d\n",
+ (int)state->state, (long)(state->max_time-state->start_time),
+ state->retry_time, state->retry_max);
+
+ /* init RX time */
+ time(&state->rx_time);
+
+ return CURLE_OK;
+}
+
+/**********************************************************
+ *
+ * tftp_set_send_first
+ *
+ * Event handler for the START state
+ *
+ **********************************************************/
+
+static void setpacketevent(tftp_packet_t *packet, unsigned short num)
+{
+ packet->data[0] = (unsigned char)(num >> 8);
+ packet->data[1] = (unsigned char)(num & 0xff);
+}
+
+
+static void setpacketblock(tftp_packet_t *packet, unsigned short num)
+{
+ packet->data[2] = (unsigned char)(num >> 8);
+ packet->data[3] = (unsigned char)(num & 0xff);
+}
+
+static unsigned short getrpacketevent(const tftp_packet_t *packet)
+{
+ return (unsigned short)((packet->data[0] << 8) | packet->data[1]);
+}
+
+static unsigned short getrpacketblock(const tftp_packet_t *packet)
+{
+ return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
+}
+
+static size_t Curl_strnlen(const char *string, size_t maxlen)
+{
+ const char *end = memchr (string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+
+static const char *tftp_option_get(const char *buf, size_t len,
+ const char **option, const char **value)
+{
+ size_t loc;
+
+ loc = Curl_strnlen( buf, len );
+ loc++; /* NULL term */
+
+ if(loc >= len)
+ return NULL;
+ *option = buf;
+
+ loc += Curl_strnlen( buf+loc, len-loc );
+ loc++; /* NULL term */
+
+ if(loc > len)
+ return NULL;
+ *value = &buf[strlen(*option) + 1];
+
+ return &buf[loc];
+}
+
+static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
+ const char *ptr, int len)
+{
+ const char *tmp = ptr;
+ struct SessionHandle *data = state->conn->data;
+
+ /* if OACK doesn't contain blksize option, the default (512) must be used */
+ state->blksize = TFTP_BLKSIZE_DEFAULT;
+
+ while(tmp < ptr + len) {
+ const char *option, *value;
+
+ tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value);
+ if(tmp == NULL) {
+ failf(data, "Malformed ACK packet, rejecting");
+ return CURLE_TFTP_ILLEGAL;
+ }
+
+ infof(data, "got option=(%s) value=(%s)\n", option, value);
+
+ if(checkprefix(option, TFTP_OPTION_BLKSIZE)) {
+ long blksize;
+
+ blksize = strtol( value, NULL, 10 );
+
+ if(!blksize) {
+ failf(data, "invalid blocksize value in OACK packet");
+ return CURLE_TFTP_ILLEGAL;
+ }
+ else if(blksize > TFTP_BLKSIZE_MAX) {
+ failf(data, "%s (%d)", "blksize is larger than max supported",
+ TFTP_BLKSIZE_MAX);
+ return CURLE_TFTP_ILLEGAL;
+ }
+ else if(blksize < TFTP_BLKSIZE_MIN) {
+ failf(data, "%s (%d)", "blksize is smaller than min supported",
+ TFTP_BLKSIZE_MIN);
+ return CURLE_TFTP_ILLEGAL;
+ }
+ else if(blksize > state->requested_blksize) {
+ /* could realloc pkt buffers here, but the spec doesn't call out
+ * support for the server requesting a bigger blksize than the client
+ * requests */
+ failf(data, "%s (%ld)",
+ "server requested blksize larger than allocated", blksize);
+ return CURLE_TFTP_ILLEGAL;
+ }
+
+ state->blksize = (int)blksize;
+ infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK",
+ state->blksize, "requested", state->requested_blksize);
+ }
+ else if(checkprefix(option, TFTP_OPTION_TSIZE)) {
+ long tsize = 0;
+
+ tsize = strtol( value, NULL, 10 );
+ infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize);
+
+ /* tsize should be ignored on upload: Who cares about the size of the
+ remote file? */
+ if(!data->set.upload) {
+ if(!tsize) {
+ failf(data, "invalid tsize -:%s:- value in OACK packet", value);
+ return CURLE_TFTP_ILLEGAL;
+ }
+ Curl_pgrsSetDownloadSize(data, tsize);
+ }
+ }
+ }
+
+ return CURLE_OK;
+}
+
+static size_t tftp_option_add(tftp_state_data_t *state, size_t csize,
+ char *buf, const char *option)
+{
+ if(( strlen(option) + csize + 1 ) > (size_t)state->blksize)
+ return 0;
+ strcpy(buf, option);
+ return( strlen(option) + 1 );
+}
+
+static CURLcode tftp_connect_for_tx(tftp_state_data_t *state,
+ tftp_event_t event)
+{
+ CURLcode res;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ struct SessionHandle *data = state->conn->data;
+
+ infof(data, "%s\n", "Connected for transmit");
+#endif
+ state->state = TFTP_STATE_TX;
+ res = tftp_set_timeouts(state);
+ if(res != CURLE_OK)
+ return(res);
+ return tftp_tx(state, event);
+}
+
+static CURLcode tftp_connect_for_rx(tftp_state_data_t *state,
+ tftp_event_t event)
+{
+ CURLcode res;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ struct SessionHandle *data = state->conn->data;
+
+ infof(data, "%s\n", "Connected for receive");
+#endif
+ state->state = TFTP_STATE_RX;
+ res = tftp_set_timeouts(state);
+ if(res != CURLE_OK)
+ return(res);
+ return tftp_rx(state, event);
+}
+
+static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
+{
+ size_t sbytes;
+ ssize_t senddata;
+ const char *mode = "octet";
+ char *filename;
+ char buf[64];
+ struct SessionHandle *data = state->conn->data;
+ CURLcode res = CURLE_OK;
+
+ /* Set ascii mode if -B flag was used */
+ if(data->set.prefer_ascii)
+ mode = "netascii";
+
+ switch(event) {
+
+ case TFTP_EVENT_INIT: /* Send the first packet out */
+ case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */
+ /* Increment the retry counter, quit if over the limit */
+ state->retries++;
+ if(state->retries>state->retry_max) {
+ state->error = TFTP_ERR_NORESPONSE;
+ state->state = TFTP_STATE_FIN;
+ return res;
+ }
+
+ if(data->set.upload) {
+ /* If we are uploading, send an WRQ */
+ setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
+ state->conn->data->req.upload_fromhere =
+ (char *)state->spacket.data+4;
+ if(data->state.infilesize != -1)
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+ else {
+ /* If we are downloading, send an RRQ */
+ setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
+ }
+ /* As RFC3617 describes the separator slash is not actually part of the
+ file name so we skip the always-present first letter of the path
+ string. */
+ filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0,
+ NULL);
+ if(!filename)
+ return CURLE_OUT_OF_MEMORY;
+
+ snprintf((char *)state->spacket.data+2,
+ state->blksize,
+ "%s%c%s%c", filename, '\0', mode, '\0');
+ sbytes = 4 + strlen(filename) + strlen(mode);
+
+ /* add tsize option */
+ if(data->set.upload && (data->state.infilesize != -1))
+ snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
+ data->state.infilesize);
+ else
+ strcpy(buf, "0"); /* the destination is large enough */
+
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes,
+ TFTP_OPTION_TSIZE);
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes, buf);
+ /* add blksize option */
+ snprintf( buf, sizeof(buf), "%d", state->requested_blksize );
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes,
+ TFTP_OPTION_BLKSIZE);
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes, buf );
+
+ /* add timeout option */
+ snprintf( buf, sizeof(buf), "%d", state->retry_time);
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes,
+ TFTP_OPTION_INTERVAL);
+ sbytes += tftp_option_add(state, sbytes,
+ (char *)state->spacket.data+sbytes, buf );
+
+ /* the typecase for the 3rd argument is mostly for systems that do
+ not have a size_t argument, like older unixes that want an 'int' */
+ senddata = sendto(state->sockfd, (void *)state->spacket.data,
+ (SEND_TYPE_ARG3)sbytes, 0,
+ state->conn->ip_addr->ai_addr,
+ state->conn->ip_addr->ai_addrlen);
+ if(senddata != (ssize_t)sbytes) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ }
+ Curl_safefree(filename);
+ break;
+
+ case TFTP_EVENT_OACK:
+ if(data->set.upload) {
+ res = tftp_connect_for_tx(state, event);
+ }
+ else {
+ res = tftp_connect_for_rx(state, event);
+ }
+ break;
+
+ case TFTP_EVENT_ACK: /* Connected for transmit */
+ res = tftp_connect_for_tx(state, event);
+ break;
+
+ case TFTP_EVENT_DATA: /* Connected for receive */
+ res = tftp_connect_for_rx(state, event);
+ break;
+
+ case TFTP_EVENT_ERROR:
+ state->state = TFTP_STATE_FIN;
+ break;
+
+ default:
+ failf(state->conn->data, "tftp_send_first: internal error");
+ break;
+ }
+ return res;
+}
+
+/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit
+ boundary */
+#define NEXT_BLOCKNUM(x) (((x)+1)&0xffff)
+
+/**********************************************************
+ *
+ * tftp_rx
+ *
+ * Event handler for the RX state
+ *
+ **********************************************************/
+static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
+{
+ ssize_t sbytes;
+ int rblock;
+ struct SessionHandle *data = state->conn->data;
+
+ switch(event) {
+
+ case TFTP_EVENT_DATA:
+ /* Is this the block we expect? */
+ rblock = getrpacketblock(&state->rpacket);
+ if(NEXT_BLOCKNUM(state->block) == rblock) {
+ /* This is the expected block. Reset counters and ACK it. */
+ state->retries = 0;
+ }
+ else if(state->block == rblock) {
+ /* This is the last recently received block again. Log it and ACK it
+ again. */
+ infof(data, "Received last DATA packet block %d again.\n", rblock);
+ }
+ else {
+ /* totally unexpected, just log it */
+ infof(data,
+ "Received unexpected DATA packet block %d, expecting block %d\n",
+ rblock, NEXT_BLOCKNUM(state->block));
+ break;
+ }
+
+ /* ACK this block. */
+ state->block = (unsigned short)rblock;
+ setpacketevent(&state->spacket, TFTP_EVENT_ACK);
+ setpacketblock(&state->spacket, state->block);
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ if(sbytes < 0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+
+ /* Check if completed (That is, a less than full packet is received) */
+ if(state->rbytes < (ssize_t)state->blksize+4) {
+ state->state = TFTP_STATE_FIN;
+ }
+ else {
+ state->state = TFTP_STATE_RX;
+ }
+ time(&state->rx_time);
+ break;
+
+ case TFTP_EVENT_OACK:
+ /* ACK option acknowledgement so we can move on to data */
+ state->block = 0;
+ state->retries = 0;
+ setpacketevent(&state->spacket, TFTP_EVENT_ACK);
+ setpacketblock(&state->spacket, state->block);
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ if(sbytes < 0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+
+ /* we're ready to RX data */
+ state->state = TFTP_STATE_RX;
+ time(&state->rx_time);
+ break;
+
+ case TFTP_EVENT_TIMEOUT:
+ /* Increment the retry count and fail if over the limit */
+ state->retries++;
+ infof(data,
+ "Timeout waiting for block %d ACK. Retries = %d\n",
+ NEXT_BLOCKNUM(state->block), state->retries);
+ if(state->retries > state->retry_max) {
+ state->error = TFTP_ERR_TIMEOUT;
+ state->state = TFTP_STATE_FIN;
+ }
+ else {
+ /* Resend the previous ACK */
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ if(sbytes<0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+ }
+ break;
+
+ case TFTP_EVENT_ERROR:
+ setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
+ setpacketblock(&state->spacket, state->block);
+ (void)sendto(state->sockfd, (void *)state->spacket.data,
+ 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* don't bother with the return code, but if the socket is still up we
+ * should be a good TFTP client and let the server know we're done */
+ state->state = TFTP_STATE_FIN;
+ break;
+
+ default:
+ failf(data, "%s", "tftp_rx: internal error");
+ return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for
+ this */
+ }
+ return CURLE_OK;
+}
+
+/**********************************************************
+ *
+ * tftp_tx
+ *
+ * Event handler for the TX state
+ *
+ **********************************************************/
+static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
+{
+ struct SessionHandle *data = state->conn->data;
+ ssize_t sbytes;
+ int rblock;
+ CURLcode res = CURLE_OK;
+ struct SingleRequest *k = &data->req;
+
+ switch(event) {
+
+ case TFTP_EVENT_ACK:
+ case TFTP_EVENT_OACK:
+ if(event == TFTP_EVENT_ACK) {
+ /* Ack the packet */
+ rblock = getrpacketblock(&state->rpacket);
+
+ if(rblock != state->block &&
+ /* There's a bug in tftpd-hpa that causes it to send us an ack for
+ * 65535 when the block number wraps to 0. So when we're expecting
+ * 0, also accept 65535. See
+ * http://syslinux.zytor.com/archives/2010-September/015253.html
+ * */
+ !(state->block == 0 && rblock == 65535)) {
+ /* This isn't the expected block. Log it and up the retry counter */
+ infof(data, "Received ACK for block %d, expecting %d\n",
+ rblock, state->block);
+ state->retries++;
+ /* Bail out if over the maximum */
+ if(state->retries>state->retry_max) {
+ failf(data, "tftp_tx: giving up waiting for block %d ack",
+ state->block);
+ res = CURLE_SEND_ERROR;
+ }
+ else {
+ /* Re-send the data packet */
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4+state->sbytes, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* Check all sbytes were sent */
+ if(sbytes<0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ res = CURLE_SEND_ERROR;
+ }
+ }
+ return res;
+ }
+ /* This is the expected packet. Reset the counters and send the next
+ block */
+ time(&state->rx_time);
+ state->block++;
+ }
+ else
+ state->block = 1; /* first data block is 1 when using OACK */
+
+ state->retries = 0;
+ setpacketevent(&state->spacket, TFTP_EVENT_DATA);
+ setpacketblock(&state->spacket, state->block);
+ if(state->block > 1 && state->sbytes < (int)state->blksize) {
+ state->state = TFTP_STATE_FIN;
+ return CURLE_OK;
+ }
+ res = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes);
+ if(res)
+ return res;
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4+state->sbytes, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* Check all sbytes were sent */
+ if(sbytes<0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+ /* Update the progress meter */
+ k->writebytecount += state->sbytes;
+ Curl_pgrsSetUploadCounter(data, k->writebytecount);
+ break;
+
+ case TFTP_EVENT_TIMEOUT:
+ /* Increment the retry counter and log the timeout */
+ state->retries++;
+ infof(data, "Timeout waiting for block %d ACK. "
+ " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries);
+ /* Decide if we've had enough */
+ if(state->retries > state->retry_max) {
+ state->error = TFTP_ERR_TIMEOUT;
+ state->state = TFTP_STATE_FIN;
+ }
+ else {
+ /* Re-send the data packet */
+ sbytes = sendto(state->sockfd, (void *)state->spacket.data,
+ 4+state->sbytes, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* Check all sbytes were sent */
+ if(sbytes<0) {
+ failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+ return CURLE_SEND_ERROR;
+ }
+ /* since this was a re-send, we remain at the still byte position */
+ Curl_pgrsSetUploadCounter(data, k->writebytecount);
+ }
+ break;
+
+ case TFTP_EVENT_ERROR:
+ state->state = TFTP_STATE_FIN;
+ setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
+ setpacketblock(&state->spacket, state->block);
+ (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG,
+ (struct sockaddr *)&state->remote_addr,
+ state->remote_addrlen);
+ /* don't bother with the return code, but if the socket is still up we
+ * should be a good TFTP client and let the server know we're done */
+ state->state = TFTP_STATE_FIN;
+ break;
+
+ default:
+ failf(data, "tftp_tx: internal error, event: %i", (int)(event));
+ break;
+ }
+
+ return res;
+}
+
+/**********************************************************
+ *
+ * tftp_translate_code
+ *
+ * Translate internal error codes to CURL error codes
+ *
+ **********************************************************/
+static CURLcode tftp_translate_code(tftp_error_t error)
+{
+ CURLcode code = CURLE_OK;
+
+ if(error != TFTP_ERR_NONE) {
+ switch(error) {
+ case TFTP_ERR_NOTFOUND:
+ code = CURLE_TFTP_NOTFOUND;
+ break;
+ case TFTP_ERR_PERM:
+ code = CURLE_TFTP_PERM;
+ break;
+ case TFTP_ERR_DISKFULL:
+ code = CURLE_REMOTE_DISK_FULL;
+ break;
+ case TFTP_ERR_UNDEF:
+ case TFTP_ERR_ILLEGAL:
+ code = CURLE_TFTP_ILLEGAL;
+ break;
+ case TFTP_ERR_UNKNOWNID:
+ code = CURLE_TFTP_UNKNOWNID;
+ break;
+ case TFTP_ERR_EXISTS:
+ code = CURLE_REMOTE_FILE_EXISTS;
+ break;
+ case TFTP_ERR_NOSUCHUSER:
+ code = CURLE_TFTP_NOSUCHUSER;
+ break;
+ case TFTP_ERR_TIMEOUT:
+ code = CURLE_OPERATION_TIMEDOUT;
+ break;
+ case TFTP_ERR_NORESPONSE:
+ code = CURLE_COULDNT_CONNECT;
+ break;
+ default:
+ code= CURLE_ABORTED_BY_CALLBACK;
+ break;
+ }
+ }
+ else {
+ code = CURLE_OK;
+ }
+
+ return(code);
+}
+
+/**********************************************************
+ *
+ * tftp_state_machine
+ *
+ * The tftp state machine event dispatcher
+ *
+ **********************************************************/
+static CURLcode tftp_state_machine(tftp_state_data_t *state,
+ tftp_event_t event)
+{
+ CURLcode res = CURLE_OK;
+ struct SessionHandle *data = state->conn->data;
+ switch(state->state) {
+ case TFTP_STATE_START:
+ DEBUGF(infof(data, "TFTP_STATE_START\n"));
+ res = tftp_send_first(state, event);
+ break;
+ case TFTP_STATE_RX:
+ DEBUGF(infof(data, "TFTP_STATE_RX\n"));
+ res = tftp_rx(state, event);
+ break;
+ case TFTP_STATE_TX:
+ DEBUGF(infof(data, "TFTP_STATE_TX\n"));
+ res = tftp_tx(state, event);
+ break;
+ case TFTP_STATE_FIN:
+ infof(data, "%s\n", "TFTP finished");
+ break;
+ default:
+ DEBUGF(infof(data, "STATE: %d\n", state->state));
+ failf(data, "%s", "Internal state machine error");
+ res = CURLE_TFTP_ILLEGAL;
+ break;
+ }
+ return res;
+}
+
+/**********************************************************
+ *
+ * tftp_disconnect
+ *
+ * The disconnect callback
+ *
+ **********************************************************/
+static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ tftp_state_data_t *state = conn->proto.tftpc;
+ (void) dead_connection;
+
+ /* done, free dynamically allocated pkt buffers */
+ if(state) {
+ Curl_safefree(state->rpacket.data);
+ Curl_safefree(state->spacket.data);
+ free(state);
+ }
+
+ return CURLE_OK;
+}
+
+/**********************************************************
+ *
+ * tftp_connect
+ *
+ * The connect callback
+ *
+ **********************************************************/
+static CURLcode tftp_connect(struct connectdata *conn, bool *done)
+{
+ CURLcode code;
+ tftp_state_data_t *state;
+ int blksize, rc;
+
+ blksize = TFTP_BLKSIZE_DEFAULT;
+
+ state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
+ if(!state)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* alloc pkt buffers based on specified blksize */
+ if(conn->data->set.tftp_blksize) {
+ blksize = (int)conn->data->set.tftp_blksize;
+ if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN )
+ return CURLE_TFTP_ILLEGAL;
+ }
+
+ if(!state->rpacket.data) {
+ state->rpacket.data = calloc(1, blksize + 2 + 2);
+
+ if(!state->rpacket.data)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!state->spacket.data) {
+ state->spacket.data = calloc(1, blksize + 2 + 2);
+
+ if(!state->spacket.data)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* we don't keep TFTP connections up bascially because there's none or very
+ * little gain for UDP */
+ connclose(conn, "TFTP");
+
+ state->conn = conn;
+ state->sockfd = state->conn->sock[FIRSTSOCKET];
+ state->state = TFTP_STATE_START;
+ state->error = TFTP_ERR_NONE;
+ state->blksize = TFTP_BLKSIZE_DEFAULT;
+ state->requested_blksize = blksize;
+
+ ((struct sockaddr *)&state->local_addr)->sa_family =
+ (unsigned short)(conn->ip_addr->ai_family);
+
+ tftp_set_timeouts(state);
+
+ if(!conn->bits.bound) {
+ /* If not already bound, bind to any interface, random UDP port. If it is
+ * reused or a custom local port was desired, this has already been done!
+ *
+ * We once used the size of the local_addr struct as the third argument
+ * for bind() to better work with IPv6 or whatever size the struct could
+ * have, but we learned that at least Tru64, AIX and IRIX *requires* the
+ * size of that argument to match the exact size of a 'sockaddr_in' struct
+ * when running IPv4-only.
+ *
+ * Therefore we use the size from the address we connected to, which we
+ * assume uses the same IP version and thus hopefully this works for both
+ * IPv4 and IPv6...
+ */
+ rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
+ conn->ip_addr->ai_addrlen);
+ if(rc) {
+ failf(conn->data, "bind() failed; %s",
+ Curl_strerror(conn, SOCKERRNO));
+ return CURLE_COULDNT_CONNECT;
+ }
+ conn->bits.bound = TRUE;
+ }
+
+ Curl_pgrsStartNow(conn->data);
+
+ *done = TRUE;
+ code = CURLE_OK;
+ return(code);
+}
+
+/**********************************************************
+ *
+ * tftp_done
+ *
+ * The done callback
+ *
+ **********************************************************/
+static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
+ bool premature)
+{
+ CURLcode code = CURLE_OK;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+
+ (void)status; /* unused */
+ (void)premature; /* not used */
+
+ if(Curl_pgrsDone(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+
+ /* If we have encountered an error */
+ if(state)
+ code = tftp_translate_code(state->error);
+
+ return code;
+}
+
+/**********************************************************
+ *
+ * tftp_getsock
+ *
+ * The getsock callback
+ *
+ **********************************************************/
+static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks)
+{
+ if(!numsocks)
+ return GETSOCK_BLANK;
+
+ socks[0] = conn->sock[FIRSTSOCKET];
+
+ return GETSOCK_READSOCK(0);
+}
+
+/**********************************************************
+ *
+ * tftp_receive_packet
+ *
+ * Called once select fires and data is ready on the socket
+ *
+ **********************************************************/
+static CURLcode tftp_receive_packet(struct connectdata *conn)
+{
+ struct Curl_sockaddr_storage fromaddr;
+ curl_socklen_t fromlen;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ struct SingleRequest *k = &data->req;
+
+ /* Receive the packet */
+ fromlen = sizeof(fromaddr);
+ state->rbytes = (int)recvfrom(state->sockfd,
+ (void *)state->rpacket.data,
+ state->blksize+4,
+ 0,
+ (struct sockaddr *)&fromaddr,
+ &fromlen);
+ if(state->remote_addrlen==0) {
+ memcpy(&state->remote_addr, &fromaddr, fromlen);
+ state->remote_addrlen = fromlen;
+ }
+
+ /* Sanity check packet length */
+ if(state->rbytes < 4) {
+ failf(data, "Received too short packet");
+ /* Not a timeout, but how best to handle it? */
+ state->event = TFTP_EVENT_TIMEOUT;
+ }
+ else {
+ /* The event is given by the TFTP packet time */
+ state->event = (tftp_event_t)getrpacketevent(&state->rpacket);
+
+ switch(state->event) {
+ case TFTP_EVENT_DATA:
+ /* Don't pass to the client empty or retransmitted packets */
+ if(state->rbytes > 4 &&
+ (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ (char *)state->rpacket.data+4,
+ state->rbytes-4);
+ if(result) {
+ tftp_state_machine(state, TFTP_EVENT_ERROR);
+ return result;
+ }
+ k->bytecount += state->rbytes-4;
+ Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
+ }
+ break;
+ case TFTP_EVENT_ERROR:
+ state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
+ infof(data, "%s\n", (const char *)state->rpacket.data+4);
+ break;
+ case TFTP_EVENT_ACK:
+ break;
+ case TFTP_EVENT_OACK:
+ result = tftp_parse_option_ack(state,
+ (const char *)state->rpacket.data+2,
+ state->rbytes-2);
+ if(result)
+ return result;
+ break;
+ case TFTP_EVENT_RRQ:
+ case TFTP_EVENT_WRQ:
+ default:
+ failf(data, "%s", "Internal error: Unexpected packet");
+ break;
+ }
+
+ /* Update the progress meter */
+ if(Curl_pgrsUpdate(conn)) {
+ tftp_state_machine(state, TFTP_EVENT_ERROR);
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+ }
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_state_timeout
+ *
+ * Check if timeouts have been reached
+ *
+ **********************************************************/
+static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
+{
+ time_t current;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+
+ if(event)
+ *event = TFTP_EVENT_NONE;
+
+ time(&current);
+ if(current > state->max_time) {
+ DEBUGF(infof(conn->data, "timeout: %ld > %ld\n",
+ (long)current, (long)state->max_time));
+ state->error = TFTP_ERR_TIMEOUT;
+ state->state = TFTP_STATE_FIN;
+ return 0;
+ }
+ else if(current > state->rx_time+state->retry_time) {
+ if(event)
+ *event = TFTP_EVENT_TIMEOUT;
+ time(&state->rx_time); /* update even though we received nothing */
+ }
+
+ /* there's a typecast below here since 'time_t' may in fact be larger than
+ 'long', but we estimate that a 'long' will still be able to hold number
+ of seconds even if "only" 32 bit */
+ return (long)(state->max_time - current);
+}
+
+/**********************************************************
+ *
+ * tftp_multi_statemach
+ *
+ * Handle single RX socket event and return
+ *
+ **********************************************************/
+static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
+{
+ int rc;
+ tftp_event_t event;
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ long timeout_ms = tftp_state_timeout(conn, &event);
+
+ *done = FALSE;
+
+ if(timeout_ms <= 0) {
+ failf(data, "TFTP response timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ else if(event != TFTP_EVENT_NONE) {
+ result = tftp_state_machine(state, event);
+ if(result != CURLE_OK)
+ return(result);
+ *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
+ if(*done)
+ /* Tell curl we're done */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ }
+ else {
+ /* no timeouts to handle, check our socket */
+ rc = Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, 0);
+
+ if(rc == -1) {
+ /* bail out */
+ int error = SOCKERRNO;
+ failf(data, "%s", Curl_strerror(conn, error));
+ state->event = TFTP_EVENT_ERROR;
+ }
+ else if(rc != 0) {
+ result = tftp_receive_packet(conn);
+ if(result != CURLE_OK)
+ return(result);
+ result = tftp_state_machine(state, state->event);
+ if(result != CURLE_OK)
+ return(result);
+ *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
+ if(*done)
+ /* Tell curl we're done */
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ }
+ /* if rc == 0, then select() timed out */
+ }
+
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_doing
+ *
+ * Called from multi.c while DOing
+ *
+ **********************************************************/
+static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result;
+ result = tftp_multi_statemach(conn, dophase_done);
+
+ if(*dophase_done) {
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ }
+ else if(!result) {
+ /* The multi code doesn't have this logic for the DOING state so we
+ provide it for TFTP since it may do the entire transfer in this
+ state. */
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(conn->data, Curl_tvnow());
+ }
+ return result;
+}
+
+/**********************************************************
+ *
+ * tftp_peform
+ *
+ * Entry point for transfer from tftp_do, sarts state mach
+ *
+ **********************************************************/
+static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
+{
+ CURLcode result = CURLE_OK;
+ tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+
+ *dophase_done = FALSE;
+
+ result = tftp_state_machine(state, TFTP_EVENT_INIT);
+
+ if(state->state == TFTP_STATE_FIN || result != CURLE_OK)
+ return(result);
+
+ tftp_multi_statemach(conn, dophase_done);
+
+ if(*dophase_done)
+ DEBUGF(infof(conn->data, "DO phase is complete\n"));
+
+ return result;
+}
+
+
+/**********************************************************
+ *
+ * tftp_do
+ *
+ * The do callback
+ *
+ * This callback initiates the TFTP transfer
+ *
+ **********************************************************/
+
+static CURLcode tftp_do(struct connectdata *conn, bool *done)
+{
+ tftp_state_data_t *state;
+ CURLcode code;
+
+ *done = FALSE;
+
+ if(!conn->proto.tftpc) {
+ code = tftp_connect(conn, done);
+ if(code)
+ return code;
+ }
+
+ state = (tftp_state_data_t *)conn->proto.tftpc;
+ if(!state)
+ return CURLE_BAD_CALLING_ORDER;
+
+ code = tftp_perform(conn, done);
+
+ /* If tftp_perform() returned an error, use that for return code. If it
+ was OK, see if tftp_translate_code() has an error. */
+ if(code == CURLE_OK)
+ /* If we have encountered an internal tftp error, translate it. */
+ code = tftp_translate_code(state->error);
+
+ return code;
+}
+
+static CURLcode tftp_setup_connection(struct connectdata * conn)
+{
+ struct SessionHandle *data = conn->data;
+ char * type;
+ char command;
+
+ conn->socktype = SOCK_DGRAM; /* UDP datagram based */
+
+ /* TFTP URLs support an extension like ";mode=<typecode>" that
+ * we'll try to get now! */
+ type = strstr(data->state.path, ";mode=");
+
+ if(!type)
+ type = strstr(conn->host.rawalloc, ";mode=");
+
+ if(type) {
+ *type = 0; /* it was in the middle of the hostname */
+ command = Curl_raw_toupper(type[6]);
+
+ switch (command) {
+ case 'A': /* ASCII mode */
+ case 'N': /* NETASCII mode */
+ data->set.prefer_ascii = TRUE;
+ break;
+
+ case 'O': /* octet mode */
+ case 'I': /* binary mode */
+ default:
+ /* switch off ASCII */
+ data->set.prefer_ascii = FALSE;
+ break;
+ }
+ }
+
+ return CURLE_OK;
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/tftp.h b/external/libcurl_android/jni/libcurl/lib/tftp.h
new file mode 100755
index 00000000..117b40f6
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/tftp.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TFTP_H
+#define HEADER_CURL_TFTP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_TFTP
+extern const struct Curl_handler Curl_handler_tftp;
+#endif
+
+#endif /* HEADER_CURL_TFTP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/timeval.c b/external/libcurl_android/jni/libcurl/lib/timeval.c
new file mode 100755
index 00000000..2fd72014
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/timeval.c
@@ -0,0 +1,134 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "timeval.h"
+
+#if defined(WIN32) && !defined(MSDOS)
+
+struct timeval curlx_tvnow(void)
+{
+ /*
+ ** GetTickCount() is available on _all_ Windows versions from W95 up
+ ** to nowadays. Returns milliseconds elapsed since last system boot,
+ ** increases monotonically and wraps once 49.7 days have elapsed.
+ */
+ struct timeval now;
+ DWORD milliseconds = GetTickCount();
+ now.tv_sec = milliseconds / 1000;
+ now.tv_usec = (milliseconds % 1000) * 1000;
+ return now;
+}
+
+#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
+
+struct timeval curlx_tvnow(void)
+{
+ /*
+ ** clock_gettime() is granted to be increased monotonically when the
+ ** monotonic clock is queried. Time starting point is unspecified, it
+ ** could be the system start-up time, the Epoch, or something else,
+ ** in any case the time starting point does not change once that the
+ ** system has started up.
+ */
+ struct timeval now;
+ struct timespec tsnow;
+ if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
+ now.tv_sec = tsnow.tv_sec;
+ now.tv_usec = tsnow.tv_nsec / 1000;
+ }
+ /*
+ ** Even when the configure process has truly detected monotonic clock
+ ** availability, it might happen that it is not actually available at
+ ** run-time. When this occurs simply fallback to other time source.
+ */
+#ifdef HAVE_GETTIMEOFDAY
+ else
+ (void)gettimeofday(&now, NULL);
+#else
+ else {
+ now.tv_sec = (long)time(NULL);
+ now.tv_usec = 0;
+ }
+#endif
+ return now;
+}
+
+#elif defined(HAVE_GETTIMEOFDAY)
+
+struct timeval curlx_tvnow(void)
+{
+ /*
+ ** gettimeofday() is not granted to be increased monotonically, due to
+ ** clock drifting and external source time synchronization it can jump
+ ** forward or backward in time.
+ */
+ struct timeval now;
+ (void)gettimeofday(&now, NULL);
+ return now;
+}
+
+#else
+
+struct timeval curlx_tvnow(void)
+{
+ /*
+ ** time() returns the value of time in seconds since the Epoch.
+ */
+ struct timeval now;
+ now.tv_sec = (long)time(NULL);
+ now.tv_usec = 0;
+ return now;
+}
+
+#endif
+
+/*
+ * Make sure that the first argument is the more recent time, as otherwise
+ * we'll get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+long curlx_tvdiff(struct timeval newer, struct timeval older)
+{
+ return (newer.tv_sec-older.tv_sec)*1000+
+ (newer.tv_usec-older.tv_usec)/1000;
+}
+
+/*
+ * Same as curlx_tvdiff but with full usec resolution.
+ *
+ * Returns: the time difference in seconds with subsecond resolution.
+ */
+double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
+{
+ if(newer.tv_sec != older.tv_sec)
+ return (double)(newer.tv_sec-older.tv_sec)+
+ (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+ else
+ return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+}
+
+/* return the number of seconds in the given input timeval struct */
+long Curl_tvlong(struct timeval t1)
+{
+ return t1.tv_sec;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/timeval.h b/external/libcurl_android/jni/libcurl/lib/timeval.h
new file mode 100755
index 00000000..3f1b9ea7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/timeval.h
@@ -0,0 +1,58 @@
+#ifndef HEADER_CURL_TIMEVAL_H
+#define HEADER_CURL_TIMEVAL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * CAUTION: this header is designed to work when included by the app-side
+ * as well as the library. Do not mix with library internals!
+ */
+
+#include "curl_setup.h"
+
+struct timeval curlx_tvnow(void);
+
+/*
+ * Make sure that the first argument (t1) is the more recent time and t2 is
+ * the older time, as otherwise you get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+long curlx_tvdiff(struct timeval t1, struct timeval t2);
+
+/*
+ * Same as curlx_tvdiff but with full usec resolution.
+ *
+ * Returns: the time difference in seconds with subsecond resolution.
+ */
+double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
+
+long Curl_tvlong(struct timeval t1);
+
+/* These two defines below exist to provide the older API for library
+ internals only. */
+#define Curl_tvnow() curlx_tvnow()
+#define Curl_tvdiff(x,y) curlx_tvdiff(x,y)
+#define Curl_tvdiff_secs(x,y) curlx_tvdiff_secs(x,y)
+
+#endif /* HEADER_CURL_TIMEVAL_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/transfer.c b/external/libcurl_android/jni/libcurl/lib/transfer.c
new file mode 100755
index 00000000..dc817a6c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/transfer.c
@@ -0,0 +1,1993 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "strtoofft.h"
+#include "strequal.h"
+#include "rawstr.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifndef HAVE_SOCKET
+#error "We can't compile without socket() support!"
+#endif
+
+#include "urldata.h"
+#include <curl/curl.h>
+#include "netrc.h"
+
+#include "content_encoding.h"
+#include "hostip.h"
+#include "transfer.h"
+#include "sendf.h"
+#include "speedcheck.h"
+#include "progress.h"
+#include "http.h"
+#include "url.h"
+#include "getinfo.h"
+#include "vtls/vtls.h"
+#include "http_digest.h"
+#include "curl_ntlm.h"
+#include "http_negotiate.h"
+#include "share.h"
+#include "curl_memory.h"
+#include "select.h"
+#include "multiif.h"
+#include "connect.h"
+#include "non-ascii.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * This function will call the read callback to fill our buffer with data
+ * to upload.
+ */
+CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
+{
+ struct SessionHandle *data = conn->data;
+ size_t buffersize = (size_t)bytes;
+ int nread;
+#ifdef CURL_DOES_CONVERSIONS
+ bool sending_http_headers = FALSE;
+
+ if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
+ const struct HTTP *http = data->req.protop;
+
+ if(http->sending == HTTPSEND_REQUEST)
+ /* We're sending the HTTP request headers, not the data.
+ Remember that so we don't re-translate them into garbage. */
+ sending_http_headers = TRUE;
+ }
+#endif
+
+ if(data->req.upload_chunky) {
+ /* if chunked Transfer-Encoding */
+ buffersize -= (8 + 2 + 2); /* 32bit hex + CRLF + CRLF */
+ data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
+ }
+
+ /* this function returns a size_t, so we typecast to int to prevent warnings
+ with picky compilers */
+ nread = (int)conn->fread_func(data->req.upload_fromhere, 1,
+ buffersize, conn->fread_in);
+
+ if(nread == CURL_READFUNC_ABORT) {
+ failf(data, "operation aborted by callback");
+ *nreadp = 0;
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+ else if(nread == CURL_READFUNC_PAUSE) {
+
+ if(conn->handler->flags & PROTOPT_NONETWORK) {
+ /* protocols that work without network cannot be paused. This is
+ actually only FILE:// just now, and it can't pause since the transfer
+ isn't done using the "normal" procedure. */
+ failf(data, "Read callback asked for PAUSE when not supported!");
+ return CURLE_READ_ERROR;
+ }
+ else {
+ struct SingleRequest *k = &data->req;
+ /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
+ k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
+ if(data->req.upload_chunky) {
+ /* Back out the preallocation done above */
+ data->req.upload_fromhere -= (8 + 2);
+ }
+ *nreadp = 0;
+ }
+ return CURLE_OK; /* nothing was read */
+ }
+ else if((size_t)nread > buffersize) {
+ /* the read function returned a too large value */
+ *nreadp = 0;
+ failf(data, "read function returned funny value");
+ return CURLE_READ_ERROR;
+ }
+
+ if(!data->req.forbidchunk && data->req.upload_chunky) {
+ /* if chunked Transfer-Encoding
+ * build chunk:
+ *
+ * <HEX SIZE> CRLF
+ * <DATA> CRLF
+ */
+ /* On non-ASCII platforms the <DATA> may or may not be
+ translated based on set.prefer_ascii while the protocol
+ portion must always be translated to the network encoding.
+ To further complicate matters, line end conversion might be
+ done later on, so we need to prevent CRLFs from becoming
+ CRCRLFs if that's the case. To do this we use bare LFs
+ here, knowing they'll become CRLFs later on.
+ */
+
+ char hexbuffer[11];
+ const char *endofline_native;
+ const char *endofline_network;
+ int hexlen;
+
+ if(
+#ifdef CURL_DO_LINEEND_CONV
+ (data->set.prefer_ascii) ||
+#endif
+ (data->set.crlf)) {
+ /* \n will become \r\n later on */
+ endofline_native = "\n";
+ endofline_network = "\x0a";
+ }
+ else {
+ endofline_native = "\r\n";
+ endofline_network = "\x0d\x0a";
+ }
+ hexlen = snprintf(hexbuffer, sizeof(hexbuffer),
+ "%x%s", nread, endofline_native);
+
+ /* move buffer pointer */
+ data->req.upload_fromhere -= hexlen;
+ nread += hexlen;
+
+ /* copy the prefix to the buffer, leaving out the NUL */
+ memcpy(data->req.upload_fromhere, hexbuffer, hexlen);
+
+ /* always append ASCII CRLF to the data */
+ memcpy(data->req.upload_fromhere + nread,
+ endofline_network,
+ strlen(endofline_network));
+
+#ifdef CURL_DOES_CONVERSIONS
+ CURLcode res;
+ int length;
+ if(data->set.prefer_ascii) {
+ /* translate the protocol and data */
+ length = nread;
+ }
+ else {
+ /* just translate the protocol portion */
+ length = strlen(hexbuffer);
+ }
+ res = Curl_convert_to_network(data, data->req.upload_fromhere, length);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(res)
+ return(res);
+#endif /* CURL_DOES_CONVERSIONS */
+
+ if((nread - hexlen) == 0)
+ /* mark this as done once this chunk is transferred */
+ data->req.upload_done = TRUE;
+
+ nread+=(int)strlen(endofline_native); /* for the added end of line */
+ }
+#ifdef CURL_DOES_CONVERSIONS
+ else if((data->set.prefer_ascii) && (!sending_http_headers)) {
+ CURLcode res;
+ res = Curl_convert_to_network(data, data->req.upload_fromhere, nread);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(res != CURLE_OK)
+ return(res);
+ }
+#endif /* CURL_DOES_CONVERSIONS */
+
+ *nreadp = nread;
+
+ return CURLE_OK;
+}
+
+
+/*
+ * Curl_readrewind() rewinds the read stream. This is typically used for HTTP
+ * POST/PUT with multi-pass authentication when a sending was denied and a
+ * resend is necessary.
+ */
+CURLcode Curl_readrewind(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+
+ conn->bits.rewindaftersend = FALSE; /* we rewind now */
+
+ /* explicitly switch off sending data on this connection now since we are
+ about to restart a new transfer and thus we want to avoid inadvertently
+ sending more data on the existing connection until the next transfer
+ starts */
+ data->req.keepon &= ~KEEP_SEND;
+
+ /* We have sent away data. If not using CURLOPT_POSTFIELDS or
+ CURLOPT_HTTPPOST, call app to rewind
+ */
+ if(data->set.postfields ||
+ (data->set.httpreq == HTTPREQ_POST_FORM))
+ ; /* do nothing */
+ else {
+ if(data->set.seek_func) {
+ int err;
+
+ err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
+ if(err) {
+ failf(data, "seek callback returned error %d", (int)err);
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ else if(data->set.ioctl_func) {
+ curlioerr err;
+
+ err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
+ data->set.ioctl_client);
+ infof(data, "the ioctl callback returned %d\n", (int)err);
+
+ if(err) {
+ /* FIXME: convert to a human readable error message */
+ failf(data, "ioctl callback returned error %d", (int)err);
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ else {
+ /* If no CURLOPT_READFUNCTION is used, we know that we operate on a
+ given FILE * stream and we can actually attempt to rewind that
+ ourselves with fseek() */
+ if(data->set.fread_func == (curl_read_callback)fread) {
+ if(-1 != fseek(data->set.in, 0, SEEK_SET))
+ /* successful rewind */
+ return CURLE_OK;
+ }
+
+ /* no callback set or failure above, makes us fail at once */
+ failf(data, "necessary data rewind wasn't possible");
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
+ return CURLE_OK;
+}
+
+static int data_pending(const struct connectdata *conn)
+{
+ /* in the case of libssh2, we can never be really sure that we have emptied
+ its internal buffers so we MUST always try until we get EAGAIN back */
+ return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
+#if defined(USE_NGHTTP2)
+ Curl_ssl_data_pending(conn, FIRSTSOCKET) ||
+ /* For HTTP/2, we may read up everything including responde body
+ with header fields in Curl_http_readwrite_headers. If no
+ content-length is provided, curl waits for the connection
+ close, which we emulate it using conn->proto.httpc.closed =
+ TRUE. The thing is if we read everything, then http2_recv won't
+ be called and we cannot signal the HTTP/2 stream has closed. As
+ a workaround, we return nonzero here to call http2_recv. */
+ ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20 &&
+ conn->proto.httpc.closed);
+#else
+ Curl_ssl_data_pending(conn, FIRSTSOCKET);
+#endif
+}
+
+static void read_rewind(struct connectdata *conn,
+ size_t thismuch)
+{
+ DEBUGASSERT(conn->read_pos >= thismuch);
+
+ conn->read_pos -= thismuch;
+ conn->bits.stream_was_rewound = TRUE;
+
+#ifdef DEBUGBUILD
+ {
+ char buf[512 + 1];
+ size_t show;
+
+ show = CURLMIN(conn->buf_len - conn->read_pos, sizeof(buf)-1);
+ if(conn->master_buffer) {
+ memcpy(buf, conn->master_buffer + conn->read_pos, show);
+ buf[show] = '\0';
+ }
+ else {
+ buf[0] = '\0';
+ }
+
+ DEBUGF(infof(conn->data,
+ "Buffer after stream rewind (read_pos = %zu): [%s]\n",
+ conn->read_pos, buf));
+ }
+#endif
+}
+
+/*
+ * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the
+ * remote document with the time provided by CURLOPT_TIMEVAL
+ */
+bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc)
+{
+ if((timeofdoc == 0) || (data->set.timevalue == 0))
+ return TRUE;
+
+ switch(data->set.timecondition) {
+ case CURL_TIMECOND_IFMODSINCE:
+ default:
+ if(timeofdoc <= data->set.timevalue) {
+ infof(data,
+ "The requested document is not new enough\n");
+ data->info.timecond = TRUE;
+ return FALSE;
+ }
+ break;
+ case CURL_TIMECOND_IFUNMODSINCE:
+ if(timeofdoc >= data->set.timevalue) {
+ infof(data,
+ "The requested document is not old enough\n");
+ data->info.timecond = TRUE;
+ return FALSE;
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Go ahead and do a read if we have a readable socket or if
+ * the stream was rewound (in which case we have data in a
+ * buffer)
+ */
+static CURLcode readwrite_data(struct SessionHandle *data,
+ struct connectdata *conn,
+ struct SingleRequest *k,
+ int *didwhat, bool *done)
+{
+ CURLcode result = CURLE_OK;
+ ssize_t nread; /* number of bytes read */
+ size_t excess = 0; /* excess bytes read */
+ bool is_empty_data = FALSE;
+ bool readmore = FALSE; /* used by RTP to signal for more data */
+
+ *done = FALSE;
+
+ /* This is where we loop until we have read everything there is to
+ read or we get a CURLE_AGAIN */
+ do {
+ size_t buffersize = data->set.buffer_size?
+ data->set.buffer_size : BUFSIZE;
+ size_t bytestoread = buffersize;
+
+ if(k->size != -1 && !k->header) {
+ /* make sure we don't read "too much" if we can help it since we
+ might be pipelining and then someone else might want to read what
+ follows! */
+ curl_off_t totalleft = k->size - k->bytecount;
+ if(totalleft < (curl_off_t)bytestoread)
+ bytestoread = (size_t)totalleft;
+ }
+
+ if(bytestoread) {
+ /* receive data from the network! */
+ result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread);
+
+ /* read would've blocked */
+ if(CURLE_AGAIN == result)
+ break; /* get out of loop */
+
+ if(result>0)
+ return result;
+ }
+ else {
+ /* read nothing but since we wanted nothing we consider this an OK
+ situation to proceed from */
+ nread = 0;
+ }
+
+ if((k->bytecount == 0) && (k->writebytecount == 0)) {
+ Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+ if(k->exp100 > EXP100_SEND_DATA)
+ /* set time stamp to compare with when waiting for the 100 */
+ k->start100 = Curl_tvnow();
+ }
+
+ *didwhat |= KEEP_RECV;
+ /* indicates data of zero size, i.e. empty file */
+ is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
+
+ /* NUL terminate, allowing string ops to be used */
+ if(0 < nread || is_empty_data) {
+ k->buf[nread] = 0;
+ }
+ else if(0 >= nread) {
+ /* if we receive 0 or less here, the server closed the connection
+ and we bail out from this! */
+ DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n"));
+ k->keepon &= ~KEEP_RECV;
+ break;
+ }
+
+ /* Default buffer to use when we write the buffer, it may be changed
+ in the flow below before the actual storing is done. */
+ k->str = k->buf;
+
+ if(conn->handler->readwrite) {
+ result = conn->handler->readwrite(data, conn, &nread, &readmore);
+ if(result)
+ return result;
+ if(readmore)
+ break;
+ }
+
+#ifndef CURL_DISABLE_HTTP
+ /* Since this is a two-state thing, we check if we are parsing
+ headers at the moment or not. */
+ if(k->header) {
+ /* we are in parse-the-header-mode */
+ bool stop_reading = FALSE;
+ result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading);
+ if(result)
+ return result;
+
+ if(conn->handler->readwrite &&
+ (k->maxdownload <= 0 && nread > 0)) {
+ result = conn->handler->readwrite(data, conn, &nread, &readmore);
+ if(result)
+ return result;
+ if(readmore)
+ break;
+ }
+
+ if(stop_reading) {
+ /* We've stopped dealing with input, get out of the do-while loop */
+
+ if(nread > 0) {
+ if(Curl_multi_pipeline_enabled(conn->data->multi)) {
+ infof(data,
+ "Rewinding stream by : %zd"
+ " bytes on url %s (zero-length body)\n",
+ nread, data->state.path);
+ read_rewind(conn, (size_t)nread);
+ }
+ else {
+ infof(data,
+ "Excess found in a non pipelined read:"
+ " excess = %zd"
+ " url = %s (zero-length body)\n",
+ nread, data->state.path);
+ }
+ }
+
+ break;
+ }
+ }
+#endif /* CURL_DISABLE_HTTP */
+
+
+ /* This is not an 'else if' since it may be a rest from the header
+ parsing, where the beginning of the buffer is headers and the end
+ is non-headers. */
+ if(k->str && !k->header && (nread > 0 || is_empty_data)) {
+
+#ifndef CURL_DISABLE_HTTP
+ if(0 == k->bodywrites && !is_empty_data) {
+ /* These checks are only made the first time we are about to
+ write a piece of the body */
+ if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
+ /* HTTP-only checks */
+
+ if(data->req.newurl) {
+ if(conn->bits.close) {
+ /* Abort after the headers if "follow Location" is set
+ and we're set to close anyway. */
+ k->keepon &= ~KEEP_RECV;
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ /* We have a new url to load, but since we want to be able
+ to re-use this connection properly, we read the full
+ response in "ignore more" */
+ k->ignorebody = TRUE;
+ infof(data, "Ignoring the response-body\n");
+ }
+ if(data->state.resume_from && !k->content_range &&
+ (data->set.httpreq==HTTPREQ_GET) &&
+ !k->ignorebody) {
+ /* we wanted to resume a download, although the server doesn't
+ * seem to support this and we did this with a GET (if it
+ * wasn't a GET we did a POST or PUT resume) */
+ failf(data, "HTTP server doesn't seem to support "
+ "byte ranges. Cannot resume.");
+ return CURLE_RANGE_ERROR;
+ }
+
+ if(data->set.timecondition && !data->state.range) {
+ /* A time condition has been set AND no ranges have been
+ requested. This seems to be what chapter 13.3.4 of
+ RFC 2616 defines to be the correct action for a
+ HTTP/1.1 client */
+
+ if(!Curl_meets_timecondition(data, k->timeofdoc)) {
+ *done = TRUE;
+ /* We're simulating a http 304 from server so we return
+ what should have been returned from the server */
+ data->info.httpcode = 304;
+ infof(data, "Simulate a HTTP 304 response!\n");
+ /* we abort the transfer before it is completed == we ruin the
+ re-use ability. Close the connection */
+ connclose(conn, "Simulated 304 handling");
+ return CURLE_OK;
+ }
+ } /* we have a time condition */
+
+ } /* this is HTTP or RTSP */
+ } /* this is the first time we write a body part */
+#endif /* CURL_DISABLE_HTTP */
+
+ k->bodywrites++;
+
+ /* pass data to the debug function before it gets "dechunked" */
+ if(data->set.verbose) {
+ if(k->badheader) {
+ Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
+ (size_t)k->hbuflen, conn);
+ if(k->badheader == HEADER_PARTHEADER)
+ Curl_debug(data, CURLINFO_DATA_IN,
+ k->str, (size_t)nread, conn);
+ }
+ else
+ Curl_debug(data, CURLINFO_DATA_IN,
+ k->str, (size_t)nread, conn);
+ }
+
+#ifndef CURL_DISABLE_HTTP
+ if(k->chunk) {
+ /*
+ * Here comes a chunked transfer flying and we need to decode this
+ * properly. While the name says read, this function both reads
+ * and writes away the data. The returned 'nread' holds the number
+ * of actual data it wrote to the client.
+ */
+
+ CHUNKcode res =
+ Curl_httpchunk_read(conn, k->str, nread, &nread);
+
+ if(CHUNKE_OK < res) {
+ if(CHUNKE_WRITE_ERROR == res) {
+ failf(data, "Failed writing data");
+ return CURLE_WRITE_ERROR;
+ }
+ failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
+ return CURLE_RECV_ERROR;
+ }
+ else if(CHUNKE_STOP == res) {
+ size_t dataleft;
+ /* we're done reading chunks! */
+ k->keepon &= ~KEEP_RECV; /* read no more */
+
+ /* There are now possibly N number of bytes at the end of the
+ str buffer that weren't written to the client.
+
+ We DO care about this data if we are pipelining.
+ Push it back to be read on the next pass. */
+
+ dataleft = conn->chunk.dataleft;
+ if(dataleft != 0) {
+ infof(conn->data, "Leftovers after chunking: %zu bytes\n",
+ dataleft);
+ if(Curl_multi_pipeline_enabled(conn->data->multi)) {
+ /* only attempt the rewind if we truly are pipelining */
+ infof(conn->data, "Rewinding %zu bytes\n",dataleft);
+ read_rewind(conn, dataleft);
+ }
+ }
+ }
+ /* If it returned OK, we just keep going */
+ }
+#endif /* CURL_DISABLE_HTTP */
+
+ /* Account for body content stored in the header buffer */
+ if(k->badheader && !k->ignorebody) {
+ DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n",
+ k->hbuflen));
+ k->bytecount += k->hbuflen;
+ }
+
+ if((-1 != k->maxdownload) &&
+ (k->bytecount + nread >= k->maxdownload)) {
+
+ excess = (size_t)(k->bytecount + nread - k->maxdownload);
+ if(excess > 0 && !k->ignorebody) {
+ if(Curl_multi_pipeline_enabled(conn->data->multi)) {
+ /* The 'excess' amount below can't be more than BUFSIZE which
+ always will fit in a size_t */
+ infof(data,
+ "Rewinding stream by : %zu"
+ " bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T
+ ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
+ ", bytecount = %" CURL_FORMAT_CURL_OFF_T ", nread = %zd)\n",
+ excess, data->state.path,
+ k->size, k->maxdownload, k->bytecount, nread);
+ read_rewind(conn, excess);
+ }
+ else {
+ infof(data,
+ "Excess found in a non pipelined read:"
+ " excess = %zu"
+ ", size = %" CURL_FORMAT_CURL_OFF_T
+ ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
+ ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n",
+ excess, k->size, k->maxdownload, k->bytecount);
+ }
+ }
+
+ nread = (ssize_t) (k->maxdownload - k->bytecount);
+ if(nread < 0 ) /* this should be unusual */
+ nread = 0;
+
+ k->keepon &= ~KEEP_RECV; /* we're done reading */
+ }
+
+ k->bytecount += nread;
+
+ Curl_pgrsSetDownloadCounter(data, k->bytecount);
+
+ if(!k->chunk && (nread || k->badheader || is_empty_data)) {
+ /* If this is chunky transfer, it was already written */
+
+ if(k->badheader && !k->ignorebody) {
+ /* we parsed a piece of data wrongly assuming it was a header
+ and now we output it as body instead */
+
+ /* Don't let excess data pollute body writes */
+ if(k->maxdownload == -1 || (curl_off_t)k->hbuflen <= k->maxdownload)
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ data->state.headerbuff,
+ k->hbuflen);
+ else
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ data->state.headerbuff,
+ (size_t)k->maxdownload);
+
+ if(result)
+ return result;
+ }
+ if(k->badheader < HEADER_ALLBAD) {
+ /* This switch handles various content encodings. If there's an
+ error here, be sure to check over the almost identical code
+ in http_chunks.c.
+ Make sure that ALL_CONTENT_ENCODINGS contains all the
+ encodings handled here. */
+#ifdef HAVE_LIBZ
+ switch (conn->data->set.http_ce_skip ?
+ IDENTITY : k->auto_decoding) {
+ case IDENTITY:
+#endif
+ /* This is the default when the server sends no
+ Content-Encoding header. See Curl_readwrite_init; the
+ memset() call initializes k->auto_decoding to zero. */
+ if(!k->ignorebody) {
+
+#ifndef CURL_DISABLE_POP3
+ if(conn->handler->protocol&PROTO_FAMILY_POP3)
+ result = Curl_pop3_write(conn, k->str, nread);
+ else
+#endif /* CURL_DISABLE_POP3 */
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str,
+ nread);
+ }
+#ifdef HAVE_LIBZ
+ break;
+
+ case DEFLATE:
+ /* Assume CLIENTWRITE_BODY; headers are not encoded. */
+ if(!k->ignorebody)
+ result = Curl_unencode_deflate_write(conn, k, nread);
+ break;
+
+ case GZIP:
+ /* Assume CLIENTWRITE_BODY; headers are not encoded. */
+ if(!k->ignorebody)
+ result = Curl_unencode_gzip_write(conn, k, nread);
+ break;
+
+ case COMPRESS:
+ default:
+ failf (data, "Unrecognized content encoding type. "
+ "libcurl understands `identity', `deflate' and `gzip' "
+ "content encodings.");
+ result = CURLE_BAD_CONTENT_ENCODING;
+ break;
+ }
+#endif
+ }
+ k->badheader = HEADER_NORMAL; /* taken care of now */
+
+ if(result)
+ return result;
+ }
+
+ } /* if(! header and data to read ) */
+
+ if(conn->handler->readwrite &&
+ (excess > 0 && !conn->bits.stream_was_rewound)) {
+ /* Parse the excess data */
+ k->str += nread;
+ nread = (ssize_t)excess;
+
+ result = conn->handler->readwrite(data, conn, &nread, &readmore);
+ if(result)
+ return result;
+
+ if(readmore)
+ k->keepon |= KEEP_RECV; /* we're not done reading */
+ break;
+ }
+
+ if(is_empty_data) {
+ /* if we received nothing, the server closed the connection and we
+ are done */
+ k->keepon &= ~KEEP_RECV;
+ }
+
+ } while(data_pending(conn));
+
+ if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
+ conn->bits.close ) {
+ /* When we've read the entire thing and the close bit is set, the server
+ may now close the connection. If there's now any kind of sending going
+ on from our side, we need to stop that immediately. */
+ infof(data, "we are done reading and this is set to close, stop send\n");
+ k->keepon &= ~KEEP_SEND; /* no writing anymore either */
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Send data to upload to the server, when the socket is writable.
+ */
+static CURLcode readwrite_upload(struct SessionHandle *data,
+ struct connectdata *conn,
+ struct SingleRequest *k,
+ int *didwhat)
+{
+ ssize_t i, si;
+ ssize_t bytes_written;
+ CURLcode result;
+ ssize_t nread; /* number of bytes read */
+ bool sending_http_headers = FALSE;
+
+ if((k->bytecount == 0) && (k->writebytecount == 0))
+ Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+
+ *didwhat |= KEEP_SEND;
+
+ /*
+ * We loop here to do the READ and SEND loop until we run out of
+ * data to send or until we get EWOULDBLOCK back
+ *
+ * FIXME: above comment is misleading. Currently no looping is
+ * actually done in do-while loop below.
+ */
+ do {
+
+ /* only read more data if there's no upload data already
+ present in the upload buffer */
+ if(0 == data->req.upload_present) {
+ /* init the "upload from here" pointer */
+ data->req.upload_fromhere = k->uploadbuf;
+
+ if(!k->upload_done) {
+ /* HTTP pollution, this should be written nicer to become more
+ protocol agnostic. */
+ int fillcount;
+ struct HTTP *http = data->req.protop;
+
+ if((k->exp100 == EXP100_SENDING_REQUEST) &&
+ (http->sending == HTTPSEND_BODY)) {
+ /* If this call is to send body data, we must take some action:
+ We have sent off the full HTTP 1.1 request, and we shall now
+ go into the Expect: 100 state and await such a header */
+ k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */
+ k->keepon &= ~KEEP_SEND; /* disable writing */
+ k->start100 = Curl_tvnow(); /* timeout count starts now */
+ *didwhat &= ~KEEP_SEND; /* we didn't write anything actually */
+
+ /* set a timeout for the multi interface */
+ Curl_expire(data, data->set.expect_100_timeout);
+ break;
+ }
+
+ if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
+ if(http->sending == HTTPSEND_REQUEST)
+ /* We're sending the HTTP request headers, not the data.
+ Remember that so we don't change the line endings. */
+ sending_http_headers = TRUE;
+ else
+ sending_http_headers = FALSE;
+ }
+
+ result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);
+ if(result)
+ return result;
+
+ nread = (ssize_t)fillcount;
+ }
+ else
+ nread = 0; /* we're done uploading/reading */
+
+ if(!nread && (k->keepon & KEEP_SEND_PAUSE)) {
+ /* this is a paused transfer */
+ break;
+ }
+ else if(nread<=0) {
+ /* done */
+ k->keepon &= ~KEEP_SEND; /* we're done writing */
+
+ if(conn->bits.rewindaftersend) {
+ result = Curl_readrewind(conn);
+ if(result)
+ return result;
+ }
+ break;
+ }
+
+ /* store number of bytes available for upload */
+ data->req.upload_present = nread;
+
+#ifndef CURL_DISABLE_SMTP
+ if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
+ result = Curl_smtp_escape_eob(conn, nread);
+ if(result)
+ return result;
+ }
+ else
+#endif /* CURL_DISABLE_SMTP */
+
+ /* convert LF to CRLF if so asked */
+ if((!sending_http_headers) && (
+#ifdef CURL_DO_LINEEND_CONV
+ /* always convert if we're FTPing in ASCII mode */
+ (data->set.prefer_ascii) ||
+#endif
+ (data->set.crlf))) {
+ if(data->state.scratch == NULL)
+ data->state.scratch = malloc(2*BUFSIZE);
+ if(data->state.scratch == NULL) {
+ failf (data, "Failed to alloc scratch buffer!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ /*
+ * ASCII/EBCDIC Note: This is presumably a text (not binary)
+ * transfer so the data should already be in ASCII.
+ * That means the hex values for ASCII CR (0x0d) & LF (0x0a)
+ * must be used instead of the escape sequences \r & \n.
+ */
+ for(i = 0, si = 0; i < nread; i++, si++) {
+ if(data->req.upload_fromhere[i] == 0x0a) {
+ data->state.scratch[si++] = 0x0d;
+ data->state.scratch[si] = 0x0a;
+ if(!data->set.crlf) {
+ /* we're here only because FTP is in ASCII mode...
+ bump infilesize for the LF we just added */
+ data->state.infilesize++;
+ }
+ }
+ else
+ data->state.scratch[si] = data->req.upload_fromhere[i];
+ }
+ if(si != nread) {
+ /* only perform the special operation if we really did replace
+ anything */
+ nread = si;
+
+ /* upload from the new (replaced) buffer instead */
+ data->req.upload_fromhere = data->state.scratch;
+
+ /* set the new amount too */
+ data->req.upload_present = nread;
+ }
+ }
+ } /* if 0 == data->req.upload_present */
+ else {
+ /* We have a partial buffer left from a previous "round". Use
+ that instead of reading more data */
+ }
+
+ /* write to socket (send away data) */
+ result = Curl_write(conn,
+ conn->writesockfd, /* socket to send to */
+ data->req.upload_fromhere, /* buffer pointer */
+ data->req.upload_present, /* buffer size */
+ &bytes_written); /* actually sent */
+
+ if(result)
+ return result;
+
+ if(data->set.verbose)
+ /* show the data before we change the pointer upload_fromhere */
+ Curl_debug(data, CURLINFO_DATA_OUT, data->req.upload_fromhere,
+ (size_t)bytes_written, conn);
+
+ k->writebytecount += bytes_written;
+
+ if(k->writebytecount == data->state.infilesize) {
+ /* we have sent all data we were supposed to */
+ k->upload_done = TRUE;
+ infof(data, "We are completely uploaded and fine\n");
+ }
+
+ if(data->req.upload_present != bytes_written) {
+ /* we only wrote a part of the buffer (if anything), deal with it! */
+
+ /* store the amount of bytes left in the buffer to write */
+ data->req.upload_present -= bytes_written;
+
+ /* advance the pointer where to find the buffer when the next send
+ is to happen */
+ data->req.upload_fromhere += bytes_written;
+ }
+ else {
+ /* we've uploaded that buffer now */
+ data->req.upload_fromhere = k->uploadbuf;
+ data->req.upload_present = 0; /* no more bytes left */
+
+ if(k->upload_done) {
+ /* switch off writing, we're done! */
+ k->keepon &= ~KEEP_SEND; /* we're done writing */
+ }
+ }
+
+ Curl_pgrsSetUploadCounter(data, k->writebytecount);
+
+ } WHILE_FALSE; /* just to break out from! */
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_readwrite() is the low-level function to be called when data is to
+ * be read and written to/from the connection.
+ */
+CURLcode Curl_readwrite(struct connectdata *conn,
+ bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ struct SingleRequest *k = &data->req;
+ CURLcode result;
+ int didwhat=0;
+
+ curl_socket_t fd_read;
+ curl_socket_t fd_write;
+ int select_res = conn->cselect_bits;
+
+ conn->cselect_bits = 0;
+
+ /* only use the proper socket if the *_HOLD bit is not set simultaneously as
+ then we are in rate limiting state in that transfer direction */
+
+ if((k->keepon & KEEP_RECVBITS) == KEEP_RECV)
+ fd_read = conn->sockfd;
+ else
+ fd_read = CURL_SOCKET_BAD;
+
+ if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
+ fd_write = conn->writesockfd;
+ else
+ fd_write = CURL_SOCKET_BAD;
+
+ if(!select_res) /* Call for select()/poll() only, if read/write/error
+ status is not known. */
+ select_res = Curl_socket_ready(fd_read, fd_write, 0);
+
+ if(select_res == CURL_CSELECT_ERR) {
+ failf(data, "select/poll returned error");
+ return CURLE_SEND_ERROR;
+ }
+
+ /* We go ahead and do a read if we have a readable socket or if
+ the stream was rewound (in which case we have data in a
+ buffer) */
+ if((k->keepon & KEEP_RECV) &&
+ ((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
+
+ result = readwrite_data(data, conn, k, &didwhat, done);
+ if(result || *done)
+ return result;
+ }
+
+ /* If we still have writing to do, we check if we have a writable socket. */
+ if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
+ /* write */
+
+ result = readwrite_upload(data, conn, k, &didwhat);
+ if(result)
+ return result;
+ }
+
+ k->now = Curl_tvnow();
+ if(didwhat) {
+ /* Update read/write counters */
+ if(k->bytecountp)
+ *k->bytecountp = k->bytecount; /* read count */
+ if(k->writebytecountp)
+ *k->writebytecountp = k->writebytecount; /* write count */
+ }
+ else {
+ /* no read no write, this is a timeout? */
+ if(k->exp100 == EXP100_AWAITING_CONTINUE) {
+ /* This should allow some time for the header to arrive, but only a
+ very short time as otherwise it'll be too much wasted time too
+ often. */
+
+ /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status":
+
+ Therefore, when a client sends this header field to an origin server
+ (possibly via a proxy) from which it has never seen a 100 (Continue)
+ status, the client SHOULD NOT wait for an indefinite period before
+ sending the request body.
+
+ */
+
+ long ms = Curl_tvdiff(k->now, k->start100);
+ if(ms >= data->set.expect_100_timeout) {
+ /* we've waited long enough, continue anyway */
+ k->exp100 = EXP100_SEND_DATA;
+ k->keepon |= KEEP_SEND;
+ infof(data, "Done waiting for 100-continue\n");
+ }
+ }
+ }
+
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+ else
+ result = Curl_speedcheck(data, k->now);
+ if(result)
+ return result;
+
+ if(k->keepon) {
+ if(0 > Curl_timeleft(data, &k->now, FALSE)) {
+ if(k->size != -1) {
+ failf(data, "Operation timed out after %ld milliseconds with %"
+ CURL_FORMAT_CURL_OFF_T " out of %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount,
+ k->size);
+ }
+ else {
+ failf(data, "Operation timed out after %ld milliseconds with %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount);
+ }
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ else {
+ /*
+ * The transfer has been performed. Just make some general checks before
+ * returning.
+ */
+
+ if(!(data->set.opt_no_body) && (k->size != -1) &&
+ (k->bytecount != k->size) &&
+#ifdef CURL_DO_LINEEND_CONV
+ /* Most FTP servers don't adjust their file SIZE response for CRLFs,
+ so we'll check to see if the discrepancy can be explained
+ by the number of CRLFs we've changed to LFs.
+ */
+ (k->bytecount != (k->size + data->state.crlf_conversions)) &&
+#endif /* CURL_DO_LINEEND_CONV */
+ !data->req.newurl) {
+ failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
+ " bytes remaining to read",
+ k->size - k->bytecount);
+ return CURLE_PARTIAL_FILE;
+ }
+ else if(!(data->set.opt_no_body) &&
+ k->chunk &&
+ (conn->chunk.state != CHUNK_STOP)) {
+ /*
+ * In chunked mode, return an error if the connection is closed prior to
+ * the empty (terminating) chunk is read.
+ *
+ * The condition above used to check for
+ * conn->proto.http->chunk.datasize != 0 which is true after reading
+ * *any* chunk, not just the empty chunk.
+ *
+ */
+ failf(data, "transfer closed with outstanding read data remaining");
+ return CURLE_PARTIAL_FILE;
+ }
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ }
+
+ /* Now update the "done" boolean we return */
+ *done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND|
+ KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE;
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_single_getsock() gets called by the multi interface code when the app
+ * has requested to get the sockets for the current connection. This function
+ * will then be called once for every connection that the multi interface
+ * keeps track of. This function will only be called for connections that are
+ * in the proper state to have this information available.
+ */
+int Curl_single_getsock(const struct connectdata *conn,
+ curl_socket_t *sock, /* points to numsocks number
+ of sockets */
+ int numsocks)
+{
+ const struct SessionHandle *data = conn->data;
+ int bitmap = GETSOCK_BLANK;
+ unsigned sockindex = 0;
+
+ if(conn->handler->perform_getsock)
+ return conn->handler->perform_getsock(conn, sock, numsocks);
+
+ if(numsocks < 2)
+ /* simple check but we might need two slots */
+ return GETSOCK_BLANK;
+
+ /* don't include HOLD and PAUSE connections */
+ if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {
+
+ DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
+
+ bitmap |= GETSOCK_READSOCK(sockindex);
+ sock[sockindex] = conn->sockfd;
+ }
+
+ /* don't include HOLD and PAUSE connections */
+ if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
+
+ if((conn->sockfd != conn->writesockfd) ||
+ !(data->req.keepon & KEEP_RECV)) {
+ /* only if they are not the same socket or we didn't have a readable
+ one, we increase index */
+ if(data->req.keepon & KEEP_RECV)
+ sockindex++; /* increase index if we need two entries */
+
+ DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
+
+ sock[sockindex] = conn->writesockfd;
+ }
+
+ bitmap |= GETSOCK_WRITESOCK(sockindex);
+ }
+
+ return bitmap;
+}
+
+/*
+ * Determine optimum sleep time based on configured rate, current rate,
+ * and packet size.
+ * Returns value in milliseconds.
+ *
+ * The basic idea is to adjust the desired rate up/down in this method
+ * based on whether we are running too slow or too fast. Then, calculate
+ * how many milliseconds to wait for the next packet to achieve this new
+ * rate.
+ */
+long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
+ int pkt_size)
+{
+ curl_off_t min_sleep = 0;
+ curl_off_t rv = 0;
+
+ if(rate_bps == 0)
+ return 0;
+
+ /* If running faster than about .1% of the desired speed, slow
+ * us down a bit. Use shift instead of division as the 0.1%
+ * cutoff is arbitrary anyway.
+ */
+ if(cur_rate_bps > (rate_bps + (rate_bps >> 10))) {
+ /* running too fast, decrease target rate by 1/64th of rate */
+ rate_bps -= rate_bps >> 6;
+ min_sleep = 1;
+ }
+ else if(cur_rate_bps < (rate_bps - (rate_bps >> 10))) {
+ /* running too slow, increase target rate by 1/64th of rate */
+ rate_bps += rate_bps >> 6;
+ }
+
+ /* Determine number of milliseconds to wait until we do
+ * the next packet at the adjusted rate. We should wait
+ * longer when using larger packets, for instance.
+ */
+ rv = ((curl_off_t)((pkt_size * 8) * 1000) / rate_bps);
+
+ /* Catch rounding errors and always slow down at least 1ms if
+ * we are running too fast.
+ */
+ if(rv < min_sleep)
+ rv = min_sleep;
+
+ /* Bound value to fit in 'long' on 32-bit platform. That's
+ * plenty long enough anyway!
+ */
+ if(rv > 0x7fffffff)
+ rv = 0x7fffffff;
+
+ return (long)rv;
+}
+
+/*
+ * Curl_pretransfer() is called immediately before a transfer starts.
+ */
+CURLcode Curl_pretransfer(struct SessionHandle *data)
+{
+ CURLcode res;
+ if(!data->change.url) {
+ /* we can't do anything without URL */
+ failf(data, "No URL set!");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ /* Init the SSL session ID cache here. We do it here since we want to do it
+ after the *_setopt() calls (that could specify the size of the cache) but
+ before any transfer takes place. */
+ res = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions);
+ if(res)
+ return res;
+
+ data->set.followlocation=0; /* reset the location-follow counter */
+ data->state.this_is_a_follow = FALSE; /* reset this */
+ data->state.errorbuf = FALSE; /* no error has occurred */
+ data->state.httpversion = 0; /* don't assume any particular server version */
+
+ data->state.ssl_connect_retry = FALSE;
+
+ data->state.authproblem = FALSE;
+ data->state.authhost.want = data->set.httpauth;
+ data->state.authproxy.want = data->set.proxyauth;
+ Curl_safefree(data->info.wouldredirect);
+ data->info.wouldredirect = NULL;
+
+ /* If there is a list of cookie files to read, do it now! */
+ if(data->change.cookielist)
+ Curl_cookie_loadfiles(data);
+
+ /* If there is a list of host pairs to deal with */
+ if(data->change.resolve)
+ res = Curl_loadhostpairs(data);
+
+ if(!res) {
+ /* Allow data->set.use_port to set which port to use. This needs to be
+ * disabled for example when we follow Location: headers to URLs using
+ * different ports! */
+ data->state.allow_port = TRUE;
+
+#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
+ /*************************************************************
+ * Tell signal handler to ignore SIGPIPE
+ *************************************************************/
+ if(!data->set.no_signal)
+ data->state.prev_signal = signal(SIGPIPE, SIG_IGN);
+#endif
+
+ Curl_initinfo(data); /* reset session-specific information "variables" */
+ Curl_pgrsStartNow(data);
+
+ if(data->set.timeout)
+ Curl_expire(data, data->set.timeout);
+
+ if(data->set.connecttimeout)
+ Curl_expire(data, data->set.connecttimeout);
+
+ /* In case the handle is re-used and an authentication method was picked
+ in the session we need to make sure we only use the one(s) we now
+ consider to be fine */
+ data->state.authhost.picked &= data->state.authhost.want;
+ data->state.authproxy.picked &= data->state.authproxy.want;
+ }
+
+ return res;
+}
+
+/*
+ * Curl_posttransfer() is called immediately after a transfer ends
+ */
+CURLcode Curl_posttransfer(struct SessionHandle *data)
+{
+#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
+ /* restore the signal handler for SIGPIPE before we get back */
+ if(!data->set.no_signal)
+ signal(SIGPIPE, data->state.prev_signal);
+#else
+ (void)data; /* unused parameter */
+#endif
+
+ return CURLE_OK;
+}
+
+#ifndef CURL_DISABLE_HTTP
+/*
+ * strlen_url() returns the length of the given URL if the spaces within the
+ * URL were properly URL encoded.
+ */
+static size_t strlen_url(const char *url)
+{
+ const char *ptr;
+ size_t newlen=0;
+ bool left=TRUE; /* left side of the ? */
+
+ for(ptr=url; *ptr; ptr++) {
+ switch(*ptr) {
+ case '?':
+ left=FALSE;
+ /* fall through */
+ default:
+ newlen++;
+ break;
+ case ' ':
+ if(left)
+ newlen+=3;
+ else
+ newlen++;
+ break;
+ }
+ }
+ return newlen;
+}
+
+/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
+ * the source URL accordingly.
+ */
+static void strcpy_url(char *output, const char *url)
+{
+ /* we must add this with whitespace-replacing */
+ bool left=TRUE;
+ const char *iptr;
+ char *optr = output;
+ for(iptr = url; /* read from here */
+ *iptr; /* until zero byte */
+ iptr++) {
+ switch(*iptr) {
+ case '?':
+ left=FALSE;
+ /* fall through */
+ default:
+ *optr++=*iptr;
+ break;
+ case ' ':
+ if(left) {
+ *optr++='%'; /* add a '%' */
+ *optr++='2'; /* add a '2' */
+ *optr++='0'; /* add a '0' */
+ }
+ else
+ *optr++='+'; /* add a '+' here */
+ break;
+ }
+ }
+ *optr=0; /* zero terminate output buffer */
+
+}
+
+/*
+ * Returns true if the given URL is absolute (as opposed to relative)
+ */
+static bool is_absolute_url(const char *url)
+{
+ char prot[16]; /* URL protocol string storage */
+ char letter; /* used for a silly sscanf */
+
+ return (2 == sscanf(url, "%15[^?&/:]://%c", prot, &letter)) ? TRUE : FALSE;
+}
+
+/*
+ * Concatenate a relative URL to a base URL making it absolute.
+ * URL-encodes any spaces.
+ * The returned pointer must be freed by the caller unless NULL
+ * (returns NULL on out of memory).
+ */
+static char *concat_url(const char *base, const char *relurl)
+{
+ /***
+ TRY to append this new path to the old URL
+ to the right of the host part. Oh crap, this is doomed to cause
+ problems in the future...
+ */
+ char *newest;
+ char *protsep;
+ char *pathsep;
+ size_t newlen;
+
+ const char *useurl = relurl;
+ size_t urllen;
+
+ /* we must make our own copy of the URL to play with, as it may
+ point to read-only data */
+ char *url_clone=strdup(base);
+
+ if(!url_clone)
+ return NULL; /* skip out of this NOW */
+
+ /* protsep points to the start of the host name */
+ protsep=strstr(url_clone, "//");
+ if(!protsep)
+ protsep=url_clone;
+ else
+ protsep+=2; /* pass the slashes */
+
+ if('/' != relurl[0]) {
+ int level=0;
+
+ /* First we need to find out if there's a ?-letter in the URL,
+ and cut it and the right-side of that off */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep=0;
+
+ /* we have a relative path to append to the last slash if there's one
+ available, or if the new URL is just a query string (starts with a
+ '?') we append the new one at the end of the entire currently worked
+ out URL */
+ if(useurl[0] != '?') {
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ *pathsep=0;
+ }
+
+ /* Check if there's any slash after the host name, and if so, remember
+ that position instead */
+ pathsep = strchr(protsep, '/');
+ if(pathsep)
+ protsep = pathsep+1;
+ else
+ protsep = NULL;
+
+ /* now deal with one "./" or any amount of "../" in the newurl
+ and act accordingly */
+
+ if((useurl[0] == '.') && (useurl[1] == '/'))
+ useurl+=2; /* just skip the "./" */
+
+ while((useurl[0] == '.') &&
+ (useurl[1] == '.') &&
+ (useurl[2] == '/')) {
+ level++;
+ useurl+=3; /* pass the "../" */
+ }
+
+ if(protsep) {
+ while(level--) {
+ /* cut off one more level from the right of the original URL */
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ *pathsep=0;
+ else {
+ *protsep=0;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ /* We got a new absolute path for this server */
+
+ if((relurl[0] == '/') && (relurl[1] == '/')) {
+ /* the new URL starts with //, just keep the protocol part from the
+ original one */
+ *protsep=0;
+ useurl = &relurl[2]; /* we keep the slashes from the original, so we
+ skip the new ones */
+ }
+ else {
+ /* cut off the original URL from the first slash, or deal with URLs
+ without slash */
+ pathsep = strchr(protsep, '/');
+ if(pathsep) {
+ /* When people use badly formatted URLs, such as
+ "http://www.url.com?dir=/home/daniel" we must not use the first
+ slash, if there's a ?-letter before it! */
+ char *sep = strchr(protsep, '?');
+ if(sep && (sep < pathsep))
+ pathsep = sep;
+ *pathsep=0;
+ }
+ else {
+ /* There was no slash. Now, since we might be operating on a badly
+ formatted URL, such as "http://www.url.com?id=2380" which doesn't
+ use a slash separator as it is supposed to, we need to check for a
+ ?-letter as well! */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep=0;
+ }
+ }
+ }
+
+ /* If the new part contains a space, this is a mighty stupid redirect
+ but we still make an effort to do "right". To the left of a '?'
+ letter we replace each space with %20 while it is replaced with '+'
+ on the right side of the '?' letter.
+ */
+ newlen = strlen_url(useurl);
+
+ urllen = strlen(url_clone);
+
+ newest = malloc(urllen + 1 + /* possible slash */
+ newlen + 1 /* zero byte */);
+
+ if(!newest) {
+ free(url_clone); /* don't leak this */
+ return NULL;
+ }
+
+ /* copy over the root url part */
+ memcpy(newest, url_clone, urllen);
+
+ /* check if we need to append a slash */
+ if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
+ ;
+ else
+ newest[urllen++]='/';
+
+ /* then append the new piece on the right side */
+ strcpy_url(&newest[urllen], useurl);
+
+ free(url_clone);
+
+ return newest;
+}
+#endif /* CURL_DISABLE_HTTP */
+
+/*
+ * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
+ * as given by the remote server and set up the new URL to request.
+ */
+CURLcode Curl_follow(struct SessionHandle *data,
+ char *newurl, /* this 'newurl' is the Location: string,
+ and it must be malloc()ed before passed
+ here */
+ followtype type) /* see transfer.h */
+{
+#ifdef CURL_DISABLE_HTTP
+ (void)data;
+ (void)newurl;
+ (void)type;
+ /* Location: following will not happen when HTTP is disabled */
+ return CURLE_TOO_MANY_REDIRECTS;
+#else
+
+ /* Location: redirect */
+ bool disallowport = FALSE;
+
+ if(type == FOLLOW_REDIR) {
+ if((data->set.maxredirs != -1) &&
+ (data->set.followlocation >= data->set.maxredirs)) {
+ failf(data,"Maximum (%ld) redirects followed", data->set.maxredirs);
+ return CURLE_TOO_MANY_REDIRECTS;
+ }
+
+ /* mark the next request as a followed location: */
+ data->state.this_is_a_follow = TRUE;
+
+ data->set.followlocation++; /* count location-followers */
+
+ if(data->set.http_auto_referer) {
+ /* We are asked to automatically set the previous URL as the referer
+ when we get the next URL. We pick the ->url field, which may or may
+ not be 100% correct */
+
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+
+ data->change.referer = strdup(data->change.url);
+ if(!data->change.referer)
+ return CURLE_OUT_OF_MEMORY;
+ data->change.referer_alloc = TRUE; /* yes, free this later */
+ }
+ }
+
+ if(!is_absolute_url(newurl)) {
+ /***
+ *DANG* this is an RFC 2068 violation. The URL is supposed
+ to be absolute and this doesn't seem to be that!
+ */
+ char *absolute = concat_url(data->change.url, newurl);
+ if(!absolute)
+ return CURLE_OUT_OF_MEMORY;
+ free(newurl);
+ newurl = absolute;
+ }
+ else {
+ /* This is an absolute URL, don't allow the custom port number */
+ disallowport = TRUE;
+
+ if(strchr(newurl, ' ')) {
+ /* This new URL contains at least one space, this is a mighty stupid
+ redirect but we still make an effort to do "right". */
+ char *newest;
+ size_t newlen = strlen_url(newurl);
+
+ newest = malloc(newlen+1); /* get memory for this */
+ if(!newest)
+ return CURLE_OUT_OF_MEMORY;
+ strcpy_url(newest, newurl); /* create a space-free URL */
+
+ free(newurl); /* that was no good */
+ newurl = newest; /* use this instead now */
+ }
+
+ }
+
+ if(type == FOLLOW_FAKE) {
+ /* we're only figuring out the new url if we would've followed locations
+ but now we're done so we can get out! */
+ data->info.wouldredirect = newurl;
+ return CURLE_OK;
+ }
+
+ if(disallowport)
+ data->state.allow_port = FALSE;
+
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
+ data->change.url = newurl;
+ data->change.url_alloc = TRUE;
+ newurl = NULL; /* don't free! */
+
+ infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
+
+ /*
+ * We get here when the HTTP code is 300-399 (and 401). We need to perform
+ * differently based on exactly what return code there was.
+ *
+ * News from 7.10.6: we can also get here on a 401 or 407, in case we act on
+ * a HTTP (proxy-) authentication scheme other than Basic.
+ */
+ switch(data->info.httpcode) {
+ /* 401 - Act on a WWW-Authenticate, we keep on moving and do the
+ Authorization: XXXX header in the HTTP request code snippet */
+ /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the
+ Proxy-Authorization: XXXX header in the HTTP request code snippet */
+ /* 300 - Multiple Choices */
+ /* 306 - Not used */
+ /* 307 - Temporary Redirect */
+ default: /* for all above (and the unknown ones) */
+ /* Some codes are explicitly mentioned since I've checked RFC2616 and they
+ * seem to be OK to POST to.
+ */
+ break;
+ case 301: /* Moved Permanently */
+ /* (quote from RFC7231, section 6.4.2)
+ *
+ * Note: For historical reasons, a user agent MAY change the request
+ * method from POST to GET for the subsequent request. If this
+ * behavior is undesired, the 307 (Temporary Redirect) status code
+ * can be used instead.
+ *
+ * ----
+ *
+ * Many webservers expect this, so these servers often answers to a POST
+ * request with an error page. To be sure that libcurl gets the page that
+ * most user agents would get, libcurl has to force GET.
+ *
+ * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
+ * can be overridden with CURLOPT_POSTREDIR.
+ */
+ if((data->set.httpreq == HTTPREQ_POST
+ || data->set.httpreq == HTTPREQ_POST_FORM)
+ && !(data->set.keep_post & CURL_REDIR_POST_301)) {
+ infof(data, "Switch from POST to GET\n");
+ data->set.httpreq = HTTPREQ_GET;
+ }
+ break;
+ case 302: /* Found */
+ /* (quote from RFC7231, section 6.4.3)
+ *
+ * Note: For historical reasons, a user agent MAY change the request
+ * method from POST to GET for the subsequent request. If this
+ * behavior is undesired, the 307 (Temporary Redirect) status code
+ * can be used instead.
+ *
+ * ----
+ *
+ * Many webservers expect this, so these servers often answers to a POST
+ * request with an error page. To be sure that libcurl gets the page that
+ * most user agents would get, libcurl has to force GET.
+ *
+ * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
+ * can be overridden with CURLOPT_POSTREDIR.
+ */
+ if((data->set.httpreq == HTTPREQ_POST
+ || data->set.httpreq == HTTPREQ_POST_FORM)
+ && !(data->set.keep_post & CURL_REDIR_POST_302)) {
+ infof(data, "Switch from POST to GET\n");
+ data->set.httpreq = HTTPREQ_GET;
+ }
+ break;
+
+ case 303: /* See Other */
+ /* Disable both types of POSTs, unless the user explicitely
+ asks for POST after POST */
+ if(data->set.httpreq != HTTPREQ_GET
+ && !(data->set.keep_post & CURL_REDIR_POST_303)) {
+ data->set.httpreq = HTTPREQ_GET; /* enforce GET request */
+ infof(data, "Disables POST, goes with %s\n",
+ data->set.opt_no_body?"HEAD":"GET");
+ }
+ break;
+ case 304: /* Not Modified */
+ /* 304 means we did a conditional request and it was "Not modified".
+ * We shouldn't get any Location: header in this response!
+ */
+ break;
+ case 305: /* Use Proxy */
+ /* (quote from RFC2616, section 10.3.6):
+ * "The requested resource MUST be accessed through the proxy given
+ * by the Location field. The Location field gives the URI of the
+ * proxy. The recipient is expected to repeat this single request
+ * via the proxy. 305 responses MUST only be generated by origin
+ * servers."
+ */
+ break;
+ }
+ Curl_pgrsTime(data, TIMER_REDIRECT);
+ Curl_pgrsResetTimesSizes(data);
+
+ return CURLE_OK;
+#endif /* CURL_DISABLE_HTTP */
+}
+
+CURLcode
+Curl_reconnect_request(struct connectdata **connp)
+{
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = *connp;
+ struct SessionHandle *data = conn->data;
+
+ /* This was a re-use of a connection and we got a write error in the
+ * DO-phase. Then we DISCONNECT this connection and have another attempt to
+ * CONNECT and then DO again! The retry cannot possibly find another
+ * connection to re-use, since we only keep one possible connection for
+ * each. */
+
+ infof(data, "Re-used connection seems dead, get a new one\n");
+
+ connclose(conn, "Reconnect dead connection"); /* enforce close */
+ result = Curl_done(&conn, result, FALSE); /* we are so done with this */
+
+ /* conn may no longer be a good pointer, clear it to avoid mistakes by
+ parent functions */
+ *connp = NULL;
+
+ /*
+ * According to bug report #1330310. We need to check for CURLE_SEND_ERROR
+ * here as well. I figure this could happen when the request failed on a FTP
+ * connection and thus Curl_done() itself tried to use the connection
+ * (again). Slight Lack of feedback in the report, but I don't think this
+ * extra check can do much harm.
+ */
+ if((CURLE_OK == result) || (CURLE_SEND_ERROR == result)) {
+ bool async;
+ bool protocol_done = TRUE;
+
+ /* Now, redo the connect and get a new connection */
+ result = Curl_connect(data, connp, &async, &protocol_done);
+ if(CURLE_OK == result) {
+ /* We have connected or sent away a name resolve query fine */
+
+ conn = *connp; /* setup conn to again point to something nice */
+ if(async) {
+ /* Now, if async is TRUE here, we need to wait for the name
+ to resolve */
+ result = Curl_resolver_wait_resolv(conn, NULL);
+ if(result)
+ return result;
+
+ /* Resolved, continue with the connection */
+ result = Curl_async_resolved(conn, &protocol_done);
+ if(result)
+ return result;
+ }
+ }
+ }
+
+ return result;
+}
+
+/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
+
+ NOTE: that the *url is malloc()ed. */
+CURLcode Curl_retry_request(struct connectdata *conn,
+ char **url)
+{
+ struct SessionHandle *data = conn->data;
+
+ *url = NULL;
+
+ /* if we're talking upload, we can't do the checks below, unless the protocol
+ is HTTP as when uploading over HTTP we will still get a response */
+ if(data->set.upload &&
+ !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)))
+ return CURLE_OK;
+
+ if(/* workaround for broken TLS servers */ data->state.ssl_connect_retry ||
+ ((data->req.bytecount +
+ data->req.headerbytecount == 0) &&
+ conn->bits.reuse &&
+ !data->set.opt_no_body &&
+ data->set.rtspreq != RTSPREQ_RECEIVE)) {
+ /* We got no data, we attempted to re-use a connection and yet we want a
+ "body". This might happen if the connection was left alive when we were
+ done using it before, but that was closed when we wanted to read from
+ it again. Bad luck. Retry the same request on a fresh connect! */
+ infof(conn->data, "Connection died, retrying a fresh connect\n");
+ *url = strdup(conn->data->change.url);
+ if(!*url)
+ return CURLE_OUT_OF_MEMORY;
+
+ connclose(conn, "retry"); /* close this connection */
+ conn->bits.retry = TRUE; /* mark this as a connection we're about
+ to retry. Marking it this way should
+ prevent i.e HTTP transfers to return
+ error just because nothing has been
+ transferred! */
+
+
+ if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
+ struct HTTP *http = data->req.protop;
+ if(http->writebytecount)
+ return Curl_readrewind(conn);
+ }
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Curl_setup_transfer() is called to setup some basic properties for the
+ * upcoming transfer.
+ */
+void
+Curl_setup_transfer(
+ struct connectdata *conn, /* connection data */
+ int sockindex, /* socket index to read from or -1 */
+ curl_off_t size, /* -1 if unknown at this point */
+ bool getheader, /* TRUE if header parsing is wanted */
+ curl_off_t *bytecountp, /* return number of bytes read or NULL */
+ int writesockindex, /* socket index to write to, it may very well be
+ the same we read from. -1 disables */
+ curl_off_t *writecountp /* return number of bytes written or NULL */
+ )
+{
+ struct SessionHandle *data;
+ struct SingleRequest *k;
+
+ DEBUGASSERT(conn != NULL);
+
+ data = conn->data;
+ k = &data->req;
+
+ DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
+
+ /* now copy all input parameters */
+ conn->sockfd = sockindex == -1 ?
+ CURL_SOCKET_BAD : conn->sock[sockindex];
+ conn->writesockfd = writesockindex == -1 ?
+ CURL_SOCKET_BAD:conn->sock[writesockindex];
+ k->getheader = getheader;
+
+ k->size = size;
+ k->bytecountp = bytecountp;
+ k->writebytecountp = writecountp;
+
+ /* The code sequence below is placed in this function just because all
+ necessary input is not always known in do_complete() as this function may
+ be called after that */
+
+ if(!k->getheader) {
+ k->header = FALSE;
+ if(size > 0)
+ Curl_pgrsSetDownloadSize(data, size);
+ }
+ /* we want header and/or body, if neither then don't do this! */
+ if(k->getheader || !data->set.opt_no_body) {
+
+ if(conn->sockfd != CURL_SOCKET_BAD)
+ k->keepon |= KEEP_RECV;
+
+ if(conn->writesockfd != CURL_SOCKET_BAD) {
+ struct HTTP *http = data->req.protop;
+ /* HTTP 1.1 magic:
+
+ Even if we require a 100-return code before uploading data, we might
+ need to write data before that since the REQUEST may not have been
+ finished sent off just yet.
+
+ Thus, we must check if the request has been sent before we set the
+ state info where we wait for the 100-return code
+ */
+ if((data->state.expect100header) &&
+ (conn->handler->protocol&PROTO_FAMILY_HTTP) &&
+ (http->sending == HTTPSEND_BODY)) {
+ /* wait with write until we either got 100-continue or a timeout */
+ k->exp100 = EXP100_AWAITING_CONTINUE;
+ k->start100 = Curl_tvnow();
+
+ /* Set a timeout for the multi interface. Add the inaccuracy margin so
+ that we don't fire slightly too early and get denied to run. */
+ Curl_expire(data, data->set.expect_100_timeout);
+ }
+ else {
+ if(data->state.expect100header)
+ /* when we've sent off the rest of the headers, we must await a
+ 100-continue but first finish sending the request */
+ k->exp100 = EXP100_SENDING_REQUEST;
+
+ /* enable the write bit when we're not waiting for continue */
+ k->keepon |= KEEP_SEND;
+ }
+ } /* if(conn->writesockfd != CURL_SOCKET_BAD) */
+ } /* if(k->getheader || !data->set.opt_no_body) */
+
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/transfer.h b/external/libcurl_android/jni/libcurl/lib/transfer.h
new file mode 100755
index 00000000..ad4a3acd
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/transfer.h
@@ -0,0 +1,70 @@
+#ifndef HEADER_CURL_TRANSFER_H
+#define HEADER_CURL_TRANSFER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+CURLcode Curl_pretransfer(struct SessionHandle *data);
+CURLcode Curl_second_connect(struct connectdata *conn);
+CURLcode Curl_posttransfer(struct SessionHandle *data);
+
+typedef enum {
+ FOLLOW_NONE, /* not used within the function, just a placeholder to
+ allow initing to this */
+ FOLLOW_FAKE, /* only records stuff, not actually following */
+ FOLLOW_RETRY, /* set if this is a request retry as opposed to a real
+ redirect following */
+ FOLLOW_REDIR, /* a full true redirect */
+ FOLLOW_LAST /* never used */
+} followtype;
+
+CURLcode Curl_follow(struct SessionHandle *data, char *newurl,
+ followtype type);
+
+
+CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
+int Curl_single_getsock(const struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+CURLcode Curl_readrewind(struct connectdata *conn);
+CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
+CURLcode Curl_reconnect_request(struct connectdata **connp);
+CURLcode Curl_retry_request(struct connectdata *conn, char **url);
+bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc);
+
+/* This sets up a forthcoming transfer */
+void
+Curl_setup_transfer (struct connectdata *data,
+ int sockindex, /* socket index to read from or -1 */
+ curl_off_t size, /* -1 if unknown at this point */
+ bool getheader, /* TRUE if header parsing is wanted */
+ curl_off_t *bytecountp, /* return number of bytes read */
+ int writesockindex, /* socket index to write to, it may
+ very well be the same we read from.
+ -1 disables */
+ curl_off_t *writecountp /* return number of bytes written */
+);
+
+long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
+ int pkt_size);
+
+#endif /* HEADER_CURL_TRANSFER_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/url.c b/external/libcurl_android/jni/libcurl/lib/url.c
new file mode 100755
index 00000000..67126ab3
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/url.c
@@ -0,0 +1,6032 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifndef HAVE_SOCKET
+#error "We can't compile without socket() support!"
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifdef USE_LIBIDN
+#include <idna.h>
+#include <tld.h>
+#include <stringprep.h>
+#ifdef HAVE_IDN_FREE_H
+#include <idn-free.h>
+#else
+/* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */
+void idn_free (void *ptr);
+#endif
+#ifndef HAVE_IDN_FREE
+/* if idn_free() was not found in this version of libidn use free() instead */
+#define idn_free(x) (free)(x)
+#endif
+#elif defined(USE_WIN32_IDN)
+/* prototype for curl_win32_idn_to_ascii() */
+int curl_win32_idn_to_ascii(const char *in, char **out);
+#endif /* USE_LIBIDN */
+
+#include "urldata.h"
+#include "netrc.h"
+
+#include "formdata.h"
+#include "vtls/vtls.h"
+#include "hostip.h"
+#include "transfer.h"
+#include "sendf.h"
+#include "progress.h"
+#include "cookie.h"
+#include "strequal.h"
+#include "strerror.h"
+#include "escape.h"
+#include "strtok.h"
+#include "share.h"
+#include "content_encoding.h"
+#include "http_digest.h"
+#include "http_negotiate.h"
+#include "select.h"
+#include "multiif.h"
+#include "easyif.h"
+#include "speedcheck.h"
+#include "rawstr.h"
+#include "warnless.h"
+#include "non-ascii.h"
+#include "inet_pton.h"
+
+/* And now for the protocols */
+#include "ftp.h"
+#include "dict.h"
+#include "telnet.h"
+#include "tftp.h"
+#include "http.h"
+#include "file.h"
+#include "curl_ldap.h"
+#include "ssh.h"
+#include "imap.h"
+#include "url.h"
+#include "connect.h"
+#include "inet_ntop.h"
+#include "curl_ntlm.h"
+#include "curl_ntlm_wb.h"
+#include "socks.h"
+#include "curl_rtmp.h"
+#include "gopher.h"
+#include "http_proxy.h"
+#include "bundles.h"
+#include "conncache.h"
+#include "multihandle.h"
+#include "pipeline.h"
+#include "dotdot.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Local static prototypes */
+static struct connectdata *
+find_oldest_idle_connection(struct SessionHandle *data);
+static struct connectdata *
+find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
+ struct connectbundle *bundle);
+static void conn_free(struct connectdata *conn);
+static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
+static CURLcode do_init(struct connectdata *conn);
+static CURLcode parse_url_login(struct SessionHandle *data,
+ struct connectdata *conn,
+ char **userptr, char **passwdptr,
+ char **optionsptr);
+static CURLcode parse_login_details(const char *login, const size_t len,
+ char **userptr, char **passwdptr,
+ char **optionsptr);
+/*
+ * Protocol table.
+ */
+
+static const struct Curl_handler * const protocols[] = {
+
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_http,
+#endif
+
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_https,
+#endif
+
+#ifndef CURL_DISABLE_FTP
+ &Curl_handler_ftp,
+#endif
+
+#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
+ &Curl_handler_ftps,
+#endif
+
+#ifndef CURL_DISABLE_TELNET
+ &Curl_handler_telnet,
+#endif
+
+#ifndef CURL_DISABLE_DICT
+ &Curl_handler_dict,
+#endif
+
+#ifndef CURL_DISABLE_LDAP
+ &Curl_handler_ldap,
+#if !defined(CURL_DISABLE_LDAPS) && \
+ ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+ (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+ &Curl_handler_ldaps,
+#endif
+#endif
+
+#ifndef CURL_DISABLE_FILE
+ &Curl_handler_file,
+#endif
+
+#ifndef CURL_DISABLE_TFTP
+ &Curl_handler_tftp,
+#endif
+
+#ifdef USE_LIBSSH2
+ &Curl_handler_scp,
+ &Curl_handler_sftp,
+#endif
+
+#ifndef CURL_DISABLE_IMAP
+ &Curl_handler_imap,
+#ifdef USE_SSL
+ &Curl_handler_imaps,
+#endif
+#endif
+
+#ifndef CURL_DISABLE_POP3
+ &Curl_handler_pop3,
+#ifdef USE_SSL
+ &Curl_handler_pop3s,
+#endif
+#endif
+
+#ifndef CURL_DISABLE_SMTP
+ &Curl_handler_smtp,
+#ifdef USE_SSL
+ &Curl_handler_smtps,
+#endif
+#endif
+
+#ifndef CURL_DISABLE_RTSP
+ &Curl_handler_rtsp,
+#endif
+
+#ifndef CURL_DISABLE_GOPHER
+ &Curl_handler_gopher,
+#endif
+
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmp,
+ &Curl_handler_rtmpt,
+ &Curl_handler_rtmpe,
+ &Curl_handler_rtmpte,
+ &Curl_handler_rtmps,
+ &Curl_handler_rtmpts,
+#endif
+
+ (struct Curl_handler *) NULL
+};
+
+/*
+ * Dummy handler for undefined protocol schemes.
+ */
+
+static const struct Curl_handler Curl_handler_dummy = {
+ "<no protocol>", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ ZERO_NULL, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ 0, /* defport */
+ 0, /* protocol */
+ PROTOPT_NONE /* flags */
+};
+
+void Curl_freeset(struct SessionHandle *data)
+{
+ /* Free all dynamic strings stored in the data->set substructure. */
+ enum dupstring i;
+ for(i=(enum dupstring)0; i < STRING_LAST; i++)
+ Curl_safefree(data->set.str[i]);
+
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+ data->change.referer = NULL;
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ data->change.url = NULL;
+}
+
+static CURLcode setstropt(char **charp, char *s)
+{
+ /* Release the previous storage at `charp' and replace by a dynamic storage
+ copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
+
+ Curl_safefree(*charp);
+
+ if(s) {
+ s = strdup(s);
+
+ if(!s)
+ return CURLE_OUT_OF_MEMORY;
+
+ *charp = s;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
+{
+ CURLcode result = CURLE_OK;
+ char *user = NULL;
+ char *passwd = NULL;
+
+ /* Parse the login details if specified. It not then we treat NULL as a hint
+ to clear the existing data */
+ if(option) {
+ result = parse_login_details(option, strlen(option),
+ (userp ? &user : NULL),
+ (passwdp ? &passwd : NULL),
+ NULL);
+ }
+
+ if(!result) {
+ /* Store the username part of option if required */
+ if(userp) {
+ if(!user && option && option[0] == ':') {
+ /* Allocate an empty string instead of returning NULL as user name */
+ user = strdup("");
+ if(!user)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_safefree(*userp);
+ *userp = user;
+ }
+
+ /* Store the password part of option if required */
+ if(passwdp) {
+ Curl_safefree(*passwdp);
+ *passwdp = passwd;
+ }
+ }
+
+ return result;
+}
+
+CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src)
+{
+ CURLcode r = CURLE_OK;
+ enum dupstring i;
+
+ /* Copy src->set into dst->set first, then deal with the strings
+ afterwards */
+ dst->set = src->set;
+
+ /* clear all string pointers first */
+ memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
+
+ /* duplicate all strings */
+ for(i=(enum dupstring)0; i< STRING_LAST; i++) {
+ r = setstropt(&dst->set.str[i], src->set.str[i]);
+ if(r != CURLE_OK)
+ break;
+ }
+
+ /* If a failure occurred, freeing has to be performed externally. */
+ return r;
+}
+
+/*
+ * This is the internal function curl_easy_cleanup() calls. This should
+ * cleanup and free all resources associated with this sessionhandle.
+ *
+ * NOTE: if we ever add something that attempts to write to a socket or
+ * similar here, we must ignore SIGPIPE first. It is currently only done
+ * when curl_easy_perform() is invoked.
+ */
+
+CURLcode Curl_close(struct SessionHandle *data)
+{
+ struct Curl_multi *m;
+
+ if(!data)
+ return CURLE_OK;
+
+ Curl_expire(data, 0); /* shut off timers */
+
+ m = data->multi;
+
+ if(m)
+ /* This handle is still part of a multi handle, take care of this first
+ and detach this handle from there. */
+ curl_multi_remove_handle(data->multi, data);
+
+ if(data->multi_easy)
+ /* when curl_easy_perform() is used, it creates its own multi handle to
+ use and this is the one */
+ curl_multi_cleanup(data->multi_easy);
+
+ /* Destroy the timeout list that is held in the easy handle. It is
+ /normally/ done by curl_multi_remove_handle() but this is "just in
+ case" */
+ if(data->state.timeoutlist) {
+ Curl_llist_destroy(data->state.timeoutlist, NULL);
+ data->state.timeoutlist = NULL;
+ }
+
+ data->magic = 0; /* force a clear AFTER the possibly enforced removal from
+ the multi handle, since that function uses the magic
+ field! */
+
+ if(data->state.rangestringalloc)
+ free(data->state.range);
+
+ /* Free the pathbuffer */
+ Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
+
+ /* freed here just in case DONE wasn't called */
+ Curl_free_request_state(data);
+
+ /* Close down all open SSL info and sessions */
+ Curl_ssl_close_all(data);
+ Curl_safefree(data->state.first_host);
+ Curl_safefree(data->state.scratch);
+ Curl_ssl_free_certinfo(data);
+
+ /* Cleanup possible redirect junk */
+ if(data->req.newurl) {
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+ }
+
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+ data->change.referer = NULL;
+
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ data->change.url = NULL;
+
+ Curl_safefree(data->state.headerbuff);
+
+ Curl_flush_cookies(data, 1);
+
+ Curl_digest_cleanup(data);
+
+ Curl_safefree(data->info.contenttype);
+ Curl_safefree(data->info.wouldredirect);
+
+ /* this destroys the channel and we cannot use it anymore after this */
+ Curl_resolver_cleanup(data->state.resolver);
+
+ Curl_convert_close(data);
+
+ /* No longer a dirty share, if it exists */
+ if(data->share) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+ data->share->dirty--;
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+ }
+
+ Curl_freeset(data);
+ free(data);
+ return CURLE_OK;
+}
+
+/*
+ * Initialize the UserDefined fields within a SessionHandle.
+ * This may be safely called on a new or existing SessionHandle.
+ */
+CURLcode Curl_init_userdefined(struct UserDefined *set)
+{
+ CURLcode res = CURLE_OK;
+
+ set->out = stdout; /* default output to stdout */
+ set->in = stdin; /* default input from stdin */
+ set->err = stderr; /* default stderr to stderr */
+
+ /* use fwrite as default function to store output */
+ set->fwrite_func = (curl_write_callback)fwrite;
+
+ /* use fread as default function to read input */
+ set->fread_func = (curl_read_callback)fread;
+ set->is_fread_set = 0;
+ set->is_fwrite_set = 0;
+
+ set->seek_func = ZERO_NULL;
+ set->seek_client = ZERO_NULL;
+
+ /* conversion callbacks for non-ASCII hosts */
+ set->convfromnetwork = ZERO_NULL;
+ set->convtonetwork = ZERO_NULL;
+ set->convfromutf8 = ZERO_NULL;
+
+ set->filesize = -1; /* we don't know the size */
+ set->postfieldsize = -1; /* unknown size */
+ set->maxredirs = -1; /* allow any amount by default */
+
+ set->httpreq = HTTPREQ_GET; /* Default HTTP request */
+ set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
+ set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
+ set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
+ set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
+ set->ftp_filemethod = FTPFILE_MULTICWD;
+
+ set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
+
+ /* Set the default size of the SSL session ID cache */
+ set->ssl.max_ssl_sessions = 5;
+
+ set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
+ set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
+ set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
+ set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
+
+ /* make libcurl quiet by default: */
+ set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
+
+ /*
+ * libcurl 7.10 introduced SSL verification *by default*! This needs to be
+ * switched off unless wanted.
+ */
+ set->ssl.verifypeer = TRUE;
+ set->ssl.verifyhost = TRUE;
+#ifdef USE_TLS_SRP
+ set->ssl.authtype = CURL_TLSAUTH_NONE;
+#endif
+ set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
+ type */
+ set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
+
+ set->new_file_perms = 0644; /* Default permissions */
+ set->new_directory_perms = 0755; /* Default permissions */
+
+ /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
+ define since we internally only use the lower 16 bits for the passed
+ in bitmask to not conflict with the private bits */
+ set->allowed_protocols = CURLPROTO_ALL;
+ set->redir_protocols =
+ CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ /*
+ * disallow unprotected protection negotiation NEC reference implementation
+ * seem not to follow rfc1961 section 4.3/4.4
+ */
+ set->socks5_gssapi_nec = FALSE;
+ /* set default GSS-API service name */
+ res = setstropt(&set->str[STRING_SOCKS5_GSSAPI_SERVICE],
+ (char *) CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE);
+ if(res != CURLE_OK)
+ return res;
+#endif
+
+ /* This is our preferred CA cert bundle/path since install time */
+#if defined(CURL_CA_BUNDLE)
+ res = setstropt(&set->str[STRING_SSL_CAFILE], (char *) CURL_CA_BUNDLE);
+#elif defined(CURL_CA_PATH)
+ res = setstropt(&set->str[STRING_SSL_CAPATH], (char *) CURL_CA_PATH);
+#endif
+
+ set->wildcardmatch = FALSE;
+ set->chunk_bgn = ZERO_NULL;
+ set->chunk_end = ZERO_NULL;
+
+ /* tcp keepalives are disabled by default, but provide reasonable values for
+ * the interval and idle times.
+ */
+ set->tcp_keepalive = FALSE;
+ set->tcp_keepintvl = 60;
+ set->tcp_keepidle = 60;
+
+ set->ssl_enable_npn = TRUE;
+ set->ssl_enable_alpn = TRUE;
+
+ set->expect_100_timeout = 1000L; /* Wait for a second by default. */
+ return res;
+}
+
+/**
+ * Curl_open()
+ *
+ * @param curl is a pointer to a sessionhandle pointer that gets set by this
+ * function.
+ * @return CURLcode
+ */
+
+CURLcode Curl_open(struct SessionHandle **curl)
+{
+ CURLcode res = CURLE_OK;
+ struct SessionHandle *data;
+ CURLcode status;
+
+ /* Very simple start-up: alloc the struct, init it with zeroes and return */
+ data = calloc(1, sizeof(struct SessionHandle));
+ if(!data) {
+ /* this is a very serious error */
+ DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n"));
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ data->magic = CURLEASY_MAGIC_NUMBER;
+
+ status = Curl_resolver_init(&data->state.resolver);
+ if(status) {
+ DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
+ free(data);
+ return status;
+ }
+
+ /* We do some initial setup here, all those fields that can't be just 0 */
+
+ data->state.headerbuff = malloc(HEADERSIZE);
+ if(!data->state.headerbuff) {
+ DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
+ res = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ res = Curl_init_userdefined(&data->set);
+
+ data->state.headersize=HEADERSIZE;
+
+ Curl_convert_init(data);
+
+ /* most recent connection is not yet defined */
+ data->state.lastconnect = NULL;
+
+ data->progress.flags |= PGRS_HIDE;
+ data->state.current_speed = -1; /* init to negative == impossible */
+
+ data->wildcard.state = CURLWC_INIT;
+ data->wildcard.filelist = NULL;
+ data->set.fnmatch = ZERO_NULL;
+ data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
+ }
+
+ if(res) {
+ Curl_resolver_cleanup(data->state.resolver);
+ if(data->state.headerbuff)
+ free(data->state.headerbuff);
+ Curl_freeset(data);
+ free(data);
+ data = NULL;
+ }
+ else
+ *curl = data;
+
+ return res;
+}
+
+CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
+ va_list param)
+{
+ char *argptr;
+ CURLcode result = CURLE_OK;
+ long arg;
+#ifndef CURL_DISABLE_HTTP
+ curl_off_t bigsize;
+#endif
+
+ switch(option) {
+ case CURLOPT_DNS_CACHE_TIMEOUT:
+ data->set.dns_cache_timeout = va_arg(param, long);
+ break;
+ case CURLOPT_DNS_USE_GLOBAL_CACHE:
+ /* remember we want this enabled */
+ arg = va_arg(param, long);
+ data->set.global_dns_cache = (0 != arg)?TRUE:FALSE;
+ break;
+ case CURLOPT_SSL_CIPHER_LIST:
+ /* set a list of cipher we want to use in the SSL connection */
+ result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RANDOM_FILE:
+ /*
+ * This is the path name to a file that contains random data to seed
+ * the random SSL stuff with. The file is only used for reading.
+ */
+ result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_EGDSOCKET:
+ /*
+ * The Entropy Gathering Daemon socket pathname
+ */
+ result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_MAXCONNECTS:
+ /*
+ * Set the absolute number of maximum simultaneous alive connection that
+ * libcurl is allowed to have.
+ */
+ data->set.maxconnects = va_arg(param, long);
+ break;
+ case CURLOPT_FORBID_REUSE:
+ /*
+ * When this transfer is done, it must not be left to be reused by a
+ * subsequent transfer but shall be closed immediately.
+ */
+ data->set.reuse_forbid = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_FRESH_CONNECT:
+ /*
+ * This transfer shall not use a previously cached connection but
+ * should be made with a fresh new connect!
+ */
+ data->set.reuse_fresh = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_VERBOSE:
+ /*
+ * Verbose means infof() calls that give a lot of information about
+ * the connection and transfer procedures as well as internal choices.
+ */
+ data->set.verbose = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_HEADER:
+ /*
+ * Set to include the header in the general data output stream.
+ */
+ data->set.include_header = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_NOPROGRESS:
+ /*
+ * Shut off the internal supported progress meter
+ */
+ data->set.hide_progress = (0 != va_arg(param, long))?TRUE:FALSE;
+ if(data->set.hide_progress)
+ data->progress.flags |= PGRS_HIDE;
+ else
+ data->progress.flags &= ~PGRS_HIDE;
+ break;
+ case CURLOPT_NOBODY:
+ /*
+ * Do not include the body part in the output data stream.
+ */
+ data->set.opt_no_body = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_FAILONERROR:
+ /*
+ * Don't output the >=300 error code HTML-page, but instead only
+ * return error.
+ */
+ data->set.http_fail_on_error = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_UPLOAD:
+ case CURLOPT_PUT:
+ /*
+ * We want to sent data to the remote host. If this is HTTP, that equals
+ * using the PUT request.
+ */
+ data->set.upload = (0 != va_arg(param, long))?TRUE:FALSE;
+ if(data->set.upload) {
+ /* If this is HTTP, PUT is what's needed to "upload" */
+ data->set.httpreq = HTTPREQ_PUT;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ else
+ /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
+ then this can be changed to HEAD later on) */
+ data->set.httpreq = HTTPREQ_GET;
+ break;
+ case CURLOPT_FILETIME:
+ /*
+ * Try to get the file time of the remote document. The time will
+ * later (possibly) become available using curl_easy_getinfo().
+ */
+ data->set.get_filetime = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_FTP_CREATE_MISSING_DIRS:
+ /*
+ * An FTP option that modifies an upload to create missing directories on
+ * the server.
+ */
+ switch(va_arg(param, long)) {
+ case 0:
+ data->set.ftp_create_missing_dirs = 0;
+ break;
+ case 1:
+ data->set.ftp_create_missing_dirs = 1;
+ break;
+ case 2:
+ data->set.ftp_create_missing_dirs = 2;
+ break;
+ default:
+ /* reserve other values for future use */
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
+ break;
+ case CURLOPT_SERVER_RESPONSE_TIMEOUT:
+ /*
+ * Option that specifies how quickly an server response must be obtained
+ * before it is considered failure. For pingpong protocols.
+ */
+ data->set.server_response_timeout = va_arg( param , long ) * 1000;
+ break;
+ case CURLOPT_TFTP_BLKSIZE:
+ /*
+ * TFTP option that specifies the block size to use for data transmission
+ */
+ data->set.tftp_blksize = va_arg(param, long);
+ break;
+ case CURLOPT_DIRLISTONLY:
+ /*
+ * An option that changes the command to one that asks for a list
+ * only, no file info details.
+ */
+ data->set.ftp_list_only = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_APPEND:
+ /*
+ * We want to upload and append to an existing file.
+ */
+ data->set.ftp_append = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_FTP_FILEMETHOD:
+ /*
+ * How do access files over FTP.
+ */
+ data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
+ break;
+ case CURLOPT_NETRC:
+ /*
+ * Parse the $HOME/.netrc file
+ */
+ data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
+ break;
+ case CURLOPT_NETRC_FILE:
+ /*
+ * Use this file instead of the $HOME/.netrc file
+ */
+ result = setstropt(&data->set.str[STRING_NETRC_FILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_TRANSFERTEXT:
+ /*
+ * This option was previously named 'FTPASCII'. Renamed to work with
+ * more protocols than merely FTP.
+ *
+ * Transfer using ASCII (instead of BINARY).
+ */
+ data->set.prefer_ascii = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_TIMECONDITION:
+ /*
+ * Set HTTP time condition. This must be one of the defines in the
+ * curl/curl.h header file.
+ */
+ data->set.timecondition = (curl_TimeCond)va_arg(param, long);
+ break;
+ case CURLOPT_TIMEVALUE:
+ /*
+ * This is the value to compare with the remote document with the
+ * method set with CURLOPT_TIMECONDITION
+ */
+ data->set.timevalue = (time_t)va_arg(param, long);
+ break;
+ case CURLOPT_SSLVERSION:
+ /*
+ * Set explicit SSL version to try to connect with, as some SSL
+ * implementations are lame.
+ */
+ data->set.ssl.version = va_arg(param, long);
+ break;
+
+#ifndef CURL_DISABLE_HTTP
+ case CURLOPT_AUTOREFERER:
+ /*
+ * Switch on automatic referer that gets set if curl follows locations.
+ */
+ data->set.http_auto_referer = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_ACCEPT_ENCODING:
+ /*
+ * String to use at the value of Accept-Encoding header.
+ *
+ * If the encoding is set to "" we use an Accept-Encoding header that
+ * encompasses all the encodings we support.
+ * If the encoding is set to NULL we don't send an Accept-Encoding header
+ * and ignore an received Content-Encoding header.
+ *
+ */
+ argptr = va_arg(param, char *);
+ result = setstropt(&data->set.str[STRING_ENCODING],
+ (argptr && !*argptr)?
+ (char *) ALL_CONTENT_ENCODINGS: argptr);
+ break;
+
+ case CURLOPT_TRANSFER_ENCODING:
+ data->set.http_transfer_encoding = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FOLLOWLOCATION:
+ /*
+ * Follow Location: header hints on a HTTP-server.
+ */
+ data->set.http_follow_location = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_UNRESTRICTED_AUTH:
+ /*
+ * Send authentication (user+password) when following locations, even when
+ * hostname changed.
+ */
+ data->set.http_disable_hostname_check_before_authentication =
+ (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_MAXREDIRS:
+ /*
+ * The maximum amount of hops you allow curl to follow Location:
+ * headers. This should mostly be used to detect never-ending loops.
+ */
+ data->set.maxredirs = va_arg(param, long);
+ break;
+
+ case CURLOPT_POSTREDIR:
+ {
+ /*
+ * Set the behaviour of POST when redirecting
+ * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
+ * CURL_REDIR_POST_301 - POST is kept as POST after 301
+ * CURL_REDIR_POST_302 - POST is kept as POST after 302
+ * CURL_REDIR_POST_303 - POST is kept as POST after 303
+ * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
+ * other - POST is kept as POST after 301 and 302
+ */
+ int postRedir = curlx_sltosi(va_arg(param, long));
+ data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
+ }
+ break;
+
+ case CURLOPT_POST:
+ /* Does this option serve a purpose anymore? Yes it does, when
+ CURLOPT_POSTFIELDS isn't used and the POST data is read off the
+ callback! */
+ if(va_arg(param, long)) {
+ data->set.httpreq = HTTPREQ_POST;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ else
+ data->set.httpreq = HTTPREQ_GET;
+ break;
+
+ case CURLOPT_COPYPOSTFIELDS:
+ /*
+ * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
+ * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
+ * CURLOPT_COPYPOSTFIELDS and not altered later.
+ */
+ argptr = va_arg(param, char *);
+
+ if(!argptr || data->set.postfieldsize == -1)
+ result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
+ else {
+ /*
+ * Check that requested length does not overflow the size_t type.
+ */
+
+ if((data->set.postfieldsize < 0) ||
+ ((sizeof(curl_off_t) != sizeof(size_t)) &&
+ (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ char * p;
+
+ (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+
+ /* Allocate even when size == 0. This satisfies the need of possible
+ later address compare to detect the COPYPOSTFIELDS mode, and
+ to mark that postfields is used rather than read function or
+ form data.
+ */
+ p = malloc((size_t)(data->set.postfieldsize?
+ data->set.postfieldsize:1));
+
+ if(!p)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ if(data->set.postfieldsize)
+ memcpy(p, argptr, (size_t)data->set.postfieldsize);
+
+ data->set.str[STRING_COPYPOSTFIELDS] = p;
+ }
+ }
+ }
+
+ data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
+ data->set.httpreq = HTTPREQ_POST;
+ break;
+
+ case CURLOPT_POSTFIELDS:
+ /*
+ * Like above, but use static data instead of copying it.
+ */
+ data->set.postfields = va_arg(param, void *);
+ /* Release old copied data. */
+ (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.httpreq = HTTPREQ_POST;
+ break;
+
+ case CURLOPT_POSTFIELDSIZE:
+ /*
+ * The size of the POSTFIELD data to prevent libcurl to do strlen() to
+ * figure it out. Enables binary posts.
+ */
+ bigsize = va_arg(param, long);
+
+ if(data->set.postfieldsize < bigsize &&
+ data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+ /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+ (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.postfields = NULL;
+ }
+
+ data->set.postfieldsize = bigsize;
+ break;
+
+ case CURLOPT_POSTFIELDSIZE_LARGE:
+ /*
+ * The size of the POSTFIELD data to prevent libcurl to do strlen() to
+ * figure it out. Enables binary posts.
+ */
+ bigsize = va_arg(param, curl_off_t);
+
+ if(data->set.postfieldsize < bigsize &&
+ data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+ /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+ (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+ data->set.postfields = NULL;
+ }
+
+ data->set.postfieldsize = bigsize;
+ break;
+
+ case CURLOPT_HTTPPOST:
+ /*
+ * Set to make us do HTTP POST
+ */
+ data->set.httppost = va_arg(param, struct curl_httppost *);
+ data->set.httpreq = HTTPREQ_POST_FORM;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ break;
+
+ case CURLOPT_REFERER:
+ /*
+ * String to set in the HTTP Referer: field.
+ */
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
+ result = setstropt(&data->set.str[STRING_SET_REFERER],
+ va_arg(param, char *));
+ data->change.referer = data->set.str[STRING_SET_REFERER];
+ break;
+
+ case CURLOPT_USERAGENT:
+ /*
+ * String to use in the HTTP User-Agent field
+ */
+ result = setstropt(&data->set.str[STRING_USERAGENT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_HTTPHEADER:
+ /*
+ * Set a list with HTTP headers to use (or replace internals with)
+ */
+ data->set.headers = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_PROXYHEADER:
+ /*
+ * Set a list with proxy headers to use (or replace internals with)
+ *
+ * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
+ * long time we remain doing it this way until CURLOPT_PROXYHEADER is
+ * used. As soon as this option has been used, if set to anything but
+ * NULL, custom headers for proxies are only picked from this list.
+ *
+ * Set this option to NULL to restore the previous behavior.
+ */
+ data->set.proxyheaders = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_HEADEROPT:
+ /*
+ * Set header option.
+ */
+ arg = va_arg(param, long);
+ data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
+ break;
+
+ case CURLOPT_HTTP200ALIASES:
+ /*
+ * Set a list of aliases for HTTP 200 in response header
+ */
+ data->set.http200aliases = va_arg(param, struct curl_slist *);
+ break;
+
+#if !defined(CURL_DISABLE_COOKIES)
+ case CURLOPT_COOKIE:
+ /*
+ * Cookie string to send to the remote server in the request.
+ */
+ result = setstropt(&data->set.str[STRING_COOKIE],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_COOKIEFILE:
+ /*
+ * Set cookie file to read and parse. Can be used multiple times.
+ */
+ argptr = (char *)va_arg(param, void *);
+ if(argptr) {
+ struct curl_slist *cl;
+ /* append the cookie file name to the list of file names, and deal with
+ them later */
+ cl = curl_slist_append(data->change.cookielist, argptr);
+ if(!cl) {
+ curl_slist_free_all(data->change.cookielist);
+ data->change.cookielist = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->change.cookielist = cl; /* store the list for later use */
+ }
+ break;
+
+ case CURLOPT_COOKIEJAR:
+ /*
+ * Set cookie file name to dump all cookies to when we're done.
+ */
+ result = setstropt(&data->set.str[STRING_COOKIEJAR],
+ va_arg(param, char *));
+
+ /*
+ * Activate the cookie parser. This may or may not already
+ * have been made.
+ */
+ data->cookies = Curl_cookie_init(data, NULL, data->cookies,
+ data->set.cookiesession);
+ break;
+
+ case CURLOPT_COOKIESESSION:
+ /*
+ * Set this option to TRUE to start a new "cookie session". It will
+ * prevent the forthcoming read-cookies-from-file actions to accept
+ * cookies that are marked as being session cookies, as they belong to a
+ * previous session.
+ *
+ * In the original Netscape cookie spec, "session cookies" are cookies
+ * with no expire date set. RFC2109 describes the same action if no
+ * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
+ * a 'Discard' action that can enforce the discard even for cookies that
+ * have a Max-Age.
+ *
+ * We run mostly with the original cookie spec, as hardly anyone implements
+ * anything else.
+ */
+ data->set.cookiesession = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_COOKIELIST:
+ argptr = va_arg(param, char *);
+
+ if(argptr == NULL)
+ break;
+
+ if(Curl_raw_equal(argptr, "ALL")) {
+ /* clear all cookies */
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_clearall(data->cookies);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ else if(Curl_raw_equal(argptr, "SESS")) {
+ /* clear session cookies */
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_clearsess(data->cookies);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ else if(Curl_raw_equal(argptr, "FLUSH")) {
+ /* flush cookies to file, takes care of the locking */
+ Curl_flush_cookies(data, 0);
+ }
+ else {
+ if(!data->cookies)
+ /* if cookie engine was not running, activate it */
+ data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
+
+ argptr = strdup(argptr);
+ if(!argptr) {
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+
+ if(checkprefix("Set-Cookie:", argptr))
+ /* HTTP Header format line */
+ Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
+
+ else
+ /* Netscape format line */
+ Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
+
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ free(argptr);
+ }
+ }
+
+ break;
+#endif /* CURL_DISABLE_COOKIES */
+
+ case CURLOPT_HTTPGET:
+ /*
+ * Set to force us do HTTP GET
+ */
+ if(va_arg(param, long)) {
+ data->set.httpreq = HTTPREQ_GET;
+ data->set.upload = FALSE; /* switch off upload */
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ 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.
+ */
+ arg = va_arg(param, long);
+#ifndef USE_NGHTTP2
+ if(arg == CURL_HTTP_VERSION_2_0)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+ data->set.httpversion = arg;
+ break;
+
+ case CURLOPT_HTTPAUTH:
+ /*
+ * Set HTTP Authentication type BITMASK.
+ */
+ {
+ int bitcheck;
+ bool authbits;
+ unsigned long auth = va_arg(param, unsigned long);
+
+ if(auth == CURLAUTH_NONE) {
+ data->set.httpauth = auth;
+ break;
+ }
+
+ /* the DIGEST_IE bit is only used to set a special marker, for all the
+ rest we need to handle it as normal DIGEST */
+ data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE;
+
+ if(auth & CURLAUTH_DIGEST_IE) {
+ auth |= CURLAUTH_DIGEST; /* set standard digest bit */
+ auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
+ }
+
+ /* switch off bits we can't support */
+#ifndef USE_NTLM
+ auth &= ~CURLAUTH_NTLM; /* no NTLM support */
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#endif
+#ifndef USE_SPNEGO
+ auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
+ GSS-API or SSPI */
+#endif
+
+ /* check if any auth bit lower than CURLAUTH_ONLY is still set */
+ bitcheck = 0;
+ authbits = FALSE;
+ while(bitcheck < 31) {
+ if(auth & (1UL << bitcheck++)) {
+ authbits = TRUE;
+ break;
+ }
+ }
+ if(!authbits)
+ return CURLE_NOT_BUILT_IN; /* no supported types left! */
+
+ data->set.httpauth = auth;
+ }
+ break;
+
+ case CURLOPT_EXPECT_100_TIMEOUT_MS:
+ /*
+ * Time to wait for a response to a HTTP request containing an
+ * Expect: 100-continue header before sending the data anyway.
+ */
+ data->set.expect_100_timeout = va_arg(param, long);
+ break;
+
+#endif /* CURL_DISABLE_HTTP */
+
+ case CURLOPT_CUSTOMREQUEST:
+ /*
+ * Set a custom string to use as request
+ */
+ result = setstropt(&data->set.str[STRING_CUSTOMREQUEST],
+ va_arg(param, char *));
+
+ /* we don't set
+ data->set.httpreq = HTTPREQ_CUSTOM;
+ here, we continue as if we were using the already set type
+ and this just changes the actual request keyword */
+ break;
+
+#ifndef CURL_DISABLE_PROXY
+ case CURLOPT_HTTPPROXYTUNNEL:
+ /*
+ * Tunnel operations through the proxy instead of normal proxy use
+ */
+ data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_PROXYPORT:
+ /*
+ * Explicitly set HTTP proxy port number.
+ */
+ data->set.proxyport = va_arg(param, long);
+ break;
+
+ case CURLOPT_PROXYAUTH:
+ /*
+ * Set HTTP Authentication type BITMASK.
+ */
+ {
+ int bitcheck;
+ bool authbits;
+ unsigned long auth = va_arg(param, unsigned long);
+
+ if(auth == CURLAUTH_NONE) {
+ data->set.proxyauth = auth;
+ break;
+ }
+
+ /* the DIGEST_IE bit is only used to set a special marker, for all the
+ rest we need to handle it as normal DIGEST */
+ data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE;
+
+ if(auth & CURLAUTH_DIGEST_IE) {
+ auth |= CURLAUTH_DIGEST; /* set standard digest bit */
+ auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
+ }
+ /* switch off bits we can't support */
+#ifndef USE_NTLM
+ auth &= ~CURLAUTH_NTLM; /* no NTLM support */
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+ auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#endif
+#ifndef USE_SPNEGO
+ auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
+ GSS-API or SSPI */
+#endif
+
+ /* check if any auth bit lower than CURLAUTH_ONLY is still set */
+ bitcheck = 0;
+ authbits = FALSE;
+ while(bitcheck < 31) {
+ if(auth & (1UL << bitcheck++)) {
+ authbits = TRUE;
+ break;
+ }
+ }
+ if(!authbits)
+ return CURLE_NOT_BUILT_IN; /* no supported types left! */
+
+ data->set.proxyauth = auth;
+ }
+ break;
+
+ case CURLOPT_PROXY:
+ /*
+ * Set proxy server:port to use as HTTP proxy.
+ *
+ * If the proxy is set to "" we explicitly say that we don't want to use a
+ * proxy (even though there might be environment variables saying so).
+ *
+ * Setting it to NULL, means no proxy but allows the environment variables
+ * to decide for us.
+ */
+ result = setstropt(&data->set.str[STRING_PROXY],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_PROXYTYPE:
+ /*
+ * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
+ */
+ data->set.proxytype = (curl_proxytype)va_arg(param, long);
+ break;
+
+ case CURLOPT_PROXY_TRANSFER_MODE:
+ /*
+ * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
+ */
+ switch (va_arg(param, long)) {
+ case 0:
+ data->set.proxy_transfer_mode = FALSE;
+ break;
+ case 1:
+ data->set.proxy_transfer_mode = TRUE;
+ break;
+ default:
+ /* reserve other values for future use */
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
+ break;
+#endif /* CURL_DISABLE_PROXY */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ case CURLOPT_SOCKS5_GSSAPI_SERVICE:
+ /*
+ * Set GSS-API service name
+ */
+ result = setstropt(&data->set.str[STRING_SOCKS5_GSSAPI_SERVICE],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SOCKS5_GSSAPI_NEC:
+ /*
+ * set flag for nec socks5 support
+ */
+ data->set.socks5_gssapi_nec = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+#endif
+
+ case CURLOPT_HEADERDATA:
+ /*
+ * Custom pointer to pass the header write callback function
+ */
+ data->set.writeheader = (void *)va_arg(param, void *);
+ break;
+ case CURLOPT_ERRORBUFFER:
+ /*
+ * Error buffer provided by the caller to get the human readable
+ * error string in.
+ */
+ data->set.errorbuffer = va_arg(param, char *);
+ break;
+ case CURLOPT_WRITEDATA:
+ /*
+ * FILE pointer to write to. Or possibly
+ * used as argument to the write callback.
+ */
+ data->set.out = va_arg(param, void *);
+ break;
+ case CURLOPT_FTPPORT:
+ /*
+ * Use FTP PORT, this also specifies which IP address to use
+ */
+ result = setstropt(&data->set.str[STRING_FTPPORT],
+ va_arg(param, char *));
+ data->set.ftp_use_port = (NULL != data->set.str[STRING_FTPPORT]) ?
+ TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_EPRT:
+ data->set.ftp_use_eprt = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_EPSV:
+ data->set.ftp_use_epsv = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_USE_PRET:
+ data->set.ftp_use_pret = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_SSL_CCC:
+ data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
+ break;
+
+ case CURLOPT_FTP_SKIP_PASV_IP:
+ /*
+ * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
+ * bypass of the IP address in PASV responses.
+ */
+ data->set.ftp_skip_ip = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_READDATA:
+ /*
+ * FILE pointer to read the file to be uploaded from. Or possibly
+ * used as argument to the read callback.
+ */
+ data->set.in = va_arg(param, void *);
+ break;
+ case CURLOPT_INFILESIZE:
+ /*
+ * If known, this should inform curl about the file size of the
+ * to-be-uploaded file.
+ */
+ data->set.filesize = va_arg(param, long);
+ break;
+ case CURLOPT_INFILESIZE_LARGE:
+ /*
+ * If known, this should inform curl about the file size of the
+ * to-be-uploaded file.
+ */
+ data->set.filesize = va_arg(param, curl_off_t);
+ break;
+ case CURLOPT_LOW_SPEED_LIMIT:
+ /*
+ * The low speed limit that if transfers are below this for
+ * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
+ */
+ data->set.low_speed_limit=va_arg(param, long);
+ break;
+ case CURLOPT_MAX_SEND_SPEED_LARGE:
+ /*
+ * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
+ * bytes per second the transfer is throttled..
+ */
+ data->set.max_send_speed=va_arg(param, curl_off_t);
+ break;
+ case CURLOPT_MAX_RECV_SPEED_LARGE:
+ /*
+ * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
+ * second the transfer is throttled..
+ */
+ data->set.max_recv_speed=va_arg(param, curl_off_t);
+ break;
+ case CURLOPT_LOW_SPEED_TIME:
+ /*
+ * The low speed time that if transfers are below the set
+ * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
+ */
+ data->set.low_speed_time=va_arg(param, long);
+ break;
+ case CURLOPT_URL:
+ /*
+ * The URL to fetch.
+ */
+ if(data->change.url_alloc) {
+ /* the already set URL is allocated, free it first! */
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+ result = setstropt(&data->set.str[STRING_SET_URL],
+ va_arg(param, char *));
+ data->change.url = data->set.str[STRING_SET_URL];
+ break;
+ case CURLOPT_PORT:
+ /*
+ * The port number to use when getting the URL
+ */
+ data->set.use_port = va_arg(param, long);
+ break;
+ case CURLOPT_TIMEOUT:
+ /*
+ * The maximum time you allow curl to use for a single transfer
+ * operation.
+ */
+ data->set.timeout = va_arg(param, long) * 1000L;
+ break;
+
+ case CURLOPT_TIMEOUT_MS:
+ data->set.timeout = va_arg(param, long);
+ break;
+
+ case CURLOPT_CONNECTTIMEOUT:
+ /*
+ * The maximum time you allow curl to use to connect.
+ */
+ data->set.connecttimeout = va_arg(param, long) * 1000L;
+ break;
+
+ case CURLOPT_CONNECTTIMEOUT_MS:
+ data->set.connecttimeout = va_arg(param, long);
+ break;
+
+ case CURLOPT_ACCEPTTIMEOUT_MS:
+ /*
+ * The maximum time you allow curl to wait for server connect
+ */
+ data->set.accepttimeout = va_arg(param, long);
+ break;
+
+ case CURLOPT_USERPWD:
+ /*
+ * user:password to use in the operation
+ */
+ result = setstropt_userpwd(va_arg(param, char *),
+ &data->set.str[STRING_USERNAME],
+ &data->set.str[STRING_PASSWORD]);
+ break;
+
+ case CURLOPT_USERNAME:
+ /*
+ * authentication user name to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_USERNAME],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_PASSWORD:
+ /*
+ * authentication password to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_PASSWORD],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_LOGIN_OPTIONS:
+ /*
+ * authentication options to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_OPTIONS],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_XOAUTH2_BEARER:
+ /*
+ * XOAUTH2 bearer token to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_BEARER],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_POSTQUOTE:
+ /*
+ * List of RAW FTP commands to use after a transfer
+ */
+ data->set.postquote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_PREQUOTE:
+ /*
+ * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
+ */
+ data->set.prequote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_QUOTE:
+ /*
+ * List of RAW FTP commands to use before a transfer
+ */
+ data->set.quote = va_arg(param, struct curl_slist *);
+ break;
+ case CURLOPT_RESOLVE:
+ /*
+ * List of NAME:[address] names to populate the DNS cache with
+ * Prefix the NAME with dash (-) to _remove_ the name from the cache.
+ *
+ * Names added with this API will remain in the cache until explicitly
+ * removed or the handle is cleaned up.
+ *
+ * This API can remove any name from the DNS cache, but only entries
+ * that aren't actually in use right now will be pruned immediately.
+ */
+ data->set.resolve = va_arg(param, struct curl_slist *);
+ data->change.resolve = data->set.resolve;
+ break;
+ case CURLOPT_PROGRESSFUNCTION:
+ /*
+ * Progress callback function
+ */
+ data->set.fprogress = va_arg(param, curl_progress_callback);
+ if(data->set.fprogress)
+ data->progress.callback = TRUE; /* no longer internal */
+ else
+ data->progress.callback = FALSE; /* NULL enforces internal */
+ break;
+
+ case CURLOPT_XFERINFOFUNCTION:
+ /*
+ * Transfer info callback function
+ */
+ data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
+ if(data->set.fxferinfo)
+ data->progress.callback = TRUE; /* no longer internal */
+ else
+ data->progress.callback = FALSE; /* NULL enforces internal */
+
+ break;
+
+ case CURLOPT_PROGRESSDATA:
+ /*
+ * Custom client data to pass to the progress callback
+ */
+ data->set.progress_client = va_arg(param, void *);
+ break;
+
+#ifndef CURL_DISABLE_PROXY
+ case CURLOPT_PROXYUSERPWD:
+ /*
+ * user:password needed to use the proxy
+ */
+ result = setstropt_userpwd(va_arg(param, char *),
+ &data->set.str[STRING_PROXYUSERNAME],
+ &data->set.str[STRING_PROXYPASSWORD]);
+ break;
+ case CURLOPT_PROXYUSERNAME:
+ /*
+ * authentication user name to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_PROXYUSERNAME],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXYPASSWORD:
+ /*
+ * authentication password to use in the operation
+ */
+ result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_NOPROXY:
+ /*
+ * proxy exception list
+ */
+ result = setstropt(&data->set.str[STRING_NOPROXY],
+ va_arg(param, char *));
+ break;
+#endif
+
+ case CURLOPT_RANGE:
+ /*
+ * What range of the file you want to transfer
+ */
+ result = setstropt(&data->set.str[STRING_SET_RANGE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_RESUME_FROM:
+ /*
+ * Resume transfer at the give file position
+ */
+ data->set.set_resume_from = va_arg(param, long);
+ break;
+ case CURLOPT_RESUME_FROM_LARGE:
+ /*
+ * Resume transfer at the give file position
+ */
+ data->set.set_resume_from = va_arg(param, curl_off_t);
+ break;
+ case CURLOPT_DEBUGFUNCTION:
+ /*
+ * stderr write callback.
+ */
+ data->set.fdebug = va_arg(param, curl_debug_callback);
+ /*
+ * if the callback provided is NULL, it'll use the default callback
+ */
+ break;
+ case CURLOPT_DEBUGDATA:
+ /*
+ * Set to a void * that should receive all error writes. This
+ * defaults to CURLOPT_STDERR for normal operations.
+ */
+ data->set.debugdata = va_arg(param, void *);
+ break;
+ case CURLOPT_STDERR:
+ /*
+ * Set to a FILE * that should receive all error writes. This
+ * defaults to stderr for normal operations.
+ */
+ data->set.err = va_arg(param, FILE *);
+ if(!data->set.err)
+ data->set.err = stderr;
+ break;
+ case CURLOPT_HEADERFUNCTION:
+ /*
+ * Set header write callback
+ */
+ data->set.fwrite_header = va_arg(param, curl_write_callback);
+ break;
+ case CURLOPT_WRITEFUNCTION:
+ /*
+ * Set data write callback
+ */
+ data->set.fwrite_func = va_arg(param, curl_write_callback);
+ if(!data->set.fwrite_func) {
+ data->set.is_fwrite_set = 0;
+ /* When set to NULL, reset to our internal default function */
+ data->set.fwrite_func = (curl_write_callback)fwrite;
+ }
+ else
+ data->set.is_fwrite_set = 1;
+ break;
+ case CURLOPT_READFUNCTION:
+ /*
+ * Read data callback
+ */
+ data->set.fread_func = va_arg(param, curl_read_callback);
+ if(!data->set.fread_func) {
+ data->set.is_fread_set = 0;
+ /* When set to NULL, reset to our internal default function */
+ data->set.fread_func = (curl_read_callback)fread;
+ }
+ else
+ data->set.is_fread_set = 1;
+ break;
+ case CURLOPT_SEEKFUNCTION:
+ /*
+ * Seek callback. Might be NULL.
+ */
+ data->set.seek_func = va_arg(param, curl_seek_callback);
+ break;
+ case CURLOPT_SEEKDATA:
+ /*
+ * Seek control callback. Might be NULL.
+ */
+ data->set.seek_client = va_arg(param, void *);
+ break;
+ case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
+ /*
+ * "Convert from network encoding" callback
+ */
+ data->set.convfromnetwork = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_CONV_TO_NETWORK_FUNCTION:
+ /*
+ * "Convert to network encoding" callback
+ */
+ data->set.convtonetwork = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_CONV_FROM_UTF8_FUNCTION:
+ /*
+ * "Convert from UTF-8 encoding" callback
+ */
+ data->set.convfromutf8 = va_arg(param, curl_conv_callback);
+ break;
+ case CURLOPT_IOCTLFUNCTION:
+ /*
+ * I/O control callback. Might be NULL.
+ */
+ data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
+ break;
+ case CURLOPT_IOCTLDATA:
+ /*
+ * I/O control data pointer. Might be NULL.
+ */
+ data->set.ioctl_client = va_arg(param, void *);
+ break;
+ case CURLOPT_SSLCERT:
+ /*
+ * String that holds file name of the SSL certificate to use
+ */
+ result = setstropt(&data->set.str[STRING_CERT],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLCERTTYPE:
+ /*
+ * String that holds file type of the SSL certificate to use
+ */
+ result = setstropt(&data->set.str[STRING_CERT_TYPE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLKEY:
+ /*
+ * String that holds file name of the SSL key to use
+ */
+ result = setstropt(&data->set.str[STRING_KEY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLKEYTYPE:
+ /*
+ * String that holds file type of the SSL key to use
+ */
+ result = setstropt(&data->set.str[STRING_KEY_TYPE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_KEYPASSWD:
+ /*
+ * String that holds the SSL or SSH private key password.
+ */
+ result = setstropt(&data->set.str[STRING_KEY_PASSWD],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSLENGINE:
+ /*
+ * String that holds the SSL crypto engine.
+ */
+ argptr = va_arg(param, char *);
+ if(argptr && argptr[0])
+ result = Curl_ssl_set_engine(data, argptr);
+ break;
+
+ case CURLOPT_SSLENGINE_DEFAULT:
+ /*
+ * flag to set engine as default.
+ */
+ result = Curl_ssl_set_engine_default(data);
+ break;
+ case CURLOPT_CRLF:
+ /*
+ * Kludgy option to enable CRLF conversions. Subject for removal.
+ */
+ data->set.crlf = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_INTERFACE:
+ /*
+ * Set what interface or address/hostname to bind the socket to when
+ * performing an operation and thus what from-IP your connection will use.
+ */
+ result = setstropt(&data->set.str[STRING_DEVICE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_LOCALPORT:
+ /*
+ * Set what local port to bind the socket to when performing an operation.
+ */
+ data->set.localport = curlx_sltous(va_arg(param, long));
+ break;
+ case CURLOPT_LOCALPORTRANGE:
+ /*
+ * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
+ */
+ data->set.localportrange = curlx_sltosi(va_arg(param, long));
+ break;
+ case CURLOPT_KRBLEVEL:
+ /*
+ * A string that defines the kerberos security level.
+ */
+ result = setstropt(&data->set.str[STRING_KRB_LEVEL],
+ va_arg(param, char *));
+ data->set.krb = (NULL != data->set.str[STRING_KRB_LEVEL])?TRUE:FALSE;
+ break;
+ case CURLOPT_GSSAPI_DELEGATION:
+ /*
+ * GSS-API credential delegation
+ */
+ data->set.gssapi_delegation = va_arg(param, long);
+ break;
+ case CURLOPT_SSL_VERIFYPEER:
+ /*
+ * Enable peer SSL verifying.
+ */
+ data->set.ssl.verifypeer = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_SSL_VERIFYHOST:
+ /*
+ * Enable verification of the host name in the peer certificate
+ */
+ arg = va_arg(param, long);
+
+ /* Obviously people are not reading documentation and too many thought
+ this argument took a boolean when it wasn't and misused it. We thus ban
+ 1 as a sensible input and we warn about its use. Then we only have the
+ 2 action internally stored as TRUE. */
+
+ if(1 == arg) {
+ failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ data->set.ssl.verifyhost = (0 != arg)?TRUE:FALSE;
+ break;
+#ifdef USE_SSLEAY
+ /* since these two options are only possible to use on an OpenSSL-
+ powered libcurl we #ifdef them on this condition so that libcurls
+ built against other SSL libs will return a proper error when trying
+ to set this option! */
+ case CURLOPT_SSL_CTX_FUNCTION:
+ /*
+ * Set a SSL_CTX callback
+ */
+ data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
+ break;
+ case CURLOPT_SSL_CTX_DATA:
+ /*
+ * Set a SSL_CTX callback parameter pointer
+ */
+ data->set.ssl.fsslctxp = va_arg(param, void *);
+ break;
+#endif
+#if defined(USE_SSLEAY) || defined(USE_QSOSSL) || defined(USE_GSKIT) || \
+ defined(USE_NSS)
+ case CURLOPT_CERTINFO:
+ data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+#endif
+ case CURLOPT_CAINFO:
+ /*
+ * Set CA info for SSL connection. Specify file name of the CA certificate
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CAFILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_CAPATH:
+ /*
+ * Set CA path info for SSL connection. Specify directory name of the CA
+ * certificates which have been prepared using openssl c_rehash utility.
+ */
+ /* This does not work on windows. */
+ result = setstropt(&data->set.str[STRING_SSL_CAPATH],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_CRLFILE:
+ /*
+ * Set CRL file info for SSL connection. Specify file name of the CRL
+ * to check certificates revocation
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_ISSUERCERT:
+ /*
+ * Set Issuer certificate file
+ * to check certificates issuer
+ */
+ result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_TELNETOPTIONS:
+ /*
+ * Set a linked list of telnet options
+ */
+ data->set.telnet_options = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_BUFFERSIZE:
+ /*
+ * The application kindly asks for a differently sized receive buffer.
+ * If it seems reasonable, we'll use it.
+ */
+ data->set.buffer_size = va_arg(param, long);
+
+ if((data->set.buffer_size> (BUFSIZE -1 )) ||
+ (data->set.buffer_size < 1))
+ data->set.buffer_size = 0; /* huge internal default */
+
+ break;
+
+ case CURLOPT_NOSIGNAL:
+ /*
+ * The application asks not to set any signal() or alarm() handlers,
+ * even when using a timeout.
+ */
+ data->set.no_signal = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_SHARE:
+ {
+ struct Curl_share *set;
+ set = va_arg(param, struct Curl_share *);
+
+ /* disconnect from old share, if any */
+ if(data->share) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+
+ if(data->dns.hostcachetype == HCACHE_SHARED) {
+ data->dns.hostcache = NULL;
+ data->dns.hostcachetype = HCACHE_NONE;
+ }
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(data->share->cookies == data->cookies)
+ data->cookies = NULL;
+#endif
+
+ if(data->share->sslsession == data->state.session)
+ data->state.session = NULL;
+
+ data->share->dirty--;
+
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+ data->share = NULL;
+ }
+
+ /* use new share if it set */
+ data->share = set;
+ if(data->share) {
+
+ Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+
+ data->share->dirty++;
+
+ if(data->share->hostcache) {
+ /* use shared host cache */
+ data->dns.hostcache = data->share->hostcache;
+ data->dns.hostcachetype = HCACHE_SHARED;
+ }
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(data->share->cookies) {
+ /* use shared cookie list, first free own one if any */
+ if(data->cookies)
+ Curl_cookie_cleanup(data->cookies);
+ /* enable cookies since we now use a share that uses cookies! */
+ data->cookies = data->share->cookies;
+ }
+#endif /* CURL_DISABLE_HTTP */
+ if(data->share->sslsession) {
+ data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+ data->state.session = data->share->sslsession;
+ }
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+
+ }
+ /* check for host cache not needed,
+ * it will be done by curl_easy_perform */
+ }
+ break;
+
+ case CURLOPT_PRIVATE:
+ /*
+ * Set private data pointer.
+ */
+ data->set.private_data = va_arg(param, void *);
+ break;
+
+ case CURLOPT_MAXFILESIZE:
+ /*
+ * Set the maximum size of a file to download.
+ */
+ data->set.max_filesize = va_arg(param, long);
+ break;
+
+#ifdef USE_SSL
+ case CURLOPT_USE_SSL:
+ /*
+ * Make transfers attempt to use SSL/TLS.
+ */
+ data->set.use_ssl = (curl_usessl)va_arg(param, long);
+ break;
+
+ case CURLOPT_SSL_OPTIONS:
+ arg = va_arg(param, long);
+ data->set.ssl_enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+ break;
+
+#endif
+ case CURLOPT_FTPSSLAUTH:
+ /*
+ * Set a specific auth for FTP-SSL transfers.
+ */
+ data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
+ break;
+
+ case CURLOPT_IPRESOLVE:
+ data->set.ipver = va_arg(param, long);
+ break;
+
+ case CURLOPT_MAXFILESIZE_LARGE:
+ /*
+ * Set the maximum size of a file to download.
+ */
+ data->set.max_filesize = va_arg(param, curl_off_t);
+ break;
+
+ case CURLOPT_TCP_NODELAY:
+ /*
+ * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
+ * algorithm
+ */
+ data->set.tcp_nodelay = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_ACCOUNT:
+ result = setstropt(&data->set.str[STRING_FTP_ACCOUNT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_IGNORE_CONTENT_LENGTH:
+ data->set.ignorecl = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_CONNECT_ONLY:
+ /*
+ * No data transfer, set up connection and let application use the socket
+ */
+ data->set.connect_only = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_FTP_ALTERNATIVE_TO_USER:
+ result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SOCKOPTFUNCTION:
+ /*
+ * socket callback function: called after socket() but before connect()
+ */
+ data->set.fsockopt = va_arg(param, curl_sockopt_callback);
+ break;
+
+ case CURLOPT_SOCKOPTDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.sockopt_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_OPENSOCKETFUNCTION:
+ /*
+ * open/create socket callback function: called instead of socket(),
+ * before connect()
+ */
+ data->set.fopensocket = va_arg(param, curl_opensocket_callback);
+ break;
+
+ case CURLOPT_OPENSOCKETDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.opensocket_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_CLOSESOCKETFUNCTION:
+ /*
+ * close socket callback function: called instead of close()
+ * when shutting down a connection
+ */
+ data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
+ break;
+
+ case CURLOPT_CLOSESOCKETDATA:
+ /*
+ * socket callback data pointer. Might be NULL.
+ */
+ data->set.closesocket_client = va_arg(param, void *);
+ break;
+
+ case CURLOPT_SSL_SESSIONID_CACHE:
+ data->set.ssl.sessionid = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+#ifdef USE_LIBSSH2
+ /* we only include SSH options if explicitly built to support SSH */
+ case CURLOPT_SSH_AUTH_TYPES:
+ data->set.ssh_auth_types = va_arg(param, long);
+ break;
+
+ case CURLOPT_SSH_PUBLIC_KEYFILE:
+ /*
+ * Use this file instead of the $HOME/.ssh/id_dsa.pub file
+ */
+ result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SSH_PRIVATE_KEYFILE:
+ /*
+ * Use this file instead of the $HOME/.ssh/id_dsa file
+ */
+ result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
+ /*
+ * Option to allow for the MD5 of the host public key to be checked
+ * for validation purposes.
+ */
+ result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
+ va_arg(param, char *));
+ break;
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+ case CURLOPT_SSH_KNOWNHOSTS:
+ /*
+ * Store the file name to read known hosts from.
+ */
+ result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_SSH_KEYFUNCTION:
+ /* setting to NULL is fine since the ssh.c functions themselves will
+ then rever to use the internal default */
+ data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
+ break;
+
+ case CURLOPT_SSH_KEYDATA:
+ /*
+ * Custom client data to pass to the SSH keyfunc callback
+ */
+ data->set.ssh_keyfunc_userp = va_arg(param, void *);
+ break;
+#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
+
+#endif /* USE_LIBSSH2 */
+
+ case CURLOPT_HTTP_TRANSFER_DECODING:
+ /*
+ * disable libcurl transfer encoding is used
+ */
+ data->set.http_te_skip = (0 == va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_HTTP_CONTENT_DECODING:
+ /*
+ * raw data passed to the application when content encoding is used
+ */
+ data->set.http_ce_skip = (0 == va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ case CURLOPT_NEW_FILE_PERMS:
+ /*
+ * Uses these permissions instead of 0644
+ */
+ data->set.new_file_perms = va_arg(param, long);
+ break;
+
+ case CURLOPT_NEW_DIRECTORY_PERMS:
+ /*
+ * Uses these permissions instead of 0755
+ */
+ data->set.new_directory_perms = va_arg(param, long);
+ break;
+
+ case CURLOPT_ADDRESS_SCOPE:
+ /*
+ * We always get longs when passed plain numericals, but for this value we
+ * know that an unsigned int will always hold the value so we blindly
+ * typecast to this type
+ */
+ data->set.scope = curlx_sltoui(va_arg(param, long));
+ break;
+
+ case CURLOPT_PROTOCOLS:
+ /* set the bitmask for the protocols that are allowed to be used for the
+ transfer, which thus helps the app which takes URLs from users or other
+ external inputs and want to restrict what protocol(s) to deal
+ with. Defaults to CURLPROTO_ALL. */
+ data->set.allowed_protocols = va_arg(param, long);
+ break;
+
+ case CURLOPT_REDIR_PROTOCOLS:
+ /* set the bitmask for the protocols that libcurl is allowed to follow to,
+ as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+ to be set in both bitmasks to be allowed to get redirected to. Defaults
+ to all protocols except FILE and SCP. */
+ data->set.redir_protocols = va_arg(param, long);
+ break;
+
+ case CURLOPT_MAIL_FROM:
+ /* Set the SMTP mail originator */
+ result = setstropt(&data->set.str[STRING_MAIL_FROM],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_MAIL_AUTH:
+ /* Set the SMTP auth originator */
+ result = setstropt(&data->set.str[STRING_MAIL_AUTH],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_MAIL_RCPT:
+ /* Set the list of mail recipients */
+ data->set.mail_rcpt = va_arg(param, struct curl_slist *);
+ break;
+
+ case CURLOPT_SASL_IR:
+ /* Enable/disable SASL initial response */
+ data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_RTSP_REQUEST:
+ {
+ /*
+ * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
+ * Would this be better if the RTSPREQ_* were just moved into here?
+ */
+ long curl_rtspreq = va_arg(param, long);
+ Curl_RtspReq rtspreq = RTSPREQ_NONE;
+ switch(curl_rtspreq) {
+ case CURL_RTSPREQ_OPTIONS:
+ rtspreq = RTSPREQ_OPTIONS;
+ break;
+
+ case CURL_RTSPREQ_DESCRIBE:
+ rtspreq = RTSPREQ_DESCRIBE;
+ break;
+
+ case CURL_RTSPREQ_ANNOUNCE:
+ rtspreq = RTSPREQ_ANNOUNCE;
+ break;
+
+ case CURL_RTSPREQ_SETUP:
+ rtspreq = RTSPREQ_SETUP;
+ break;
+
+ case CURL_RTSPREQ_PLAY:
+ rtspreq = RTSPREQ_PLAY;
+ break;
+
+ case CURL_RTSPREQ_PAUSE:
+ rtspreq = RTSPREQ_PAUSE;
+ break;
+
+ case CURL_RTSPREQ_TEARDOWN:
+ rtspreq = RTSPREQ_TEARDOWN;
+ break;
+
+ case CURL_RTSPREQ_GET_PARAMETER:
+ rtspreq = RTSPREQ_GET_PARAMETER;
+ break;
+
+ case CURL_RTSPREQ_SET_PARAMETER:
+ rtspreq = RTSPREQ_SET_PARAMETER;
+ break;
+
+ case CURL_RTSPREQ_RECORD:
+ rtspreq = RTSPREQ_RECORD;
+ break;
+
+ case CURL_RTSPREQ_RECEIVE:
+ rtspreq = RTSPREQ_RECEIVE;
+ break;
+ default:
+ rtspreq = RTSPREQ_NONE;
+ }
+
+ data->set.rtspreq = rtspreq;
+ break;
+ }
+
+
+ case CURLOPT_RTSP_SESSION_ID:
+ /*
+ * Set the RTSP Session ID manually. Useful if the application is
+ * resuming a previously established RTSP session
+ */
+ result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_STREAM_URI:
+ /*
+ * Set the Stream URI for the RTSP request. Unless the request is
+ * for generic server options, the application will need to set this.
+ */
+ result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_TRANSPORT:
+ /*
+ * The content of the Transport: header for the RTSP request
+ */
+ result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
+ va_arg(param, char *));
+ break;
+
+ case CURLOPT_RTSP_CLIENT_CSEQ:
+ /*
+ * Set the CSEQ number to issue for the next RTSP request. Useful if the
+ * application is resuming a previously broken connection. The CSEQ
+ * will increment from this new number henceforth.
+ */
+ data->state.rtsp_next_client_CSeq = va_arg(param, long);
+ break;
+
+ case CURLOPT_RTSP_SERVER_CSEQ:
+ /* Same as the above, but for server-initiated requests */
+ data->state.rtsp_next_client_CSeq = va_arg(param, long);
+ break;
+
+ case CURLOPT_INTERLEAVEDATA:
+ data->set.rtp_out = va_arg(param, void *);
+ break;
+ case CURLOPT_INTERLEAVEFUNCTION:
+ /* Set the user defined RTP write function */
+ data->set.fwrite_rtp = va_arg(param, curl_write_callback);
+ break;
+
+ case CURLOPT_WILDCARDMATCH:
+ data->set.wildcardmatch = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_CHUNK_BGN_FUNCTION:
+ data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
+ break;
+ case CURLOPT_CHUNK_END_FUNCTION:
+ data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
+ break;
+ case CURLOPT_FNMATCH_FUNCTION:
+ data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
+ break;
+ case CURLOPT_CHUNK_DATA:
+ data->wildcard.customptr = va_arg(param, void *);
+ break;
+ case CURLOPT_FNMATCH_DATA:
+ data->set.fnmatch_data = va_arg(param, void *);
+ break;
+#ifdef USE_TLS_SRP
+ case CURLOPT_TLSAUTH_USERNAME:
+ result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
+ case CURLOPT_TLSAUTH_PASSWORD:
+ result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
+ case CURLOPT_TLSAUTH_TYPE:
+ if(strnequal((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+ data->set.ssl.authtype = CURL_TLSAUTH_SRP;
+ else
+ data->set.ssl.authtype = CURL_TLSAUTH_NONE;
+ break;
+#endif
+ case CURLOPT_DNS_SERVERS:
+ result = Curl_set_dns_servers(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_INTERFACE:
+ result = Curl_set_dns_interface(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_LOCAL_IP4:
+ result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
+ break;
+ case CURLOPT_DNS_LOCAL_IP6:
+ result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
+ break;
+
+ case CURLOPT_TCP_KEEPALIVE:
+ data->set.tcp_keepalive = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_TCP_KEEPIDLE:
+ data->set.tcp_keepidle = va_arg(param, long);
+ break;
+ case CURLOPT_TCP_KEEPINTVL:
+ data->set.tcp_keepintvl = va_arg(param, long);
+ break;
+ case CURLOPT_SSL_ENABLE_NPN:
+ data->set.ssl_enable_npn = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+ case CURLOPT_SSL_ENABLE_ALPN:
+ data->set.ssl_enable_alpn = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
+
+ default:
+ /* unknown tag and its companion, just ignore: */
+ result = CURLE_UNKNOWN_OPTION;
+ break;
+ }
+
+ return result;
+}
+
+static void conn_free(struct connectdata *conn)
+{
+ if(!conn)
+ return;
+
+ /* possible left-overs from the async name resolvers */
+ Curl_resolver_cancel(conn);
+
+ /* close the SSL stuff before we close any sockets since they will/may
+ write to the sockets */
+ Curl_ssl_close(conn, FIRSTSOCKET);
+ Curl_ssl_close(conn, SECONDARYSOCKET);
+
+ /* close possibly still open sockets */
+ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
+ Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
+ Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
+ if(CURL_SOCKET_BAD != conn->tempsock[0])
+ Curl_closesocket(conn, conn->tempsock[0]);
+ if(CURL_SOCKET_BAD != conn->tempsock[1])
+ Curl_closesocket(conn, conn->tempsock[1]);
+
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ Curl_ntlm_wb_cleanup(conn);
+#endif
+
+ Curl_safefree(conn->user);
+ Curl_safefree(conn->passwd);
+ Curl_safefree(conn->xoauth2_bearer);
+ Curl_safefree(conn->options);
+ Curl_safefree(conn->proxyuser);
+ Curl_safefree(conn->proxypasswd);
+ Curl_safefree(conn->allocptr.proxyuserpwd);
+ Curl_safefree(conn->allocptr.uagent);
+ Curl_safefree(conn->allocptr.userpwd);
+ Curl_safefree(conn->allocptr.accept_encoding);
+ Curl_safefree(conn->allocptr.te);
+ Curl_safefree(conn->allocptr.rangeline);
+ Curl_safefree(conn->allocptr.ref);
+ Curl_safefree(conn->allocptr.host);
+ Curl_safefree(conn->allocptr.cookiehost);
+ Curl_safefree(conn->allocptr.rtsp_transport);
+ Curl_safefree(conn->trailer);
+ Curl_safefree(conn->host.rawalloc); /* host name buffer */
+ Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
+ Curl_safefree(conn->master_buffer);
+
+ Curl_llist_destroy(conn->send_pipe, NULL);
+ Curl_llist_destroy(conn->recv_pipe, NULL);
+
+ conn->send_pipe = NULL;
+ conn->recv_pipe = NULL;
+
+ Curl_safefree(conn->localdev);
+ Curl_free_ssl_config(&conn->ssl_config);
+
+ free(conn); /* free all the connection oriented data */
+}
+
+/*
+ * Disconnects the given connection. Note the connection may not be the
+ * primary connection, like when freeing room in the connection cache or
+ * killing of a dead old connection.
+ *
+ * This function MUST NOT reset state in the SessionHandle struct if that
+ * isn't strictly bound to the life-time of *this* particular connection.
+ *
+ */
+
+CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
+{
+ struct SessionHandle *data;
+ if(!conn)
+ return CURLE_OK; /* this is closed and fine already */
+ data = conn->data;
+
+ if(!data) {
+ DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
+ return CURLE_OK;
+ }
+
+ if(conn->dns_entry != NULL) {
+ Curl_resolv_unlock(data, conn->dns_entry);
+ conn->dns_entry = NULL;
+ }
+
+ Curl_hostcache_prune(data); /* kill old DNS cache entries */
+
+ /* Cleanup NTLM connection-related data */
+ Curl_http_ntlm_cleanup(conn);
+
+ if(conn->handler->disconnect)
+ /* This is set if protocol-specific cleanups should be made */
+ conn->handler->disconnect(conn, dead_connection);
+
+ /* unlink ourselves! */
+ infof(data, "Closing connection %ld\n", conn->connection_id);
+ Curl_conncache_remove_conn(data->state.conn_cache, conn);
+
+#if defined(USE_LIBIDN)
+ if(conn->host.encalloc)
+ idn_free(conn->host.encalloc); /* encoded host name buffer, must be freed
+ with idn_free() since this was allocated
+ by libidn */
+ if(conn->proxy.encalloc)
+ idn_free(conn->proxy.encalloc); /* encoded proxy name buffer, must be
+ freed with idn_free() since this was
+ allocated by libidn */
+#elif defined(USE_WIN32_IDN)
+ free(conn->host.encalloc); /* encoded host name buffer, must be freed with
+ idn_free() since this was allocated by
+ curl_win32_idn_to_ascii */
+ if(conn->proxy.encalloc)
+ free(conn->proxy.encalloc); /* encoded proxy name buffer, must be freed
+ with idn_free() since this was allocated by
+ curl_win32_idn_to_ascii */
+#endif
+
+ Curl_ssl_close(conn, FIRSTSOCKET);
+
+ /* Indicate to all handles on the pipe that we're dead */
+ if(Curl_multi_pipeline_enabled(data->multi)) {
+ signalPipeClose(conn->send_pipe, TRUE);
+ signalPipeClose(conn->recv_pipe, TRUE);
+ }
+
+ conn_free(conn);
+
+ return CURLE_OK;
+}
+
+/*
+ * This function should return TRUE if the socket is to be assumed to
+ * be dead. Most commonly this happens when the server has closed the
+ * connection due to inactivity.
+ */
+static bool SocketIsDead(curl_socket_t sock)
+{
+ int sval;
+ bool ret_val = TRUE;
+
+ sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
+ if(sval == 0)
+ /* timeout */
+ ret_val = FALSE;
+
+ return ret_val;
+}
+
+static bool IsPipeliningPossible(const struct SessionHandle *handle,
+ const struct connectdata *conn)
+{
+ if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ Curl_multi_pipeline_enabled(handle->multi) &&
+ (handle->set.httpreq == HTTPREQ_GET ||
+ handle->set.httpreq == HTTPREQ_HEAD) &&
+ handle->set.httpversion != CURL_HTTP_VERSION_1_0)
+ return TRUE;
+
+ return FALSE;
+}
+
+bool Curl_isPipeliningEnabled(const struct SessionHandle *handle)
+{
+ return Curl_multi_pipeline_enabled(handle->multi);
+}
+
+CURLcode Curl_addHandleToPipeline(struct SessionHandle *data,
+ struct curl_llist *pipeline)
+{
+ if(!Curl_llist_insert_next(pipeline, pipeline->tail, data))
+ return CURLE_OUT_OF_MEMORY;
+ return CURLE_OK;
+}
+
+int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
+ struct curl_llist *pipeline)
+{
+ struct curl_llist_element *curr;
+
+ curr = pipeline->head;
+ while(curr) {
+ if(curr->ptr == handle) {
+ Curl_llist_remove(pipeline, curr, NULL);
+ return 1; /* we removed a handle */
+ }
+ curr = curr->next;
+ }
+
+ return 0;
+}
+
+#if 0 /* this code is saved here as it is useful for debugging purposes */
+static void Curl_printPipeline(struct curl_llist *pipeline)
+{
+ struct curl_llist_element *curr;
+
+ curr = pipeline->head;
+ while(curr) {
+ struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
+ infof(data, "Handle in pipeline: %s\n", data->state.path);
+ curr = curr->next;
+ }
+}
+#endif
+
+static struct SessionHandle* gethandleathead(struct curl_llist *pipeline)
+{
+ struct curl_llist_element *curr = pipeline->head;
+ if(curr) {
+ return (struct SessionHandle *) curr->ptr;
+ }
+
+ return NULL;
+}
+
+/* remove the specified connection from all (possible) pipelines and related
+ queues */
+void Curl_getoff_all_pipelines(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ bool recv_head = (conn->readchannel_inuse &&
+ (gethandleathead(conn->recv_pipe) == data)) ? TRUE : FALSE;
+
+ bool send_head = (conn->writechannel_inuse &&
+ (gethandleathead(conn->send_pipe) == data)) ? TRUE : FALSE;
+
+ if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
+ conn->readchannel_inuse = FALSE;
+ if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head)
+ conn->writechannel_inuse = FALSE;
+}
+
+static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
+{
+ struct curl_llist_element *curr;
+
+ if(!pipeline)
+ return;
+
+ curr = pipeline->head;
+ while(curr) {
+ struct curl_llist_element *next = curr->next;
+ struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
+
+#ifdef DEBUGBUILD /* debug-only code */
+ if(data->magic != CURLEASY_MAGIC_NUMBER) {
+ /* MAJOR BADNESS */
+ infof(data, "signalPipeClose() found BAAD easy handle\n");
+ }
+#endif
+
+ if(pipe_broke)
+ data->state.pipe_broke = TRUE;
+ Curl_multi_handlePipeBreak(data);
+ Curl_llist_remove(pipeline, curr, NULL);
+ curr = next;
+ }
+}
+
+/*
+ * This function finds the connection in the connection
+ * cache that has been unused for the longest time.
+ *
+ * Returns the pointer to the oldest idle connection, or NULL if none was
+ * found.
+ */
+static struct connectdata *
+find_oldest_idle_connection(struct SessionHandle *data)
+{
+ struct conncache *bc = data->state.conn_cache;
+ struct curl_hash_iterator iter;
+ struct curl_llist_element *curr;
+ struct curl_hash_element *he;
+ long highscore=-1;
+ long score;
+ struct timeval now;
+ struct connectdata *conn_candidate = NULL;
+ struct connectbundle *bundle;
+
+ now = Curl_tvnow();
+
+ Curl_hash_start_iterate(bc->hash, &iter);
+
+ he = Curl_hash_next_element(&iter);
+ while(he) {
+ struct connectdata *conn;
+
+ bundle = he->ptr;
+
+ curr = bundle->conn_list->head;
+ while(curr) {
+ conn = curr->ptr;
+
+ if(!conn->inuse) {
+ /* Set higher score for the age passed since the connection was used */
+ score = Curl_tvdiff(now, conn->now);
+
+ if(score > highscore) {
+ highscore = score;
+ conn_candidate = conn;
+ }
+ }
+ curr = curr->next;
+ }
+
+ he = Curl_hash_next_element(&iter);
+ }
+
+ return conn_candidate;
+}
+
+/*
+ * This function finds the connection in the connection
+ * bundle that has been unused for the longest time.
+ *
+ * Returns the pointer to the oldest idle connection, or NULL if none was
+ * found.
+ */
+static struct connectdata *
+find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
+ struct connectbundle *bundle)
+{
+ struct curl_llist_element *curr;
+ long highscore=-1;
+ long score;
+ struct timeval now;
+ struct connectdata *conn_candidate = NULL;
+ struct connectdata *conn;
+
+ (void)data;
+
+ now = Curl_tvnow();
+
+ curr = bundle->conn_list->head;
+ while(curr) {
+ conn = curr->ptr;
+
+ if(!conn->inuse) {
+ /* Set higher score for the age passed since the connection was used */
+ score = Curl_tvdiff(now, conn->now);
+
+ if(score > highscore) {
+ highscore = score;
+ conn_candidate = conn;
+ }
+ }
+ curr = curr->next;
+ }
+
+ return conn_candidate;
+}
+
+/*
+ * This function checks if given connection is dead and disconnects if so.
+ * (That also removes it from the connection cache.)
+ *
+ * Returns TRUE if the connection actually was dead and disconnected.
+ */
+static bool disconnect_if_dead(struct connectdata *conn,
+ struct SessionHandle *data)
+{
+ size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
+ if(!pipeLen && !conn->inuse) {
+ /* The check for a dead socket makes sense only if there are no
+ handles in pipeline and the connection isn't already marked in
+ use */
+ bool dead;
+ if(conn->handler->protocol & CURLPROTO_RTSP)
+ /* RTSP is a special case due to RTP interleaving */
+ dead = Curl_rtsp_connisdead(conn);
+ else
+ dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
+
+ if(dead) {
+ conn->data = data;
+ infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
+
+ /* disconnect resources */
+ Curl_disconnect(conn, /* dead_connection */TRUE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Wrapper to use disconnect_if_dead() function in Curl_conncache_foreach()
+ *
+ * Returns always 0.
+ */
+static int call_disconnect_if_dead(struct connectdata *conn,
+ void *param)
+{
+ struct SessionHandle* data = (struct SessionHandle*)param;
+ disconnect_if_dead(conn, data);
+ return 0; /* continue iteration */
+}
+
+/*
+ * This function scans the connection cache for half-open/dead connections,
+ * closes and removes them.
+ * The cleanup is done at most once per second.
+ */
+static void prune_dead_connections(struct SessionHandle *data)
+{
+ struct timeval now = Curl_tvnow();
+ long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+
+ if(elapsed >= 1000L) {
+ Curl_conncache_foreach(data->state.conn_cache, data,
+ call_disconnect_if_dead);
+ data->state.conn_cache->last_cleanup = now;
+ }
+}
+
+/*
+ * Given one filled in connection struct (named needle), this function should
+ * detect if there already is one that has all the significant details
+ * exactly the same and thus should be used instead.
+ *
+ * If there is a match, this function returns TRUE - and has marked the
+ * connection as 'in-use'. It must later be called with ConnectionDone() to
+ * return back to 'idle' (unused) state.
+ *
+ * The force_reuse flag is set if the connection must be used, even if
+ * the pipelining strategy wants to open a new connection instead of reusing.
+ */
+static bool
+ConnectionExists(struct SessionHandle *data,
+ struct connectdata *needle,
+ struct connectdata **usethis,
+ bool *force_reuse)
+{
+ struct connectdata *check;
+ struct connectdata *chosen = 0;
+ bool canPipeline = IsPipeliningPossible(data, needle);
+ bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) ||
+ (data->state.authhost.want & CURLAUTH_NTLM_WB)) &&
+ (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE;
+ struct connectbundle *bundle;
+
+ *force_reuse = FALSE;
+
+ /* We can't pipe if the site is blacklisted */
+ if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
+ canPipeline = FALSE;
+ }
+
+ /* Look up the bundle with all the connections to this
+ particular host */
+ bundle = Curl_conncache_find_bundle(data->state.conn_cache,
+ needle->host.name);
+ if(bundle) {
+ size_t max_pipe_len = Curl_multi_max_pipeline_length(data->multi);
+ size_t best_pipe_len = max_pipe_len;
+ struct curl_llist_element *curr;
+
+ infof(data, "Found bundle for host %s: %p\n",
+ needle->host.name, (void *)bundle);
+
+ /* We can't pipe if we don't know anything about the server */
+ if(canPipeline && !bundle->server_supports_pipelining) {
+ infof(data, "Server doesn't support pipelining\n");
+ canPipeline = FALSE;
+ }
+
+ curr = bundle->conn_list->head;
+ while(curr) {
+ bool match = FALSE;
+ bool credentialsMatch = FALSE;
+ size_t pipeLen;
+
+ /*
+ * Note that if we use a HTTP proxy, we check connections to that
+ * proxy and not to the actual remote server.
+ */
+ check = curr->ptr;
+ curr = curr->next;
+
+ if(disconnect_if_dead(check, data))
+ continue;
+
+ pipeLen = check->send_pipe->size + check->recv_pipe->size;
+
+ if(canPipeline) {
+ /* Make sure the pipe has only GET requests */
+ struct SessionHandle* sh = gethandleathead(check->send_pipe);
+ struct SessionHandle* rh = gethandleathead(check->recv_pipe);
+ if(sh) {
+ if(!IsPipeliningPossible(sh, check))
+ continue;
+ }
+ else if(rh) {
+ if(!IsPipeliningPossible(rh, check))
+ continue;
+ }
+ }
+ else {
+ if(pipeLen > 0) {
+ /* can only happen within multi handles, and means that another easy
+ handle is using this connection */
+ continue;
+ }
+
+ if(Curl_resolver_asynch()) {
+ /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
+ completed yet and until then we don't re-use this connection */
+ if(!check->ip_addr_str[0]) {
+ infof(data,
+ "Connection #%ld is still name resolving, can't reuse\n",
+ check->connection_id);
+ continue;
+ }
+ }
+
+ if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) ||
+ check->bits.close) {
+ /* Don't pick a connection that hasn't connected yet or that is going
+ to get closed. */
+ infof(data, "Connection #%ld isn't open enough, can't reuse\n",
+ check->connection_id);
+#ifdef DEBUGBUILD
+ if(check->recv_pipe->size > 0) {
+ infof(data,
+ "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
+ check->connection_id);
+ }
+#endif
+ continue;
+ }
+ }
+
+ if((needle->handler->flags&PROTOPT_SSL) !=
+ (check->handler->flags&PROTOPT_SSL))
+ /* don't do mixed SSL and non-SSL connections */
+ if(!(needle->handler->protocol & check->handler->protocol))
+ /* except protocols that have been upgraded via TLS */
+ continue;
+
+ if(needle->handler->flags&PROTOPT_SSL) {
+ if((data->set.ssl.verifypeer != check->verifypeer) ||
+ (data->set.ssl.verifyhost != check->verifyhost))
+ continue;
+ }
+
+ if(needle->bits.proxy != check->bits.proxy)
+ /* don't do mixed proxy and non-proxy connections */
+ continue;
+
+ if(!canPipeline && check->inuse)
+ /* this request can't be pipelined but the checked connection is
+ already in use so we skip it */
+ continue;
+
+ if(needle->localdev || needle->localport) {
+ /* If we are bound to a specific local end (IP+port), we must not
+ re-use a random other one, although if we didn't ask for a
+ particular one we can reuse one that was bound.
+
+ This comparison is a bit rough and too strict. Since the input
+ parameters can be specified in numerous ways and still end up the
+ same it would take a lot of processing to make it really accurate.
+ Instead, this matching will assume that re-uses of bound connections
+ will most likely also re-use the exact same binding parameters and
+ missing out a few edge cases shouldn't hurt anyone very much.
+ */
+ if((check->localport != needle->localport) ||
+ (check->localportrange != needle->localportrange) ||
+ !check->localdev ||
+ !needle->localdev ||
+ strcmp(check->localdev, needle->localdev))
+ continue;
+ }
+
+ if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) ||
+ wantNTLMhttp) {
+ /* This protocol requires credentials per connection or is HTTP+NTLM,
+ so verify that we're using the same name and password as well */
+ if(!strequal(needle->user, check->user) ||
+ !strequal(needle->passwd, check->passwd)) {
+ /* one of them was different */
+ continue;
+ }
+ credentialsMatch = TRUE;
+ }
+
+ if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL ||
+ (needle->bits.httpproxy && check->bits.httpproxy &&
+ needle->bits.tunnel_proxy && check->bits.tunnel_proxy &&
+ Curl_raw_equal(needle->proxy.name, check->proxy.name) &&
+ (needle->port == check->port))) {
+ /* The requested connection does not use a HTTP proxy or it uses SSL or
+ it is a non-SSL protocol tunneled over the same http proxy name and
+ port number or it is a non-SSL protocol which is allowed to be
+ upgraded via TLS */
+
+ if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) ||
+ needle->handler->protocol & check->handler->protocol) &&
+ Curl_raw_equal(needle->host.name, check->host.name) &&
+ needle->remote_port == check->remote_port) {
+ if(needle->handler->flags & PROTOPT_SSL) {
+ /* This is a SSL connection so verify that we're using the same
+ SSL options as well */
+ if(!Curl_ssl_config_matches(&needle->ssl_config,
+ &check->ssl_config)) {
+ DEBUGF(infof(data,
+ "Connection #%ld has different SSL parameters, "
+ "can't reuse\n",
+ check->connection_id));
+ continue;
+ }
+ else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
+ DEBUGF(infof(data,
+ "Connection #%ld has not started SSL connect, "
+ "can't reuse\n",
+ check->connection_id));
+ continue;
+ }
+ }
+ match = TRUE;
+ }
+ }
+ else { /* The requested needle connection is using a proxy,
+ is the checked one using the same host, port and type? */
+ if(check->bits.proxy &&
+ (needle->proxytype == check->proxytype) &&
+ (needle->bits.tunnel_proxy == check->bits.tunnel_proxy) &&
+ Curl_raw_equal(needle->proxy.name, check->proxy.name) &&
+ needle->port == check->port) {
+ /* This is the same proxy connection, use it! */
+ match = TRUE;
+ }
+ }
+
+ if(match) {
+ /* If we are looking for an HTTP+NTLM connection, check if this is
+ already authenticating with the right credentials. If not, keep
+ looking so that we can reuse NTLM connections if
+ possible. (Especially we must not reuse the same connection if
+ partway through a handshake!) */
+ if(wantNTLMhttp) {
+ if(credentialsMatch && check->ntlm.state != NTLMSTATE_NONE) {
+ chosen = check;
+
+ /* We must use this connection, no other */
+ *force_reuse = TRUE;
+ break;
+ }
+ else if(credentialsMatch)
+ /* this is a backup choice */
+ chosen = check;
+ continue;
+ }
+
+ if(canPipeline) {
+ /* We can pipeline if we want to. Let's continue looking for
+ the optimal connection to use, i.e the shortest pipe that is not
+ blacklisted. */
+
+ if(pipeLen == 0) {
+ /* We have the optimal connection. Let's stop looking. */
+ chosen = check;
+ break;
+ }
+
+ /* We can't use the connection if the pipe is full */
+ if(pipeLen >= max_pipe_len)
+ continue;
+
+ /* We can't use the connection if the pipe is penalized */
+ if(Curl_pipeline_penalized(data, check))
+ continue;
+
+ if(pipeLen < best_pipe_len) {
+ /* This connection has a shorter pipe so far. We'll pick this
+ and continue searching */
+ chosen = check;
+ best_pipe_len = pipeLen;
+ continue;
+ }
+ }
+ else {
+ /* We have found a connection. Let's stop searching. */
+ chosen = check;
+ break;
+ }
+ }
+ }
+ }
+
+ if(chosen) {
+ *usethis = chosen;
+ return TRUE; /* yes, we found one to use! */
+ }
+
+ return FALSE; /* no matching connecting exists */
+}
+
+/* Mark the connection as 'idle', or close it if the cache is full.
+ Returns TRUE if the connection is kept, or FALSE if it was closed. */
+static bool
+ConnectionDone(struct SessionHandle *data, struct connectdata *conn)
+{
+ /* data->multi->maxconnects can be negative, deal with it. */
+ size_t maxconnects =
+ (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
+ data->multi->maxconnects;
+ struct connectdata *conn_candidate = NULL;
+
+ /* Mark the current connection as 'unused' */
+ conn->inuse = FALSE;
+
+ if(maxconnects > 0 &&
+ data->state.conn_cache->num_connections > maxconnects) {
+ infof(data, "Connection cache is full, closing the oldest one.\n");
+
+ conn_candidate = find_oldest_idle_connection(data);
+
+ if(conn_candidate) {
+ /* Set the connection's owner correctly */
+ conn_candidate->data = data;
+
+ /* the winner gets the honour of being disconnected */
+ (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+ }
+ }
+
+ return (conn_candidate == conn) ? FALSE : TRUE;
+}
+
+/*
+ * The given input connection struct pointer is to be stored in the connection
+ * cache. If the cache is already full, least interesting existing connection
+ * (if any) gets closed.
+ *
+ * The given connection should be unique. That must've been checked prior to
+ * this call.
+ */
+static CURLcode ConnectionStore(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ return Curl_conncache_add_conn(data->state.conn_cache, conn);
+}
+
+/* after a TCP connection to the proxy has been verified, this function does
+ the next magic step.
+
+ Note: this function's sub-functions call failf()
+
+*/
+CURLcode Curl_connected_proxy(struct connectdata *conn,
+ int sockindex)
+{
+ if(!conn->bits.proxy || sockindex)
+ /* this magic only works for the primary socket as the secondary is used
+ for FTP only and it has FTP specific magic in ftp.c */
+ return CURLE_OK;
+
+ switch(conn->proxytype) {
+#ifndef CURL_DISABLE_PROXY
+ case CURLPROXY_SOCKS5:
+ case CURLPROXY_SOCKS5_HOSTNAME:
+ return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
+ conn->host.name, conn->remote_port,
+ FIRSTSOCKET, conn);
+
+ case CURLPROXY_SOCKS4:
+ return Curl_SOCKS4(conn->proxyuser, conn->host.name,
+ conn->remote_port, FIRSTSOCKET, conn, FALSE);
+
+ case CURLPROXY_SOCKS4A:
+ return Curl_SOCKS4(conn->proxyuser, conn->host.name,
+ conn->remote_port, FIRSTSOCKET, conn, TRUE);
+
+#endif /* CURL_DISABLE_PROXY */
+ case CURLPROXY_HTTP:
+ case CURLPROXY_HTTP_1_0:
+ /* do nothing here. handled later. */
+ break;
+ default:
+ break;
+ } /* switch proxytype */
+
+ return CURLE_OK;
+}
+
+/*
+ * verboseconnect() displays verbose information after a connect
+ */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+void Curl_verboseconnect(struct connectdata *conn)
+{
+ if(conn->data->set.verbose)
+ infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
+ conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
+ conn->ip_addr_str, conn->port, conn->connection_id);
+}
+#endif
+
+int Curl_protocol_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ if(conn->handler->proto_getsock)
+ return conn->handler->proto_getsock(conn, socks, numsocks);
+ return GETSOCK_BLANK;
+}
+
+int Curl_doing_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ if(conn && conn->handler->doing_getsock)
+ return conn->handler->doing_getsock(conn, socks, numsocks);
+ return GETSOCK_BLANK;
+}
+
+/*
+ * We are doing protocol-specific connecting and this is being called over and
+ * over from the multi interface until the connection phase is done on
+ * protocol layer.
+ */
+
+CURLcode Curl_protocol_connecting(struct connectdata *conn,
+ bool *done)
+{
+ CURLcode result=CURLE_OK;
+
+ if(conn && conn->handler->connecting) {
+ *done = FALSE;
+ result = conn->handler->connecting(conn, done);
+ }
+ else
+ *done = TRUE;
+
+ return result;
+}
+
+/*
+ * We are DOING this is being called over and over from the multi interface
+ * until the DOING phase is done on protocol layer.
+ */
+
+CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
+{
+ CURLcode result=CURLE_OK;
+
+ if(conn && conn->handler->doing) {
+ *done = FALSE;
+ result = conn->handler->doing(conn, done);
+ }
+ else
+ *done = TRUE;
+
+ return result;
+}
+
+/*
+ * We have discovered that the TCP connection has been successful, we can now
+ * proceed with some action.
+ *
+ */
+CURLcode Curl_protocol_connect(struct connectdata *conn,
+ bool *protocol_done)
+{
+ CURLcode result=CURLE_OK;
+
+ *protocol_done = FALSE;
+
+ if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
+ /* We already are connected, get back. This may happen when the connect
+ worked fine in the first call, like when we connect to a local server
+ or proxy. Note that we don't know if the protocol is actually done.
+
+ Unless this protocol doesn't have any protocol-connect callback, as
+ then we know we're done. */
+ if(!conn->handler->connecting)
+ *protocol_done = TRUE;
+
+ return CURLE_OK;
+ }
+
+ if(!conn->bits.protoconnstart) {
+
+ result = Curl_proxy_connect(conn);
+ if(result)
+ return result;
+
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
+ (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
+ /* when using an HTTP tunnel proxy, await complete tunnel establishment
+ before proceeding further. Return CURLE_OK so we'll be called again */
+ return CURLE_OK;
+
+ if(conn->handler->connect_it) {
+ /* is there a protocol-specific connect() procedure? */
+
+ /* Call the protocol-specific connect function */
+ result = conn->handler->connect_it(conn, protocol_done);
+ }
+ else
+ *protocol_done = TRUE;
+
+ /* it has started, possibly even completed but that knowledge isn't stored
+ in this bit! */
+ if(!result)
+ conn->bits.protoconnstart = TRUE;
+ }
+
+ return result; /* pass back status */
+}
+
+/*
+ * Helpers for IDNA convertions.
+ */
+static bool is_ASCII_name(const char *hostname)
+{
+ const unsigned char *ch = (const unsigned char*)hostname;
+
+ while(*ch) {
+ if(*ch++ & 0x80)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#ifdef USE_LIBIDN
+/*
+ * Check if characters in hostname is allowed in Top Level Domain.
+ */
+static bool tld_check_name(struct SessionHandle *data,
+ const char *ace_hostname)
+{
+ size_t err_pos;
+ char *uc_name = NULL;
+ int rc;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ const char *tld_errmsg = "<no msg>";
+#else
+ (void)data;
+#endif
+
+ /* Convert (and downcase) ACE-name back into locale's character set */
+ rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
+ if(rc != IDNA_SUCCESS)
+ return FALSE;
+
+ rc = tld_check_lz(uc_name, &err_pos, NULL);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef HAVE_TLD_STRERROR
+ if(rc != TLD_SUCCESS)
+ tld_errmsg = tld_strerror((Tld_rc)rc);
+#endif
+ if(rc == TLD_INVALID)
+ infof(data, "WARNING: %s; pos %u = `%c'/0x%02X\n",
+ tld_errmsg, err_pos, uc_name[err_pos],
+ uc_name[err_pos] & 255);
+ else if(rc != TLD_SUCCESS)
+ infof(data, "WARNING: TLD check for %s failed; %s\n",
+ uc_name, tld_errmsg);
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+ if(uc_name)
+ idn_free(uc_name);
+ if(rc != TLD_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+#endif
+
+/*
+ * Perform any necessary IDN conversion of hostname
+ */
+static void fix_hostname(struct SessionHandle *data,
+ struct connectdata *conn, struct hostname *host)
+{
+ size_t len;
+
+#ifndef USE_LIBIDN
+ (void)data;
+ (void)conn;
+#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void)conn;
+#endif
+
+ /* set the name we use to display the host name */
+ host->dispname = host->name;
+
+ len = strlen(host->name);
+ if(host->name[len-1] == '.')
+ /* strip off a single trailing dot if present, primarily for SNI but
+ there's no use for it */
+ host->name[len-1]=0;
+
+ if(!is_ASCII_name(host->name)) {
+#ifdef USE_LIBIDN
+ /*************************************************************
+ * Check name for non-ASCII and convert hostname to ACE form.
+ *************************************************************/
+ if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
+ char *ace_hostname = NULL;
+ int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
+ infof (data, "Input domain encoded as `%s'\n",
+ stringprep_locale_charset ());
+ if(rc != IDNA_SUCCESS)
+ infof(data, "Failed to convert %s to ACE; %s\n",
+ host->name, Curl_idn_strerror(conn,rc));
+ else {
+ /* tld_check_name() displays a warning if the host name contains
+ "illegal" characters for this TLD */
+ (void)tld_check_name(data, ace_hostname);
+
+ host->encalloc = ace_hostname;
+ /* change the name pointer to point to the encoded hostname */
+ host->name = host->encalloc;
+ }
+ }
+#elif defined(USE_WIN32_IDN)
+ /*************************************************************
+ * Check name for non-ASCII and convert hostname to ACE form.
+ *************************************************************/
+ char *ace_hostname = NULL;
+ int rc = curl_win32_idn_to_ascii(host->name, &ace_hostname);
+ if(rc == 0)
+ infof(data, "Failed to convert %s to ACE;\n",
+ host->name);
+ else {
+ host->encalloc = ace_hostname;
+ /* change the name pointer to point to the encoded hostname */
+ host->name = host->encalloc;
+ }
+#else
+ infof(data, "IDN support not present, can't parse Unicode domains\n");
+#endif
+ }
+}
+
+static void llist_dtor(void *user, void *element)
+{
+ (void)user;
+ (void)element;
+ /* Do nothing */
+}
+
+/*
+ * Allocate and initialize a new connectdata object.
+ */
+static struct connectdata *allocate_conn(struct SessionHandle *data)
+{
+ struct connectdata *conn = calloc(1, sizeof(struct connectdata));
+ if(!conn)
+ return NULL;
+
+ conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined
+ already from start to avoid NULL
+ situations and checks */
+
+ /* and we setup a few fields in case we end up actually using this struct */
+
+ conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->connection_id = -1; /* no ID */
+ conn->port = -1; /* unknown at this point */
+ conn->remote_port = -1; /* unknown */
+
+ /* Default protocol-independent behavior doesn't support persistent
+ connections, so we set this to force-close. Protocols that support
+ this need to set this to FALSE in their "curl_do" functions. */
+ connclose(conn, "Default to force-close");
+
+ /* Store creation time to help future close decision making */
+ conn->created = Curl_tvnow();
+
+ conn->data = data; /* Setup the association between this connection
+ and the SessionHandle */
+
+ conn->proxytype = data->set.proxytype; /* type */
+
+#ifdef CURL_DISABLE_PROXY
+
+ conn->bits.proxy = FALSE;
+ conn->bits.httpproxy = FALSE;
+ conn->bits.proxy_user_passwd = FALSE;
+ conn->bits.tunnel_proxy = FALSE;
+
+#else /* CURL_DISABLE_PROXY */
+
+ /* note that these two proxy bits are now just on what looks to be
+ requested, they may be altered down the road */
+ conn->bits.proxy = (data->set.str[STRING_PROXY] &&
+ *data->set.str[STRING_PROXY])?TRUE:FALSE;
+ conn->bits.httpproxy = (conn->bits.proxy &&
+ (conn->proxytype == CURLPROXY_HTTP ||
+ conn->proxytype == CURLPROXY_HTTP_1_0))?TRUE:FALSE;
+ conn->bits.proxy_user_passwd =
+ (NULL != data->set.str[STRING_PROXYUSERNAME])?TRUE:FALSE;
+ conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
+
+#endif /* CURL_DISABLE_PROXY */
+
+ conn->bits.user_passwd = (NULL != data->set.str[STRING_USERNAME])?TRUE:FALSE;
+ conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
+ conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
+
+ conn->verifypeer = data->set.ssl.verifypeer;
+ conn->verifyhost = data->set.ssl.verifyhost;
+
+ conn->ip_version = data->set.ipver;
+
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+ conn->ntlm_auth_hlpr_pid = 0;
+ conn->challenge_header = NULL;
+ conn->response_header = NULL;
+#endif
+
+ if(Curl_multi_pipeline_enabled(data->multi) &&
+ !conn->master_buffer) {
+ /* Allocate master_buffer to be used for pipelining */
+ conn->master_buffer = calloc(BUFSIZE, sizeof (char));
+ if(!conn->master_buffer)
+ goto error;
+ }
+
+ /* Initialize the pipeline lists */
+ conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
+ conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
+ if(!conn->send_pipe || !conn->recv_pipe)
+ goto error;
+
+#ifdef HAVE_GSSAPI
+ conn->data_prot = PROT_CLEAR;
+#endif
+
+ /* Store the local bind parameters that will be used for this connection */
+ if(data->set.str[STRING_DEVICE]) {
+ conn->localdev = strdup(data->set.str[STRING_DEVICE]);
+ if(!conn->localdev)
+ goto error;
+ }
+ conn->localportrange = data->set.localportrange;
+ conn->localport = data->set.localport;
+
+ /* the close socket stuff needs to be copied to the connection struct as
+ it may live on without (this specific) SessionHandle */
+ conn->fclosesocket = data->set.fclosesocket;
+ conn->closesocket_client = data->set.closesocket_client;
+
+ return conn;
+ error:
+
+ Curl_llist_destroy(conn->send_pipe, NULL);
+ Curl_llist_destroy(conn->recv_pipe, NULL);
+
+ conn->send_pipe = NULL;
+ conn->recv_pipe = NULL;
+
+ Curl_safefree(conn->master_buffer);
+ Curl_safefree(conn->localdev);
+ Curl_safefree(conn);
+ return NULL;
+}
+
+static CURLcode findprotocol(struct SessionHandle *data,
+ struct connectdata *conn,
+ const char *protostr)
+{
+ const struct Curl_handler * const *pp;
+ const struct Curl_handler *p;
+
+ /* Scan protocol handler table and match against 'protostr' to set a few
+ variables based on the URL. Now that the handler may be changed later
+ when the protocol specific setup function is called. */
+ for(pp = protocols; (p = *pp) != NULL; pp++) {
+ if(Curl_raw_equal(p->scheme, protostr)) {
+ /* Protocol found in table. Check if allowed */
+ if(!(data->set.allowed_protocols & p->protocol))
+ /* nope, get out */
+ break;
+
+ /* it is allowed for "normal" request, now do an extra check if this is
+ the result of a redirect */
+ if(data->state.this_is_a_follow &&
+ !(data->set.redir_protocols & p->protocol))
+ /* nope, get out */
+ break;
+
+ /* Perform setup complement if some. */
+ conn->handler = conn->given = p;
+
+ /* 'port' and 'remote_port' are set in setup_connection_internals() */
+ return CURLE_OK;
+ }
+ }
+
+
+ /* The protocol was not found in the table, but we don't have to assign it
+ to anything since it is already assigned to a dummy-struct in the
+ create_conn() function when the connectdata struct is allocated. */
+ failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
+ protostr);
+
+ return CURLE_UNSUPPORTED_PROTOCOL;
+}
+
+/*
+ * Parse URL and fill in the relevant members of the connection struct.
+ */
+static CURLcode parseurlandfillconn(struct SessionHandle *data,
+ struct connectdata *conn,
+ bool *prot_missing,
+ char **userp, char **passwdp,
+ char **optionsp)
+{
+ char *at;
+ char *fragment;
+ char *path = data->state.path;
+ char *query;
+ int rc;
+ char protobuf[16] = "";
+ const char *protop = "";
+ CURLcode result;
+ bool rebuild_url = FALSE;
+
+ *prot_missing = FALSE;
+
+ /*************************************************************
+ * Parse the URL.
+ *
+ * We need to parse the url even when using the proxy, because we will need
+ * the hostname and port in case we are trying to SSL connect through the
+ * proxy -- and we don't know if we will need to use SSL until we parse the
+ * url ...
+ ************************************************************/
+ if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
+ protobuf, path)) &&
+ Curl_raw_equal(protobuf, "file")) {
+ if(path[0] == '/' && path[1] == '/') {
+ /* Allow omitted hostname (e.g. file:/<path>). This is not strictly
+ * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
+ * file://localhost/<path> is similar to how other schemes treat missing
+ * hostnames. See RFC 1808. */
+
+ /* This cannot be done with strcpy() in a portable manner, since the
+ memory areas overlap! */
+ memmove(path, path + 2, strlen(path + 2)+1);
+ }
+ /*
+ * we deal with file://<host>/<path> differently since it supports no
+ * hostname other than "localhost" and "127.0.0.1", which is unique among
+ * the URL protocols specified in RFC 1738
+ */
+ if(path[0] != '/') {
+ /* the URL included a host name, we ignore host names in file:// URLs
+ as the standards don't define what to do with them */
+ char *ptr=strchr(path, '/');
+ if(ptr) {
+ /* there was a slash present
+
+ RFC1738 (section 3.1, page 5) says:
+
+ The rest of the locator consists of data specific to the scheme,
+ and is known as the "url-path". It supplies the details of how the
+ specified resource can be accessed. Note that the "/" between the
+ host (or port) and the url-path is NOT part of the url-path.
+
+ As most agents use file://localhost/foo to get '/foo' although the
+ slash preceding foo is a separator and not a slash for the path,
+ a URL as file://localhost//foo must be valid as well, to refer to
+ the same file with an absolute path.
+ */
+
+ if(ptr[1] && ('/' == ptr[1]))
+ /* if there was two slashes, we skip the first one as that is then
+ used truly as a separator */
+ ptr++;
+
+ /* This cannot be made with strcpy, as the memory chunks overlap! */
+ memmove(path, ptr, strlen(ptr)+1);
+ }
+ }
+
+ protop = "file"; /* protocol string */
+ }
+ else {
+ /* clear path */
+ path[0]=0;
+
+ if(2 > sscanf(data->change.url,
+ "%15[^\n:]://%[^\n/?]%[^\n]",
+ protobuf,
+ conn->host.name, path)) {
+
+ /*
+ * The URL was badly formatted, let's try the browser-style _without_
+ * protocol specified like 'http://'.
+ */
+ rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
+ if(1 > rc) {
+ /*
+ * We couldn't even get this format.
+ * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is
+ * assigned, but the return value is EOF!
+ */
+#if defined(__DJGPP__) && (DJGPP_MINOR == 4)
+ if(!(rc == -1 && *conn->host.name))
+#endif
+ {
+ failf(data, "<url> malformed");
+ return CURLE_URL_MALFORMAT;
+ }
+ }
+
+ /*
+ * Since there was no protocol part specified, we guess what protocol it
+ * is based on the first letters of the server name.
+ */
+
+ /* Note: if you add a new protocol, please update the list in
+ * lib/version.c too! */
+
+ if(checkprefix("FTP.", conn->host.name))
+ protop = "ftp";
+ else if(checkprefix("DICT.", conn->host.name))
+ protop = "DICT";
+ else if(checkprefix("LDAP.", conn->host.name))
+ protop = "LDAP";
+ else if(checkprefix("IMAP.", conn->host.name))
+ protop = "IMAP";
+ else if(checkprefix("SMTP.", conn->host.name))
+ protop = "smtp";
+ else if(checkprefix("POP3.", conn->host.name))
+ protop = "pop3";
+ else {
+ protop = "http";
+ }
+
+ *prot_missing = TRUE; /* not given in URL */
+ }
+ else
+ protop = protobuf;
+ }
+
+ /* We search for '?' in the host name (but only on the right side of a
+ * @-letter to allow ?-letters in username and password) to handle things
+ * like http://example.com?param= (notice the missing '/').
+ */
+ at = strchr(conn->host.name, '@');
+ if(at)
+ query = strchr(at+1, '?');
+ else
+ query = strchr(conn->host.name, '?');
+
+ if(query) {
+ /* We must insert a slash before the '?'-letter in the URL. If the URL had
+ a slash after the '?', that is where the path currently begins and the
+ '?string' is still part of the host name.
+
+ We must move the trailing part from the host name and put it first in
+ the path. And have it all prefixed with a slash.
+ */
+
+ size_t hostlen = strlen(query);
+ size_t pathlen = strlen(path);
+
+ /* move the existing path plus the zero byte forward, to make room for
+ the host-name part */
+ memmove(path+hostlen+1, path, pathlen+1);
+
+ /* now copy the trailing host part in front of the existing path */
+ memcpy(path+1, query, hostlen);
+
+ path[0]='/'; /* prepend the missing slash */
+ rebuild_url = TRUE;
+
+ *query=0; /* now cut off the hostname at the ? */
+ }
+ else if(!path[0]) {
+ /* if there's no path set, use a single slash */
+ strcpy(path, "/");
+ rebuild_url = TRUE;
+ }
+
+ /* If the URL is malformatted (missing a '/' after hostname before path) we
+ * insert a slash here. The only letter except '/' we accept to start a path
+ * is '?'.
+ */
+ if(path[0] == '?') {
+ /* We need this function to deal with overlapping memory areas. We know
+ that the memory area 'path' points to is 'urllen' bytes big and that
+ is bigger than the path. Use +1 to move the zero byte too. */
+ memmove(&path[1], path, strlen(path)+1);
+ path[0] = '/';
+ rebuild_url = TRUE;
+ }
+ else {
+ /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
+ char *newp = Curl_dedotdotify(path);
+ if(!newp)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(strcmp(newp, path)) {
+ rebuild_url = TRUE;
+ free(data->state.pathbuffer);
+ data->state.pathbuffer = newp;
+ data->state.path = newp;
+ path = newp;
+ }
+ else
+ free(newp);
+ }
+
+ /*
+ * "rebuild_url" means that one or more URL components have been modified so
+ * we need to generate an updated full version. We need the corrected URL
+ * when communicating over HTTP proxy and we don't know at this point if
+ * we're using a proxy or not.
+ */
+ if(rebuild_url) {
+ char *reurl;
+
+ size_t plen = strlen(path); /* new path, should be 1 byte longer than
+ the original */
+ size_t urllen = strlen(data->change.url); /* original URL length */
+
+ size_t prefixlen = strlen(conn->host.name);
+
+ if(!*prot_missing)
+ prefixlen += strlen(protop) + strlen("://");
+
+ reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
+ if(!reurl)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* copy the prefix */
+ memcpy(reurl, data->change.url, prefixlen);
+
+ /* append the trailing piece + zerobyte */
+ memcpy(&reurl[prefixlen], path, plen + 1);
+
+ /* possible free the old one */
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
+ infof(data, "Rebuilt URL to: %s\n", reurl);
+
+ data->change.url = reurl;
+ data->change.url_alloc = TRUE; /* free this later */
+ }
+
+ /*
+ * Parse the login details from the URL and strip them out of
+ * the host name
+ */
+ result = parse_url_login(data, conn, userp, passwdp, optionsp);
+ if(result != CURLE_OK)
+ return result;
+
+ if(conn->host.name[0] == '[') {
+ /* This looks like an IPv6 address literal. See if there is an address
+ scope if there is no location header */
+ char *percent = strchr(conn->host.name, '%');
+ if(percent) {
+ unsigned int identifier_offset = 3;
+ char *endp;
+ unsigned long scope;
+ if(strncmp("%25", percent, 3) != 0) {
+ infof(data,
+ "Please URL encode %% as %%25, see RFC 6874.\n");
+ identifier_offset = 1;
+ }
+ scope = strtoul(percent + identifier_offset, &endp, 10);
+ if(*endp == ']') {
+ /* The address scope was well formed. Knock it out of the
+ hostname. */
+ memmove(percent, endp, strlen(endp)+1);
+ conn->scope = (unsigned int)scope;
+ }
+ else {
+ /* Zone identifier is not numeric */
+#if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX)
+ char ifname[IFNAMSIZ + 2];
+ char *square_bracket;
+ unsigned int scopeidx = 0;
+ strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2);
+ /* Ensure nullbyte termination */
+ ifname[IFNAMSIZ + 1] = '\0';
+ square_bracket = strchr(ifname, ']');
+ if(square_bracket) {
+ /* Remove ']' */
+ *square_bracket = '\0';
+ scopeidx = if_nametoindex(ifname);
+ if(scopeidx == 0) {
+ infof(data, "Invalid network interface: %s; %s\n", ifname,
+ strerror(errno));
+ }
+ }
+ if(scopeidx > 0) {
+ /* Remove zone identifier from hostname */
+ memmove(percent,
+ percent + identifier_offset + strlen(ifname),
+ identifier_offset + strlen(ifname));
+ conn->scope = scopeidx;
+ }
+ else
+#endif /* HAVE_NET_IF_H && IFNAMSIZ */
+ infof(data, "Invalid IPv6 address format\n");
+ }
+ }
+ }
+
+ if(data->set.scope)
+ /* Override any scope that was set above. */
+ conn->scope = data->set.scope;
+
+ /* Remove the fragment part of the path. Per RFC 2396, this is always the
+ last part of the URI. We are looking for the first '#' so that we deal
+ gracefully with non conformant URI such as http://example.com#foo#bar. */
+ fragment = strchr(path, '#');
+ if(fragment) {
+ *fragment = 0;
+
+ /* we know the path part ended with a fragment, so we know the full URL
+ string does too and we need to cut it off from there so it isn't used
+ over proxy */
+ fragment = strchr(data->change.url, '#');
+ if(fragment)
+ *fragment = 0;
+ }
+
+ /*
+ * So if the URL was A://B/C#D,
+ * protop is A
+ * conn->host.name is B
+ * data->state.path is /C
+ */
+
+ return findprotocol(data, conn, protop);
+}
+
+/*
+ * If we're doing a resumed transfer, we need to setup our stuff
+ * properly.
+ */
+static CURLcode setup_range(struct SessionHandle *data)
+{
+ struct UrlState *s = &data->state;
+ s->resume_from = data->set.set_resume_from;
+ if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
+ if(s->rangestringalloc)
+ free(s->range);
+
+ if(s->resume_from)
+ s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
+ else
+ s->range = strdup(data->set.str[STRING_SET_RANGE]);
+
+ s->rangestringalloc = (s->range)?TRUE:FALSE;
+
+ if(!s->range)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* tell ourselves to fetch this range */
+ s->use_range = TRUE; /* enable range download */
+ }
+ else
+ s->use_range = FALSE; /* disable range download */
+
+ return CURLE_OK;
+}
+
+
+/*
+ * setup_connection_internals() -
+ *
+ * Setup connection internals specific to the requested protocol in the
+ * SessionHandle. This is inited and setup before the connection is made but
+ * is about the particular protocol that is to be used.
+ *
+ * This MUST get called after proxy magic has been figured out.
+ */
+static CURLcode setup_connection_internals(struct connectdata *conn)
+{
+ const struct Curl_handler * p;
+ CURLcode result;
+ struct SessionHandle *data = conn->data;
+
+ /* in some case in the multi state-machine, we go back to the CONNECT state
+ and then a second (or third or...) call to this function will be made
+ without doing a DISCONNECT or DONE in between (since the connection is
+ yet in place) and therefore this function needs to first make sure
+ there's no lingering previous data allocated. */
+ Curl_free_request_state(data);
+
+ memset(&data->req, 0, sizeof(struct SingleRequest));
+ data->req.maxdownload = -1;
+
+ conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
+
+ /* Perform setup complement if some. */
+ p = conn->handler;
+
+ if(p->setup_connection) {
+ result = (*p->setup_connection)(conn);
+
+ if(result != CURLE_OK)
+ return result;
+
+ p = conn->handler; /* May have changed. */
+ }
+
+ if(conn->port < 0)
+ /* we check for -1 here since if proxy was detected already, this
+ was very likely already set to the proxy port */
+ conn->port = p->defport;
+
+ /* only if remote_port was not already parsed off the URL we use the
+ default port number */
+ if(conn->remote_port < 0)
+ conn->remote_port = (unsigned short)conn->given->defport;
+
+ return CURLE_OK;
+}
+
+/*
+ * Curl_free_request_state() should free temp data that was allocated in the
+ * SessionHandle for this single request.
+ */
+
+void Curl_free_request_state(struct SessionHandle *data)
+{
+ Curl_safefree(data->req.protop);
+ Curl_safefree(data->req.newurl);
+}
+
+
+#ifndef CURL_DISABLE_PROXY
+/****************************************************************
+* Checks if the host is in the noproxy list. returns true if it matches
+* and therefore the proxy should NOT be used.
+****************************************************************/
+static bool check_noproxy(const char* name, const char* no_proxy)
+{
+ /* no_proxy=domain1.dom,host.domain2.dom
+ * (a comma-separated list of hosts which should
+ * not be proxied, or an asterisk to override
+ * all proxy variables)
+ */
+ size_t tok_start;
+ size_t tok_end;
+ const char* separator = ", ";
+ size_t no_proxy_len;
+ size_t namelen;
+ char *endptr;
+
+ if(no_proxy && no_proxy[0]) {
+ if(Curl_raw_equal("*", no_proxy)) {
+ return TRUE;
+ }
+
+ /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ no_proxy_len = strlen(no_proxy);
+ endptr = strchr(name, ':');
+ if(endptr)
+ namelen = endptr - name;
+ else
+ namelen = strlen(name);
+
+ for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
+ while(tok_start < no_proxy_len &&
+ strchr(separator, no_proxy[tok_start]) != NULL) {
+ /* Look for the beginning of the token. */
+ ++tok_start;
+ }
+
+ if(tok_start == no_proxy_len)
+ break; /* It was all trailing separator chars, no more tokens. */
+
+ for(tok_end = tok_start; tok_end < no_proxy_len &&
+ strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
+ /* Look for the end of the token. */
+ ;
+
+ /* To match previous behaviour, where it was necessary to specify
+ * ".local.com" to prevent matching "notlocal.com", we will leave
+ * the '.' off.
+ */
+ if(no_proxy[tok_start] == '.')
+ ++tok_start;
+
+ if((tok_end - tok_start) <= namelen) {
+ /* Match the last part of the name to the domain we are checking. */
+ const char *checkn = name + namelen - (tok_end - tok_start);
+ if(Curl_raw_nequal(no_proxy + tok_start, checkn,
+ tok_end - tok_start)) {
+ if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
+ /* We either have an exact match, or the previous character is a .
+ * so it is within the same domain, so no proxy for this host.
+ */
+ return TRUE;
+ }
+ }
+ } /* if((tok_end - tok_start) <= namelen) */
+ } /* for(tok_start = 0; tok_start < no_proxy_len;
+ tok_start = tok_end + 1) */
+ } /* NO_PROXY was specified and it wasn't just an asterisk */
+
+ return FALSE;
+}
+
+/****************************************************************
+* Detect what (if any) proxy to use. Remember that this selects a host
+* name and is not limited to HTTP proxies only.
+* The returned pointer must be freed by the caller (unless NULL)
+****************************************************************/
+static char *detect_proxy(struct connectdata *conn)
+{
+ char *proxy = NULL;
+
+#ifndef CURL_DISABLE_HTTP
+ /* If proxy was not specified, we check for default proxy environment
+ * variables, to enable i.e Lynx compliance:
+ *
+ * http_proxy=http://some.server.dom:port/
+ * https_proxy=http://some.server.dom:port/
+ * ftp_proxy=http://some.server.dom:port/
+ * no_proxy=domain1.dom,host.domain2.dom
+ * (a comma-separated list of hosts which should
+ * not be proxied, or an asterisk to override
+ * all proxy variables)
+ * all_proxy=http://some.server.dom:port/
+ * (seems to exist for the CERN www lib. Probably
+ * the first to check for.)
+ *
+ * For compatibility, the all-uppercase versions of these variables are
+ * checked if the lowercase versions don't exist.
+ */
+ char *no_proxy=NULL;
+ char proxy_env[128];
+
+ no_proxy=curl_getenv("no_proxy");
+ if(!no_proxy)
+ no_proxy=curl_getenv("NO_PROXY");
+
+ if(!check_noproxy(conn->host.name, no_proxy)) {
+ /* It was not listed as without proxy */
+ const char *protop = conn->handler->scheme;
+ char *envp = proxy_env;
+ char *prox;
+
+ /* Now, build <protocol>_proxy and check for such a one to use */
+ while(*protop)
+ *envp++ = (char)tolower((int)*protop++);
+
+ /* append _proxy */
+ strcpy(envp, "_proxy");
+
+ /* read the protocol proxy: */
+ prox=curl_getenv(proxy_env);
+
+ /*
+ * We don't try the uppercase version of HTTP_PROXY because of
+ * security reasons:
+ *
+ * When curl is used in a webserver application
+ * environment (cgi or php), this environment variable can
+ * be controlled by the web server user by setting the
+ * http header 'Proxy:' to some value.
+ *
+ * This can cause 'internal' http/ftp requests to be
+ * arbitrarily redirected by any external attacker.
+ */
+ if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
+ /* There was no lowercase variable, try the uppercase version: */
+ Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
+ prox=curl_getenv(proxy_env);
+ }
+
+ if(prox && *prox) { /* don't count "" strings */
+ proxy = prox; /* use this */
+ }
+ else {
+ proxy = curl_getenv("all_proxy"); /* default proxy to use */
+ if(!proxy)
+ proxy=curl_getenv("ALL_PROXY");
+ }
+ } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
+ non-proxy */
+ if(no_proxy)
+ free(no_proxy);
+
+#else /* !CURL_DISABLE_HTTP */
+
+ (void)conn;
+#endif /* CURL_DISABLE_HTTP */
+
+ return proxy;
+}
+
+/*
+ * If this is supposed to use a proxy, we need to figure out the proxy
+ * host name, so that we can re-use an existing connection
+ * that may exist registered to the same proxy host.
+ * proxy will be freed before this function returns.
+ */
+static CURLcode parse_proxy(struct SessionHandle *data,
+ struct connectdata *conn, char *proxy)
+{
+ char *prox_portno;
+ char *endofprot;
+
+ /* We use 'proxyptr' to point to the proxy name from now on... */
+ char *proxyptr;
+ char *portptr;
+ char *atsign;
+
+ /* We do the proxy host string parsing here. We want the host name and the
+ * port name. Accept a protocol:// prefix
+ */
+
+ /* Parse the protocol part if present */
+ endofprot = strstr(proxy, "://");
+ if(endofprot) {
+ proxyptr = endofprot+3;
+ if(checkprefix("socks5h", proxy))
+ conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
+ else if(checkprefix("socks5", proxy))
+ conn->proxytype = CURLPROXY_SOCKS5;
+ else if(checkprefix("socks4a", proxy))
+ conn->proxytype = CURLPROXY_SOCKS4A;
+ else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
+ conn->proxytype = CURLPROXY_SOCKS4;
+ /* Any other xxx:// : change to http proxy */
+ }
+ else
+ proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
+
+ /* Is there a username and password given in this proxy url? */
+ atsign = strchr(proxyptr, '@');
+ if(atsign) {
+ CURLcode res = CURLE_OK;
+ char *proxyuser = NULL;
+ char *proxypasswd = NULL;
+
+ res = parse_login_details(proxyptr, atsign - proxyptr,
+ &proxyuser, &proxypasswd, NULL);
+ if(!res) {
+ /* found user and password, rip them out. note that we are
+ unescaping them, as there is otherwise no way to have a
+ username or password with reserved characters like ':' in
+ them. */
+ Curl_safefree(conn->proxyuser);
+ if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
+ conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
+ else
+ conn->proxyuser = strdup("");
+
+ if(!conn->proxyuser)
+ res = CURLE_OUT_OF_MEMORY;
+ else {
+ Curl_safefree(conn->proxypasswd);
+ if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
+ conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+ else
+ conn->proxypasswd = strdup("");
+
+ if(!conn->proxypasswd)
+ res = CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!res) {
+ conn->bits.proxy_user_passwd = TRUE; /* enable it */
+ atsign++; /* the right side of the @-letter */
+
+ if(atsign)
+ proxyptr = atsign; /* now use this instead */
+ else
+ res = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ Curl_safefree(proxyuser);
+ Curl_safefree(proxypasswd);
+
+ if(res)
+ return res;
+ }
+
+ /* start scanning for port number at this point */
+ portptr = proxyptr;
+
+ /* detect and extract RFC6874-style IPv6-addresses */
+ if(*proxyptr == '[') {
+ char *ptr = ++proxyptr; /* advance beyond the initial bracket */
+ while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
+ ptr++;
+ if(*ptr == '%') {
+ /* There might be a zone identifier */
+ if(strncmp("%25", ptr, 3))
+ infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
+ ptr++;
+ /* Allow unresered characters as defined in RFC 3986 */
+ while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
+ (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
+ ptr++;
+ }
+ if(*ptr == ']')
+ /* yeps, it ended nicely with a bracket as well */
+ *ptr++ = 0;
+ else
+ infof(data, "Invalid IPv6 address format\n");
+ portptr = ptr;
+ /* Note that if this didn't end with a bracket, we still advanced the
+ * proxyptr first, but I can't see anything wrong with that as no host
+ * name nor a numeric can legally start with a bracket.
+ */
+ }
+
+ /* Get port number off proxy.server.com:1080 */
+ prox_portno = strchr(portptr, ':');
+ if(prox_portno) {
+ *prox_portno = 0x0; /* cut off number from host name */
+ prox_portno ++;
+ /* now set the local port number */
+ conn->port = strtol(prox_portno, NULL, 10);
+ }
+ else {
+ if(proxyptr[0]=='/')
+ /* If the first character in the proxy string is a slash, fail
+ immediately. The following code will otherwise clear the string which
+ will lead to code running as if no proxy was set! */
+ return CURLE_COULDNT_RESOLVE_PROXY;
+
+ /* without a port number after the host name, some people seem to use
+ a slash so we strip everything from the first slash */
+ atsign = strchr(proxyptr, '/');
+ if(atsign)
+ *atsign = 0x0; /* cut off path part from host name */
+
+ if(data->set.proxyport)
+ /* None given in the proxy string, then get the default one if it is
+ given */
+ conn->port = data->set.proxyport;
+ }
+
+ /* now, clone the cleaned proxy host name */
+ conn->proxy.rawalloc = strdup(proxyptr);
+ conn->proxy.name = conn->proxy.rawalloc;
+
+ if(!conn->proxy.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+/*
+ * Extract the user and password from the authentication string
+ */
+static CURLcode parse_proxy_auth(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ char proxyuser[MAX_CURL_USER_LENGTH]="";
+ char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
+
+ if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
+ strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
+ MAX_CURL_USER_LENGTH);
+ proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/
+ }
+ if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
+ strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
+ MAX_CURL_PASSWORD_LENGTH);
+ proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
+ }
+
+ conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
+ if(!conn->proxyuser)
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+ if(!conn->proxypasswd)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+#endif /* CURL_DISABLE_PROXY */
+
+/*
+ * parse_url_login()
+ *
+ * Parse the login details (user name, password and options) from the URL and
+ * strip them out of the host name
+ *
+ * Inputs: data->set.use_netrc (CURLOPT_NETRC)
+ * conn->host.name
+ *
+ * Outputs: (almost :- all currently undefined)
+ * conn->bits.user_passwd - non-zero if non-default passwords exist
+ * user - non-zero length if defined
+ * passwd - non-zero length if defined
+ * options - non-zero length if defined
+ * conn->host.name - remove user name and password
+ */
+static CURLcode parse_url_login(struct SessionHandle *data,
+ struct connectdata *conn,
+ char **user, char **passwd, char **options)
+{
+ CURLcode result = CURLE_OK;
+ char *userp = NULL;
+ char *passwdp = NULL;
+ char *optionsp = NULL;
+
+ /* At this point, we're hoping all the other special cases have
+ * been taken care of, so conn->host.name is at most
+ * [user[:password][;options]]@]hostname
+ *
+ * We need somewhere to put the embedded details, so do that first.
+ */
+
+ char *ptr = strchr(conn->host.name, '@');
+ char *login = conn->host.name;
+
+ DEBUGASSERT(!**user);
+ DEBUGASSERT(!**passwd);
+ DEBUGASSERT(!**options);
+
+ if(!ptr)
+ goto out;
+
+ /* We will now try to extract the
+ * possible login information in a string like:
+ * ftp://user:password@ftp.my.site:8021/README */
+ conn->host.name = ++ptr;
+
+ /* So the hostname is sane. Only bother interpreting the
+ * results if we could care. It could still be wasted
+ * work because it might be overtaken by the programmatically
+ * set user/passwd, but doing that first adds more cases here :-(
+ */
+
+ if(data->set.use_netrc == CURL_NETRC_REQUIRED)
+ goto out;
+
+ /* We could use the login information in the URL so extract it */
+ result = parse_login_details(login, ptr - login - 1,
+ &userp, &passwdp, &optionsp);
+ if(result != CURLE_OK)
+ goto out;
+
+ if(userp) {
+ char *newname;
+
+ /* We have a user in the URL */
+ conn->bits.userpwd_in_url = TRUE;
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+
+ /* Decode the user */
+ newname = curl_easy_unescape(data, userp, 0, NULL);
+ if(!newname) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ free(*user);
+ *user = newname;
+ }
+
+ if(passwdp) {
+ /* We have a password in the URL so decode it */
+ char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
+ if(!newpasswd) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ free(*passwd);
+ *passwd = newpasswd;
+ }
+
+ if(optionsp) {
+ /* We have an options list in the URL so decode it */
+ char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
+ if(!newoptions) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ free(*options);
+ *options = newoptions;
+ }
+
+
+ out:
+
+ Curl_safefree(userp);
+ Curl_safefree(passwdp);
+ Curl_safefree(optionsp);
+
+ return result;
+}
+
+/*
+ * parse_login_details()
+ *
+ * This is used to parse a login string for user name, password and options in
+ * the following formats:
+ *
+ * user
+ * user:password
+ * user:password;options
+ * user;options
+ * user;options:password
+ * :password
+ * :password;options
+ * ;options
+ * ;options:password
+ *
+ * Parameters:
+ *
+ * login [in] - The login string.
+ * len [in] - The length of the login string.
+ * userp [in/out] - The address where a pointer to newly allocated memory
+ * holding the user will be stored upon completion.
+ * passdwp [in/out] - The address where a pointer to newly allocated memory
+ * holding the password will be stored upon completion.
+ * optionsp [in/out] - The address where a pointer to newly allocated memory
+ * holding the options will be stored upon completion.
+ *
+ * Returns CURLE_OK on success.
+ */
+static CURLcode parse_login_details(const char *login, const size_t len,
+ char **userp, char **passwdp,
+ char **optionsp)
+{
+ CURLcode result = CURLE_OK;
+ char *ubuf = NULL;
+ char *pbuf = NULL;
+ char *obuf = NULL;
+ const char *psep = NULL;
+ const char *osep = NULL;
+ size_t ulen;
+ size_t plen;
+ size_t olen;
+
+ /* Attempt to find the password separator */
+ if(passwdp) {
+ psep = strchr(login, ':');
+
+ /* Within the constraint of the login string */
+ if(psep >= login + len)
+ psep = NULL;
+ }
+
+ /* Attempt to find the options separator */
+ if(optionsp) {
+ osep = strchr(login, ';');
+
+ /* Within the constraint of the login string */
+ if(osep >= login + len)
+ osep = NULL;
+ }
+
+ /* Calculate the portion lengths */
+ ulen = (psep ?
+ (size_t)(osep && psep > osep ? osep - login : psep - login) :
+ (osep ? (size_t)(osep - login) : len));
+ plen = (psep ?
+ (osep && osep > psep ? (size_t)(osep - psep) :
+ (size_t)(login + len - psep)) - 1 : 0);
+ olen = (osep ?
+ (psep && psep > osep ? (size_t)(psep - osep) :
+ (size_t)(login + len - osep)) - 1 : 0);
+
+ /* Allocate the user portion buffer */
+ if(userp && ulen) {
+ ubuf = malloc(ulen + 1);
+ if(!ubuf)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Allocate the password portion buffer */
+ if(!result && passwdp && plen) {
+ pbuf = malloc(plen + 1);
+ if(!pbuf) {
+ Curl_safefree(ubuf);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* Allocate the options portion buffer */
+ if(!result && optionsp && olen) {
+ obuf = malloc(olen + 1);
+ if(!obuf) {
+ Curl_safefree(pbuf);
+ Curl_safefree(ubuf);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ if(!result) {
+ /* Store the user portion if necessary */
+ if(ubuf) {
+ memcpy(ubuf, login, ulen);
+ ubuf[ulen] = '\0';
+ Curl_safefree(*userp);
+ *userp = ubuf;
+ }
+
+ /* Store the password portion if necessary */
+ if(pbuf) {
+ memcpy(pbuf, psep + 1, plen);
+ pbuf[plen] = '\0';
+ Curl_safefree(*passwdp);
+ *passwdp = pbuf;
+ }
+
+ /* Store the options portion if necessary */
+ if(obuf) {
+ memcpy(obuf, osep + 1, olen);
+ obuf[olen] = '\0';
+ Curl_safefree(*optionsp);
+ *optionsp = obuf;
+ }
+ }
+
+ return result;
+}
+
+/*************************************************************
+ * Figure out the remote port number and fix it in the URL
+ *
+ * No matter if we use a proxy or not, we have to figure out the remote
+ * port number of various reasons.
+ *
+ * To be able to detect port number flawlessly, we must not confuse them
+ * IPv6-specified addresses in the [0::1] style. (RFC2732)
+ *
+ * The conn->host.name is currently [user:passwd@]host[:port] where host
+ * could be a hostname, IPv4 address or IPv6 address.
+ *
+ * The port number embedded in the URL is replaced, if necessary.
+ *************************************************************/
+static CURLcode parse_remote_port(struct SessionHandle *data,
+ struct connectdata *conn)
+{
+ char *portptr;
+ char endbracket;
+
+ /* Note that at this point, the IPv6 address cannot contain any scope
+ suffix as that has already been removed in the parseurlandfillconn()
+ function */
+ if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
+ &endbracket)) &&
+ (']' == endbracket)) {
+ /* this is a RFC2732-style specified IP-address */
+ conn->bits.ipv6_ip = TRUE;
+
+ conn->host.name++; /* skip over the starting bracket */
+ portptr = strchr(conn->host.name, ']');
+ if(portptr) {
+ *portptr++ = '\0'; /* zero terminate, killing the bracket */
+ if(':' != *portptr)
+ portptr = NULL; /* no port number available */
+ }
+ }
+ else {
+#ifdef ENABLE_IPV6
+ struct in6_addr in6;
+ if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) {
+ /* This is a numerical IPv6 address, meaning this is a wrongly formatted
+ URL */
+ failf(data, "IPv6 numerical address used in URL without brackets");
+ return CURLE_URL_MALFORMAT;
+ }
+#endif
+
+ portptr = strrchr(conn->host.name, ':');
+ }
+
+ if(data->set.use_port && data->state.allow_port) {
+ /* if set, we use this and ignore the port possibly given in the URL */
+ conn->remote_port = (unsigned short)data->set.use_port;
+ if(portptr)
+ *portptr = '\0'; /* cut off the name there anyway - if there was a port
+ number - since the port number is to be ignored! */
+ if(conn->bits.httpproxy) {
+ /* we need to create new URL with the new port number */
+ char *url;
+ char type[12]="";
+
+ if(conn->bits.type_set)
+ snprintf(type, sizeof(type), ";type=%c",
+ data->set.prefer_ascii?'A':
+ (data->set.ftp_list_only?'D':'I'));
+
+ /*
+ * This synthesized URL isn't always right--suffixes like ;type=A are
+ * stripped off. It would be better to work directly from the original
+ * URL and simply replace the port part of it.
+ */
+ url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
+ conn->bits.ipv6_ip?"[":"", conn->host.name,
+ conn->bits.ipv6_ip?"]":"", conn->remote_port,
+ data->state.slash_removed?"/":"", data->state.path,
+ type);
+ if(!url)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
+ data->change.url = url;
+ data->change.url_alloc = TRUE;
+ }
+ }
+ else if(portptr) {
+ /* no CURLOPT_PORT given, extract the one from the URL */
+
+ char *rest;
+ long port;
+
+ port=strtol(portptr+1, &rest, 10); /* Port number must be decimal */
+
+ if((port < 0) || (port > 0xffff)) {
+ /* Single unix standard says port numbers are 16 bits long */
+ failf(data, "Port number out of range");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ else if(rest != &portptr[1]) {
+ *portptr = '\0'; /* cut off the name there */
+ conn->remote_port = curlx_ultous(port);
+ }
+ else
+ /* Browser behavior adaptation. If there's a colon with no digits after,
+ just cut off the name there which makes us ignore the colon and just
+ use the default port. Firefox and Chrome both do that. */
+ *portptr = '\0';
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Override the login details from the URL with that in the CURLOPT_USERPWD
+ * option or a .netrc file, if applicable.
+ */
+static CURLcode override_login(struct SessionHandle *data,
+ struct connectdata *conn,
+ char **userp, char **passwdp, char **optionsp)
+{
+ if(data->set.str[STRING_USERNAME]) {
+ free(*userp);
+ *userp = strdup(data->set.str[STRING_USERNAME]);
+ if(!*userp)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->set.str[STRING_PASSWORD]) {
+ free(*passwdp);
+ *passwdp = strdup(data->set.str[STRING_PASSWORD]);
+ if(!*passwdp)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->set.str[STRING_OPTIONS]) {
+ free(*optionsp);
+ *optionsp = strdup(data->set.str[STRING_OPTIONS]);
+ if(!*optionsp)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ conn->bits.netrc = FALSE;
+ if(data->set.use_netrc != CURL_NETRC_IGNORED) {
+ int ret = Curl_parsenetrc(conn->host.name,
+ userp, passwdp,
+ data->set.str[STRING_NETRC_FILE]);
+ if(ret > 0) {
+ infof(data, "Couldn't find host %s in the "
+ DOT_CHAR "netrc file; using defaults\n",
+ conn->host.name);
+ }
+ else if(ret < 0 ) {
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ /* set bits.netrc TRUE to remember that we got the name from a .netrc
+ file, so that it is safe to use even if we followed a Location: to a
+ different host or similar. */
+ conn->bits.netrc = TRUE;
+
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+ }
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Set the login details so they're available in the connection
+ */
+static CURLcode set_login(struct connectdata *conn,
+ const char *user, const char *passwd,
+ const char *options)
+{
+ CURLcode result = CURLE_OK;
+
+ /* If our protocol needs a password and we have none, use the defaults */
+ if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
+ /* Store the default user */
+ conn->user = strdup(CURL_DEFAULT_USER);
+
+ /* Store the default password */
+ if(conn->user)
+ conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
+ else
+ conn->passwd = NULL;
+
+ /* This is the default password, so DON'T set conn->bits.user_passwd */
+ }
+ else {
+ /* Store the user, zero-length if not set */
+ conn->user = strdup(user);
+
+ /* Store the password (only if user is present), zero-length if not set */
+ if(conn->user)
+ conn->passwd = strdup(passwd);
+ else
+ conn->passwd = NULL;
+ }
+
+ if(!conn->user || !conn->passwd)
+ result = CURLE_OUT_OF_MEMORY;
+
+ /* Store the options, null if not set */
+ if(!result && options[0]) {
+ conn->options = strdup(options);
+
+ if(!conn->options)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ return result;
+}
+
+/*************************************************************
+ * Resolve the address of the server or proxy
+ *************************************************************/
+static CURLcode resolve_server(struct SessionHandle *data,
+ struct connectdata *conn,
+ bool *async)
+{
+ CURLcode result=CURLE_OK;
+ long timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ /*************************************************************
+ * Resolve the name of the server or proxy
+ *************************************************************/
+ if(conn->bits.reuse)
+ /* We're reusing the connection - no need to resolve anything, and
+ fix_hostname() was called already in create_conn() for the re-use
+ case. */
+ *async = FALSE;
+
+ else {
+ /* this is a fresh connect */
+ int rc;
+ struct Curl_dns_entry *hostaddr;
+
+ /* set a pointer to the hostname we display */
+ fix_hostname(data, conn, &conn->host);
+
+ if(!conn->proxy.name || !*conn->proxy.name) {
+ /* If not connecting via a proxy, extract the port from the URL, if it is
+ * there, thus overriding any defaults that might have been set above. */
+ conn->port = conn->remote_port; /* it is the same port */
+
+ /* Resolve target host right on */
+ rc = Curl_resolv_timeout(conn, conn->host.name, (int)conn->port,
+ &hostaddr, timeout_ms);
+ if(rc == CURLRESOLV_PENDING)
+ *async = TRUE;
+
+ else if(rc == CURLRESOLV_TIMEDOUT)
+ result = CURLE_OPERATION_TIMEDOUT;
+
+ else if(!hostaddr) {
+ failf(data, "Couldn't resolve host '%s'", conn->host.dispname);
+ result = CURLE_COULDNT_RESOLVE_HOST;
+ /* don't return yet, we need to clean up the timeout first */
+ }
+ }
+ else {
+ /* This is a proxy that hasn't been resolved yet. */
+
+ /* IDN-fix the proxy name */
+ fix_hostname(data, conn, &conn->proxy);
+
+ /* resolve proxy */
+ rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
+ &hostaddr, timeout_ms);
+
+ if(rc == CURLRESOLV_PENDING)
+ *async = TRUE;
+
+ else if(rc == CURLRESOLV_TIMEDOUT)
+ result = CURLE_OPERATION_TIMEDOUT;
+
+ else if(!hostaddr) {
+ failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
+ result = CURLE_COULDNT_RESOLVE_PROXY;
+ /* don't return yet, we need to clean up the timeout first */
+ }
+ }
+ DEBUGASSERT(conn->dns_entry == NULL);
+ conn->dns_entry = hostaddr;
+ }
+
+ return result;
+}
+
+/*
+ * Cleanup the connection just allocated before we can move along and use the
+ * previously existing one. All relevant data is copied over and old_conn is
+ * ready for freeing once this function returns.
+ */
+static void reuse_conn(struct connectdata *old_conn,
+ struct connectdata *conn)
+{
+ if(old_conn->proxy.rawalloc)
+ free(old_conn->proxy.rawalloc);
+
+ /* free the SSL config struct from this connection struct as this was
+ allocated in vain and is targeted for destruction */
+ Curl_free_ssl_config(&old_conn->ssl_config);
+
+ conn->data = old_conn->data;
+
+ /* get the user+password information from the old_conn struct since it may
+ * be new for this request even when we re-use an existing connection */
+ conn->bits.user_passwd = old_conn->bits.user_passwd;
+ if(conn->bits.user_passwd) {
+ /* use the new user name and password though */
+ Curl_safefree(conn->user);
+ Curl_safefree(conn->passwd);
+ conn->user = old_conn->user;
+ conn->passwd = old_conn->passwd;
+ old_conn->user = NULL;
+ old_conn->passwd = NULL;
+ }
+
+ conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
+ if(conn->bits.proxy_user_passwd) {
+ /* use the new proxy user name and proxy password though */
+ Curl_safefree(conn->proxyuser);
+ Curl_safefree(conn->proxypasswd);
+ conn->proxyuser = old_conn->proxyuser;
+ conn->proxypasswd = old_conn->proxypasswd;
+ old_conn->proxyuser = NULL;
+ old_conn->proxypasswd = NULL;
+ }
+
+ /* host can change, when doing keepalive with a proxy or if the case is
+ different this time etc */
+ Curl_safefree(conn->host.rawalloc);
+ conn->host=old_conn->host;
+
+ /* persist connection info in session handle */
+ Curl_persistconninfo(conn);
+
+ /* re-use init */
+ conn->bits.reuse = TRUE; /* yes, we're re-using here */
+
+ Curl_safefree(old_conn->user);
+ Curl_safefree(old_conn->passwd);
+ Curl_safefree(old_conn->proxyuser);
+ Curl_safefree(old_conn->proxypasswd);
+ Curl_safefree(old_conn->localdev);
+
+ Curl_llist_destroy(old_conn->send_pipe, NULL);
+ Curl_llist_destroy(old_conn->recv_pipe, NULL);
+
+ old_conn->send_pipe = NULL;
+ old_conn->recv_pipe = NULL;
+
+ Curl_safefree(old_conn->master_buffer);
+}
+
+/**
+ * create_conn() sets up a new connectdata struct, or re-uses an already
+ * existing one, and resolves host name.
+ *
+ * if this function returns CURLE_OK and *async is set to TRUE, the resolve
+ * response will be coming asynchronously. If *async is FALSE, the name is
+ * already resolved.
+ *
+ * @param data The sessionhandle pointer
+ * @param in_connect is set to the next connection data pointer
+ * @param async is set TRUE when an async DNS resolution is pending
+ * @see Curl_setup_conn()
+ *
+ * *NOTE* this function assigns the conn->data pointer!
+ */
+
+static CURLcode create_conn(struct SessionHandle *data,
+ struct connectdata **in_connect,
+ bool *async)
+{
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn;
+ struct connectdata *conn_temp = NULL;
+ size_t urllen;
+ char *user = NULL;
+ char *passwd = NULL;
+ char *options = NULL;
+ bool reuse;
+ char *proxy = NULL;
+ bool prot_missing = FALSE;
+ bool no_connections_available = FALSE;
+ bool force_reuse = FALSE;
+ size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
+ size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
+
+ *async = FALSE;
+
+ /*************************************************************
+ * Check input data
+ *************************************************************/
+
+ if(!data->change.url) {
+ result = CURLE_URL_MALFORMAT;
+ goto out;
+ }
+
+ /* First, split up the current URL in parts so that we can use the
+ parts for checking against the already present connections. In order
+ to not have to modify everything at once, we allocate a temporary
+ connection data struct and fill in for comparison purposes. */
+ conn = allocate_conn(data);
+
+ if(!conn) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ /* We must set the return variable as soon as possible, so that our
+ parent can cleanup any possible allocs we may have done before
+ any failure */
+ *in_connect = conn;
+
+ /* This initing continues below, see the comment "Continue connectdata
+ * initialization here" */
+
+ /***********************************************************
+ * We need to allocate memory to store the path in. We get the size of the
+ * full URL to be sure, and we need to make it at least 256 bytes since
+ * other parts of the code will rely on this fact
+ ***********************************************************/
+#define LEAST_PATH_ALLOC 256
+ urllen=strlen(data->change.url);
+ if(urllen < LEAST_PATH_ALLOC)
+ urllen=LEAST_PATH_ALLOC;
+
+ /*
+ * We malloc() the buffers below urllen+2 to make room for 2 possibilities:
+ * 1 - an extra terminating zero
+ * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
+ */
+
+ Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
+
+ data->state.pathbuffer = malloc(urllen+2);
+ if(NULL == data->state.pathbuffer) {
+ result = CURLE_OUT_OF_MEMORY; /* really bad error */
+ goto out;
+ }
+ data->state.path = data->state.pathbuffer;
+
+ conn->host.rawalloc = malloc(urllen+2);
+ if(NULL == conn->host.rawalloc) {
+ Curl_safefree(data->state.pathbuffer);
+ data->state.path = NULL;
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ conn->host.name = conn->host.rawalloc;
+ conn->host.name[0] = 0;
+
+ user = strdup("");
+ passwd = strdup("");
+ options = strdup("");
+ if(!user || !passwd || !options) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
+ &options);
+ if(result != CURLE_OK)
+ goto out;
+
+ /*************************************************************
+ * No protocol part in URL was used, add it!
+ *************************************************************/
+ if(prot_missing) {
+ /* We're guessing prefixes here and if we're told to use a proxy or if
+ we're gonna follow a Location: later or... then we need the protocol
+ part added so that we have a valid URL. */
+ char *reurl;
+
+ reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
+
+ if(!reurl) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if(data->change.url_alloc) {
+ Curl_safefree(data->change.url);
+ data->change.url_alloc = FALSE;
+ }
+
+ data->change.url = reurl;
+ data->change.url_alloc = TRUE; /* free this later */
+ }
+
+ /*************************************************************
+ * If the protocol can't handle url query strings, then cut
+ * off the unhandable part
+ *************************************************************/
+ if((conn->given->flags&PROTOPT_NOURLQUERY)) {
+ char *path_q_sep = strchr(conn->data->state.path, '?');
+ if(path_q_sep) {
+ /* according to rfc3986, allow the query (?foo=bar)
+ also on protocols that can't handle it.
+
+ cut the string-part after '?'
+ */
+
+ /* terminate the string */
+ path_q_sep[0] = 0;
+ }
+ }
+
+ if(data->set.str[STRING_BEARER]) {
+ conn->xoauth2_bearer = strdup(data->set.str[STRING_BEARER]);
+ if(!conn->xoauth2_bearer) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ }
+
+#ifndef CURL_DISABLE_PROXY
+ /*************************************************************
+ * Extract the user and password from the authentication string
+ *************************************************************/
+ if(conn->bits.proxy_user_passwd) {
+ result = parse_proxy_auth(data, conn);
+ if(result != CURLE_OK)
+ goto out;
+ }
+
+ /*************************************************************
+ * Detect what (if any) proxy to use
+ *************************************************************/
+ if(data->set.str[STRING_PROXY]) {
+ proxy = strdup(data->set.str[STRING_PROXY]);
+ /* if global proxy is set, this is it */
+ if(NULL == proxy) {
+ failf(data, "memory shortage");
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ }
+
+ if(data->set.str[STRING_NOPROXY] &&
+ check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
+ if(proxy) {
+ free(proxy); /* proxy is in exception list */
+ proxy = NULL;
+ }
+ }
+ else if(!proxy)
+ proxy = detect_proxy(conn);
+
+ if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
+ free(proxy); /* Don't bother with an empty proxy string or if the
+ protocol doesn't work with network */
+ proxy = NULL;
+ }
+
+ /***********************************************************************
+ * If this is supposed to use a proxy, we need to figure out the proxy host
+ * name, proxy type and port number, so that we can re-use an existing
+ * connection that may exist registered to the same proxy host.
+ ***********************************************************************/
+ if(proxy) {
+ result = parse_proxy(data, conn, proxy);
+
+ Curl_safefree(proxy); /* parse_proxy copies the proxy string */
+
+ if(result)
+ goto out;
+
+ if((conn->proxytype == CURLPROXY_HTTP) ||
+ (conn->proxytype == CURLPROXY_HTTP_1_0)) {
+#ifdef CURL_DISABLE_HTTP
+ /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
+ result = CURLE_UNSUPPORTED_PROTOCOL;
+ goto out;
+#else
+ /* force this connection's protocol to become HTTP if not already
+ compatible - if it isn't tunneling through */
+ if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ !conn->bits.tunnel_proxy)
+ conn->handler = &Curl_handler_http;
+
+ conn->bits.httpproxy = TRUE;
+#endif
+ }
+ else
+ conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
+ conn->bits.proxy = TRUE;
+ }
+ else {
+ /* we aren't using the proxy after all... */
+ conn->bits.proxy = FALSE;
+ conn->bits.httpproxy = FALSE;
+ conn->bits.proxy_user_passwd = FALSE;
+ conn->bits.tunnel_proxy = FALSE;
+ }
+
+#endif /* CURL_DISABLE_PROXY */
+
+ /*************************************************************
+ * If the protocol is using SSL and HTTP proxy is used, we set
+ * the tunnel_proxy bit.
+ *************************************************************/
+ if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
+ conn->bits.tunnel_proxy = TRUE;
+
+ /*************************************************************
+ * Figure out the remote port number and fix it in the URL
+ *************************************************************/
+ result = parse_remote_port(data, conn);
+ if(result != CURLE_OK)
+ goto out;
+
+ /* Check for overridden login details and set them accordingly so they
+ they are known when protocol->setup_connection is called! */
+ result = override_login(data, conn, &user, &passwd, &options);
+ if(result != CURLE_OK)
+ goto out;
+ result = set_login(conn, user, passwd, options);
+ if(result != CURLE_OK)
+ goto out;
+
+ /*************************************************************
+ * Setup internals depending on protocol. Needs to be done after
+ * we figured out what/if proxy to use.
+ *************************************************************/
+ result = setup_connection_internals(conn);
+ if(result != CURLE_OK)
+ goto out;
+
+ conn->recv[FIRSTSOCKET] = Curl_recv_plain;
+ conn->send[FIRSTSOCKET] = Curl_send_plain;
+ conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
+ conn->send[SECONDARYSOCKET] = Curl_send_plain;
+
+ /***********************************************************************
+ * file: is a special case in that it doesn't need a network connection
+ ***********************************************************************/
+#ifndef CURL_DISABLE_FILE
+ if(conn->handler->flags & PROTOPT_NONETWORK) {
+ bool done;
+ /* this is supposed to be the connect function so we better at least check
+ that the file is present here! */
+ DEBUGASSERT(conn->handler->connect_it);
+ result = conn->handler->connect_it(conn, &done);
+
+ /* Setup a "faked" transfer that'll do nothing */
+ if(CURLE_OK == result) {
+ conn->data = data;
+ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
+
+ ConnectionStore(data, conn);
+
+ /*
+ * Setup whatever necessary for a resumed transfer
+ */
+ result = setup_range(data);
+ if(result) {
+ DEBUGASSERT(conn->handler->done);
+ /* we ignore the return code for the protocol-specific DONE */
+ (void)conn->handler->done(conn, result, FALSE);
+ goto out;
+ }
+
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
+ -1, NULL); /* no upload */
+ }
+
+ /* since we skip do_init() */
+ do_init(conn);
+
+ goto out;
+ }
+#endif
+
+ /* Get a cloned copy of the SSL config situation stored in the
+ connection struct. But to get this going nicely, we must first make
+ sure that the strings in the master copy are pointing to the correct
+ strings in the session handle strings array!
+
+ Keep in mind that the pointers in the master copy are pointing to strings
+ that will be freed as part of the SessionHandle struct, but all cloned
+ copies will be separately allocated.
+ */
+ data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
+ data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+ data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
+ data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+ data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
+#ifdef USE_TLS_SRP
+ data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
+ data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+#endif
+
+ if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ prune_dead_connections(data);
+
+ /*************************************************************
+ * Check the current list of connections to see if we can
+ * re-use an already existing one or if we have to create a
+ * new one.
+ *************************************************************/
+
+ /* reuse_fresh is TRUE if we are told to use a new connection by force, but
+ we only acknowledge this option if this is not a re-used connection
+ already (which happens due to follow-location or during a HTTP
+ authentication phase). */
+ if(data->set.reuse_fresh && !data->state.this_is_a_follow)
+ reuse = FALSE;
+ else
+ reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse);
+
+ /* If we found a reusable connection, we may still want to
+ open a new connection if we are pipelining. */
+ if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
+ size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size;
+ if(pipelen > 0) {
+ infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
+ conn_temp->connection_id, pipelen);
+
+ if(conn_temp->bundle->num_connections < max_host_connections &&
+ data->state.conn_cache->num_connections < max_total_connections) {
+ /* We want a new connection anyway */
+ reuse = FALSE;
+
+ infof(data, "We can reuse, but we want a new connection anyway\n");
+ }
+ }
+ }
+
+ if(reuse) {
+ /*
+ * We already have a connection for this, we got the former connection
+ * in the conn_temp variable and thus we need to cleanup the one we
+ * just allocated before we can move along and use the previously
+ * existing one.
+ */
+ conn_temp->inuse = TRUE; /* mark this as being in use so that no other
+ handle in a multi stack may nick it */
+ reuse_conn(conn, conn_temp);
+ free(conn); /* we don't need this anymore */
+ conn = conn_temp;
+ *in_connect = conn;
+
+ /* set a pointer to the hostname we display */
+ fix_hostname(data, conn, &conn->host);
+
+ infof(data, "Re-using existing connection! (#%ld) with host %s\n",
+ conn->connection_id,
+ conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
+ }
+ else {
+ /* We have decided that we want a new connection. However, we may not
+ be able to do that if we have reached the limit of how many
+ connections we are allowed to open. */
+ struct connectbundle *bundle;
+
+ bundle = Curl_conncache_find_bundle(data->state.conn_cache,
+ conn->host.name);
+ if(max_host_connections > 0 && bundle &&
+ (bundle->num_connections >= max_host_connections)) {
+ struct connectdata *conn_candidate;
+
+ /* The bundle is full. Let's see if we can kill a connection. */
+ conn_candidate = find_oldest_idle_connection_in_bundle(data, bundle);
+
+ if(conn_candidate) {
+ /* Set the connection's owner correctly, then kill it */
+ conn_candidate->data = data;
+ (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+ }
+ else
+ no_connections_available = TRUE;
+ }
+
+ if(max_total_connections > 0 &&
+ (data->state.conn_cache->num_connections >= max_total_connections)) {
+ struct connectdata *conn_candidate;
+
+ /* The cache is full. Let's see if we can kill a connection. */
+ conn_candidate = find_oldest_idle_connection(data);
+
+ if(conn_candidate) {
+ /* Set the connection's owner correctly, then kill it */
+ conn_candidate->data = data;
+ (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+ }
+ else
+ no_connections_available = TRUE;
+ }
+
+
+ if(no_connections_available) {
+ infof(data, "No connections available.\n");
+
+ conn_free(conn);
+ *in_connect = NULL;
+
+ result = CURLE_NO_CONNECTION_AVAILABLE;
+ goto out;
+ }
+ else {
+ /*
+ * This is a brand new connection, so let's store it in the connection
+ * cache of ours!
+ */
+ ConnectionStore(data, conn);
+ }
+
+ /* If NTLM is requested in a part of this connection, make sure we don't
+ assume the state is fine as this is a fresh connection and NTLM is
+ connection based. */
+ if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+ data->state.authhost.done) {
+ infof(data, "NTLM picked AND auth done set, clear picked!\n");
+ data->state.authhost.picked = CURLAUTH_NONE;
+ }
+ if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
+ data->state.authproxy.done) {
+ infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
+ data->state.authproxy.picked = CURLAUTH_NONE;
+ }
+
+ }
+
+ /* Mark the connection as used */
+ conn->inuse = TRUE;
+
+ /* Setup and init stuff before DO starts, in preparing for the transfer. */
+ do_init(conn);
+
+ /*
+ * Setup whatever necessary for a resumed transfer
+ */
+ result = setup_range(data);
+ if(result)
+ goto out;
+
+ /* Continue connectdata initialization here. */
+
+ /*
+ * Inherit the proper values from the urldata struct AFTER we have arranged
+ * the persistent connection stuff
+ */
+ conn->fread_func = data->set.fread_func;
+ conn->fread_in = data->set.in;
+ conn->seek_func = data->set.seek_func;
+ conn->seek_client = data->set.seek_client;
+
+ /*************************************************************
+ * Resolve the address of the server or proxy
+ *************************************************************/
+ result = resolve_server(data, conn, async);
+
+ out:
+
+ Curl_safefree(options);
+ Curl_safefree(passwd);
+ Curl_safefree(user);
+ Curl_safefree(proxy);
+ return result;
+}
+
+/* Curl_setup_conn() is called after the name resolve initiated in
+ * create_conn() is all done.
+ *
+ * Curl_setup_conn() also handles reused connections
+ *
+ * conn->data MUST already have been setup fine (in create_conn)
+ */
+
+CURLcode Curl_setup_conn(struct connectdata *conn,
+ bool *protocol_done)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+
+ Curl_pgrsTime(data, TIMER_NAMELOOKUP);
+
+ if(conn->handler->flags & PROTOPT_NONETWORK) {
+ /* nothing to setup when not using a network */
+ *protocol_done = TRUE;
+ return result;
+ }
+ *protocol_done = FALSE; /* default to not done */
+
+ /* set proxy_connect_closed to false unconditionally already here since it
+ is used strictly to provide extra information to a parent function in the
+ case of proxy CONNECT failures and we must make sure we don't have it
+ lingering set from a previous invoke */
+ conn->bits.proxy_connect_closed = FALSE;
+
+ /*
+ * Set user-agent. Used for HTTP, but since we can attempt to tunnel
+ * basically anything through a http proxy we can't limit this based on
+ * protocol.
+ */
+ if(data->set.str[STRING_USERAGENT]) {
+ Curl_safefree(conn->allocptr.uagent);
+ conn->allocptr.uagent =
+ aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
+ if(!conn->allocptr.uagent)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ data->req.headerbytecount = 0;
+
+#ifdef CURL_DO_LINEEND_CONV
+ data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
+#endif /* CURL_DO_LINEEND_CONV */
+
+ /* set start time here for timeout purposes in the connect procedure, it
+ is later set again for the progress meter purpose */
+ conn->now = Curl_tvnow();
+
+ if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
+ conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
+ result = Curl_connecthost(conn, conn->dns_entry);
+ if(result)
+ return result;
+ }
+ else {
+ Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
+ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
+ *protocol_done = TRUE;
+ Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
+ Curl_verboseconnect(conn);
+ }
+
+ conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
+ set this here perhaps a second time */
+
+#ifdef __EMX__
+ /*
+ * This check is quite a hack. We're calling _fsetmode to fix the problem
+ * with fwrite converting newline characters (you get mangled text files,
+ * and corrupted binary files when you download to stdout and redirect it to
+ * a file).
+ */
+
+ if((data->set.out)->_handle == NULL) {
+ _fsetmode(stdout, "b");
+ }
+#endif
+
+ return result;
+}
+
+CURLcode Curl_connect(struct SessionHandle *data,
+ struct connectdata **in_connect,
+ bool *asyncp,
+ bool *protocol_done)
+{
+ CURLcode code;
+
+ *asyncp = FALSE; /* assume synchronous resolves by default */
+
+ /* call the stuff that needs to be called */
+ code = create_conn(data, in_connect, asyncp);
+
+ if(CURLE_OK == code) {
+ /* no error */
+ if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size)
+ /* pipelining */
+ *protocol_done = TRUE;
+ else if(!*asyncp) {
+ /* DNS resolution is done: that's either because this is a reused
+ connection, in which case DNS was unnecessary, or because DNS
+ really did finish already (synch resolver/fast async resolve) */
+ code = Curl_setup_conn(*in_connect, protocol_done);
+ }
+ }
+
+ if(code == CURLE_NO_CONNECTION_AVAILABLE) {
+ *in_connect = NULL;
+ return code;
+ }
+
+ if(code && *in_connect) {
+ /* We're not allowed to return failure with memory left allocated
+ in the connectdata struct, free those here */
+ Curl_disconnect(*in_connect, FALSE); /* close the connection */
+ *in_connect = NULL; /* return a NULL */
+ }
+
+ return code;
+}
+
+CURLcode Curl_done(struct connectdata **connp,
+ CURLcode status, /* an error if this is called after an
+ error was detected */
+ bool premature)
+{
+ CURLcode result;
+ struct connectdata *conn;
+ struct SessionHandle *data;
+
+ DEBUGASSERT(*connp);
+
+ conn = *connp;
+ data = conn->data;
+
+ if(conn->bits.done)
+ /* Stop if Curl_done() has already been called */
+ return CURLE_OK;
+
+ Curl_getoff_all_pipelines(data, conn);
+
+ if((conn->send_pipe->size + conn->recv_pipe->size != 0 &&
+ !data->set.reuse_forbid &&
+ !conn->bits.close))
+ /* Stop if pipeline is not empty and we do not have to close
+ connection. */
+ return CURLE_OK;
+
+ conn->bits.done = TRUE; /* called just now! */
+
+ /* Cleanup possible redirect junk */
+ if(data->req.newurl) {
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+ }
+ if(data->req.location) {
+ free(data->req.location);
+ data->req.location = NULL;
+ }
+
+ Curl_resolver_cancel(conn);
+
+ if(conn->dns_entry) {
+ Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
+ conn->dns_entry = NULL;
+ }
+
+ switch(status) {
+ case CURLE_ABORTED_BY_CALLBACK:
+ case CURLE_READ_ERROR:
+ case CURLE_WRITE_ERROR:
+ /* When we're aborted due to a callback return code it basically have to
+ be counted as premature as there is trouble ahead if we don't. We have
+ many callbacks and protocols work differently, we could potentially do
+ this more fine-grained in the future. */
+ premature = TRUE;
+ default:
+ break;
+ }
+
+ /* this calls the protocol-specific function pointer previously set */
+ if(conn->handler->done)
+ result = conn->handler->done(conn, status, premature);
+ else
+ result = status;
+
+ if(!result && Curl_pgrsDone(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
+
+ /* if the transfer was completed in a paused state there can be buffered
+ data left to write and then kill */
+ if(data->state.tempwrite) {
+ free(data->state.tempwrite);
+ data->state.tempwrite = NULL;
+ }
+
+ /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
+ forced us to close this connection. This is ignored for requests taking
+ place in a NTLM authentication handshake
+
+ if conn->bits.close is TRUE, it means that the connection should be
+ closed in spite of all our efforts to be nice, due to protocol
+ restrictions in our or the server's end
+
+ if premature is TRUE, it means this connection was said to be DONE before
+ the entire request operation is complete and thus we can't know in what
+ state it is for re-using, so we're forced to close it. In a perfect world
+ we can add code that keep track of if we really must close it here or not,
+ but currently we have no such detail knowledge.
+ */
+
+ if((data->set.reuse_forbid && !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
+ conn->proxyntlm.state == NTLMSTATE_TYPE2))
+ || conn->bits.close || premature) {
+ CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
+
+ /* If we had an error already, make sure we return that one. But
+ if we got a new error, return that. */
+ if(!result && res2)
+ result = res2;
+ }
+ else {
+ /* the connection is no longer in use */
+ if(ConnectionDone(data, conn)) {
+ /* remember the most recently used connection */
+ data->state.lastconnect = conn;
+
+ infof(data, "Connection #%ld to host %s left intact\n",
+ conn->connection_id,
+ conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
+ }
+ else
+ data->state.lastconnect = NULL;
+ }
+
+ *connp = NULL; /* to make the caller of this function better detect that
+ this was either closed or handed over to the connection
+ cache here, and therefore cannot be used from this point on
+ */
+ Curl_free_request_state(data);
+
+ return result;
+}
+
+/*
+ * do_init() inits the readwrite session. This is inited each time (in the DO
+ * function before the protocol-specific DO functions are invoked) for a
+ * transfer, sometimes multiple times on the same SessionHandle. Make sure
+ * nothing in here depends on stuff that are setup dynamically for the
+ * transfer.
+ */
+
+static CURLcode do_init(struct connectdata *conn)
+{
+ struct SessionHandle *data = conn->data;
+ struct SingleRequest *k = &data->req;
+
+ conn->bits.done = FALSE; /* Curl_done() is not called yet */
+ conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
+ data->state.expect100header = FALSE;
+
+ if(data->set.opt_no_body)
+ /* in HTTP lingo, no body means using the HEAD request... */
+ data->set.httpreq = HTTPREQ_HEAD;
+ else if(HTTPREQ_HEAD == data->set.httpreq)
+ /* ... but if unset there really is no perfect method that is the
+ "opposite" of HEAD but in reality most people probably think GET
+ then. The important thing is that we can't let it remain HEAD if the
+ opt_no_body is set FALSE since then we'll behave wrong when getting
+ HTTP. */
+ data->set.httpreq = HTTPREQ_GET;
+
+ k->start = Curl_tvnow(); /* start time */
+ k->now = k->start; /* current time is now */
+ k->header = TRUE; /* assume header */
+
+ k->bytecount = 0;
+
+ k->buf = data->state.buffer;
+ k->uploadbuf = data->state.uploadbuffer;
+ k->hbufp = data->state.headerbuff;
+ k->ignorebody=FALSE;
+
+ Curl_speedinit(data);
+
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+
+ return CURLE_OK;
+}
+
+/*
+ * do_complete is called when the DO actions are complete.
+ *
+ * We init chunking and trailer bits to their default values here immediately
+ * before receiving any header data for the current request in the pipeline.
+ */
+static void do_complete(struct connectdata *conn)
+{
+ conn->data->req.chunk=FALSE;
+ conn->data->req.maxfd = (conn->sockfd>conn->writesockfd?
+ conn->sockfd:conn->writesockfd)+1;
+ Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
+}
+
+CURLcode Curl_do(struct connectdata **connp, bool *done)
+{
+ CURLcode result=CURLE_OK;
+ struct connectdata *conn = *connp;
+ struct SessionHandle *data = conn->data;
+
+ if(conn->handler->do_it) {
+ /* generic protocol-specific function pointer set in curl_connect() */
+ result = conn->handler->do_it(conn, done);
+
+ /* This was formerly done in transfer.c, but we better do it here */
+ if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
+ /*
+ * If the connection is using an easy handle, call reconnect
+ * to re-establish the connection. Otherwise, let the multi logic
+ * figure out how to re-establish the connection.
+ */
+ if(!data->multi) {
+ result = Curl_reconnect_request(connp);
+
+ if(result == CURLE_OK) {
+ /* ... finally back to actually retry the DO phase */
+ conn = *connp; /* re-assign conn since Curl_reconnect_request
+ creates a new connection */
+ result = conn->handler->do_it(conn, done);
+ }
+ }
+ else
+ return result;
+ }
+
+ if((result == CURLE_OK) && *done)
+ /* do_complete must be called after the protocol-specific DO function */
+ do_complete(conn);
+ }
+ return result;
+}
+
+/*
+ * Curl_do_more() is called during the DO_MORE multi state. It is basically a
+ * second stage DO state which (wrongly) was introduced to support FTP's
+ * second connection.
+ *
+ * TODO: A future libcurl should be able to work away this state.
+ *
+ * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
+ * DOING state there's more work to do!
+ */
+
+CURLcode Curl_do_more(struct connectdata *conn, int *complete)
+{
+ CURLcode result=CURLE_OK;
+
+ *complete = 0;
+
+ if(conn->handler->do_more)
+ result = conn->handler->do_more(conn, complete);
+
+ if(!result && (*complete == 1))
+ /* do_complete must be called after the protocol-specific DO function */
+ do_complete(conn);
+
+ return result;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/url.h b/external/libcurl_android/jni/libcurl/lib/url.h
new file mode 100755
index 00000000..cd46a92c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/url.h
@@ -0,0 +1,82 @@
+#ifndef HEADER_CURL_URL_H
+#define HEADER_CURL_URL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/*
+ * Prototypes for library-wide functions provided by url.c
+ */
+
+CURLcode Curl_open(struct SessionHandle **curl);
+CURLcode Curl_init_userdefined(struct UserDefined *set);
+CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
+ va_list arg);
+CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src);
+void Curl_freeset(struct SessionHandle * data);
+CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
+CURLcode Curl_connect(struct SessionHandle *, struct connectdata **,
+ bool *async, bool *protocol_connect);
+CURLcode Curl_do(struct connectdata **, bool *done);
+CURLcode Curl_do_more(struct connectdata *, int *completed);
+CURLcode Curl_done(struct connectdata **, CURLcode, bool premature);
+CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
+CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
+CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
+CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
+CURLcode Curl_setup_conn(struct connectdata *conn,
+ bool *protocol_done);
+void Curl_free_request_state(struct SessionHandle *data);
+
+int Curl_protocol_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+int Curl_doing_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+bool Curl_isPipeliningEnabled(const struct SessionHandle *handle);
+CURLcode Curl_addHandleToPipeline(struct SessionHandle *handle,
+ struct curl_llist *pipeline);
+int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
+ struct curl_llist *pipeline);
+/* remove the specified connection from all (possible) pipelines and related
+ queues */
+void Curl_getoff_all_pipelines(struct SessionHandle *data,
+ struct connectdata *conn);
+
+void Curl_close_connections(struct SessionHandle *data);
+
+#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
+#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
+ service */
+
+CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
+
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+#define Curl_verboseconnect(x) Curl_nop_stmt
+#else
+void Curl_verboseconnect(struct connectdata *conn);
+#endif
+
+
+#endif /* HEADER_CURL_URL_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/urldata.h b/external/libcurl_android/jni/libcurl/lib/urldata.h
new file mode 100755
index 00000000..8594c2f7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/urldata.h
@@ -0,0 +1,1705 @@
+#ifndef HEADER_CURL_URLDATA_H
+#define HEADER_CURL_URLDATA_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This file is for lib internal stuff */
+
+#include "curl_setup.h"
+
+#define PORT_FTP 21
+#define PORT_FTPS 990
+#define PORT_TELNET 23
+#define PORT_HTTP 80
+#define PORT_HTTPS 443
+#define PORT_DICT 2628
+#define PORT_LDAP 389
+#define PORT_LDAPS 636
+#define PORT_TFTP 69
+#define PORT_SSH 22
+#define PORT_IMAP 143
+#define PORT_IMAPS 993
+#define PORT_POP3 110
+#define PORT_POP3S 995
+#define PORT_SMTP 25
+#define PORT_SMTPS 465 /* sometimes called SSMTP */
+#define PORT_RTSP 554
+#define PORT_RTMP 1935
+#define PORT_RTMPT PORT_HTTP
+#define PORT_RTMPS PORT_HTTPS
+#define PORT_GOPHER 70
+
+#define DICT_MATCH "/MATCH:"
+#define DICT_MATCH2 "/M:"
+#define DICT_MATCH3 "/FIND:"
+#define DICT_DEFINE "/DEFINE:"
+#define DICT_DEFINE2 "/D:"
+#define DICT_DEFINE3 "/LOOKUP:"
+
+#define CURL_DEFAULT_USER "anonymous"
+#define CURL_DEFAULT_PASSWORD "ftp@example.com"
+
+/* Convenience defines for checking protocols or their SSL based version. Each
+ protocol handler should only ever have a single CURLPROTO_ in its protocol
+ field. */
+#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS)
+#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS)
+#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S)
+#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS)
+
+#define DEFAULT_CONNCACHE_SIZE 5
+
+/* length of longest IPv6 address string including the trailing null */
+#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")
+
+/* Default FTP/IMAP etc response timeout in milliseconds.
+ Symbian OS panics when given a timeout much greater than 1/2 hour.
+*/
+#define RESP_TIMEOUT (1800*1000)
+
+#include "cookie.h"
+#include "formdata.h"
+
+#ifdef USE_SSLEAY
+#ifdef USE_OPENSSL
+#include <openssl/rsa.h>
+#include <openssl/crypto.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
+#ifdef HAVE_OPENSSL_PKCS12_H
+#include <openssl/pkcs12.h>
+#endif
+#else /* SSLeay-style includes */
+#include <rsa.h>
+#include <crypto.h>
+#include <x509.h>
+#include <pem.h>
+#include <ssl.h>
+#include <err.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <engine.h>
+#endif
+#ifdef HAVE_OPENSSL_PKCS12_H
+#include <pkcs12.h>
+#endif
+#endif /* USE_OPENSSL */
+#ifdef USE_GNUTLS
+#error Configuration error; cannot use GnuTLS *and* OpenSSL.
+#endif
+#endif /* USE_SSLEAY */
+
+#ifdef USE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
+#ifdef USE_POLARSSL
+#include <polarssl/ssl.h>
+#include <polarssl/version.h>
+#if POLARSSL_VERSION_NUMBER<0x01010000
+#include <polarssl/havege.h>
+#else
+#include <polarssl/entropy.h>
+#include <polarssl/ctr_drbg.h>
+#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */
+#endif /* USE_POLARSSL */
+
+#ifdef USE_CYASSL
+#undef OCSP_REQUEST /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */
+#undef OCSP_RESPONSE /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */
+#include <cyassl/openssl/ssl.h>
+#endif
+
+#ifdef USE_NSS
+#include <nspr.h>
+#include <pk11pub.h>
+#endif
+
+#ifdef USE_QSOSSL
+#include <qsossl.h>
+#endif
+
+#ifdef USE_GSKIT
+#include <gskssl.h>
+#endif
+
+#ifdef USE_AXTLS
+#include <axTLS/ssl.h>
+#undef malloc
+#undef calloc
+#undef realloc
+#endif /* USE_AXTLS */
+
+#ifdef USE_SCHANNEL
+#include "curl_sspi.h"
+#include <schnlsp.h>
+#include <schannel.h>
+#endif
+
+#ifdef USE_DARWINSSL
+#include <Security/Security.h>
+/* For some reason, when building for iOS, the omnibus header above does
+ * not include SecureTransport.h as of iOS SDK 5.1. */
+#include <Security/SecureTransport.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "timeval.h"
+
+#ifdef HAVE_ZLIB_H
+#include <zlib.h> /* for content-encoding */
+#ifdef __SYMBIAN32__
+/* zlib pollutes the namespace with this definition */
+#undef WIN32
+#endif
+#endif
+
+#include <curl/curl.h>
+
+#include "http_chunks.h" /* for the structs and enum stuff */
+#include "hostip.h"
+#include "hash.h"
+#include "splay.h"
+
+#include "imap.h"
+#include "pop3.h"
+#include "smtp.h"
+#include "ftp.h"
+#include "file.h"
+#include "ssh.h"
+#include "http.h"
+#include "rtsp.h"
+#include "wildcard.h"
+#include "multihandle.h"
+
+#ifdef HAVE_GSSAPI
+# ifdef HAVE_GSSGNU
+# include <gss.h>
+# elif defined HAVE_GSSMIT
+# include <gssapi/gssapi.h>
+# include <gssapi/gssapi_generic.h>
+# else
+# include <gssapi.h>
+# endif
+#endif
+
+#ifdef HAVE_LIBSSH2_H
+#include <libssh2.h>
+#include <libssh2_sftp.h>
+#endif /* HAVE_LIBSSH2_H */
+
+/* Download buffer size, keep it fairly big for speed reasons */
+#undef BUFSIZE
+#define BUFSIZE CURL_MAX_WRITE_SIZE
+
+/* Initial size of the buffer to store headers in, it'll be enlarged in case
+ of need. */
+#define HEADERSIZE 256
+
+#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
+
+/* Some convenience macros to get the larger/smaller value out of two given.
+ We prefix with CURL to prevent name collisions. */
+#define CURLMAX(x,y) ((x)>(y)?(x):(y))
+#define CURLMIN(x,y) ((x)<(y)?(x):(y))
+
+
+#ifdef HAVE_GSSAPI
+/* Types needed for krb5-ftp connections */
+struct krb5buffer {
+ void *data;
+ size_t size;
+ size_t index;
+ int eof_flag;
+};
+
+enum protection_level {
+ PROT_NONE, /* first in list */
+ PROT_CLEAR,
+ PROT_SAFE,
+ PROT_CONFIDENTIAL,
+ PROT_PRIVATE,
+ PROT_CMD,
+ PROT_LAST /* last in list */
+};
+#endif
+
+#ifdef USE_SCHANNEL
+/* Structs to store Schannel handles */
+struct curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ int refcount;
+ bool cached;
+};
+
+struct curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+#endif
+
+/* enum for the nonblocking SSL connection state machine */
+typedef enum {
+ ssl_connect_1,
+ ssl_connect_2,
+ ssl_connect_2_reading,
+ ssl_connect_2_writing,
+ ssl_connect_3,
+ ssl_connect_done
+} ssl_connect_state;
+
+typedef enum {
+ ssl_connection_none,
+ ssl_connection_negotiating,
+ ssl_connection_complete
+} ssl_connection_state;
+
+/* struct for data related to each SSL connection */
+struct ssl_connect_data {
+ /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm
+ but at least asked to or meaning to use it. See 'state' for the exact
+ current state of the connection. */
+ bool use;
+ ssl_connection_state state;
+#ifdef USE_SSLEAY
+ /* these ones requires specific SSL-types */
+ SSL_CTX* ctx;
+ SSL* handle;
+ X509* server_cert;
+ ssl_connect_state connecting_state;
+#endif /* USE_SSLEAY */
+#ifdef USE_GNUTLS
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t cred;
+#ifdef USE_TLS_SRP
+ gnutls_srp_client_credentials_t srp_client_cred;
+#endif
+ ssl_connect_state connecting_state;
+#endif /* USE_GNUTLS */
+#ifdef USE_POLARSSL
+ ctr_drbg_context ctr_drbg;
+ entropy_context entropy;
+ ssl_context ssl;
+ ssl_session ssn;
+ int server_fd;
+ x509_crt cacert;
+ x509_crt clicert;
+ x509_crl crl;
+ rsa_context rsa;
+ ssl_connect_state connecting_state;
+#endif /* USE_POLARSSL */
+#ifdef USE_CYASSL
+ SSL_CTX* ctx;
+ SSL* handle;
+ ssl_connect_state connecting_state;
+#endif /* USE_CYASSL */
+#ifdef USE_NSS
+ PRFileDesc *handle;
+ char *client_nickname;
+ struct SessionHandle *data;
+ struct curl_llist *obj_list;
+ PK11GenericObject *obj_clicert;
+ ssl_connect_state connecting_state;
+#endif /* USE_NSS */
+#ifdef USE_QSOSSL
+ SSLHandle *handle;
+#endif /* USE_QSOSSL */
+#ifdef USE_GSKIT
+ gsk_handle handle;
+ int iocport;
+ ssl_connect_state connecting_state;
+#endif
+#ifdef USE_AXTLS
+ SSL_CTX* ssl_ctx;
+ SSL* ssl;
+ ssl_connect_state connecting_state;
+#endif /* USE_AXTLS */
+#ifdef USE_SCHANNEL
+ struct curl_schannel_cred *cred;
+ struct curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ ssl_connect_state connecting_state;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ unsigned long req_flags, ret_flags;
+#endif /* USE_SCHANNEL */
+#ifdef USE_DARWINSSL
+ SSLContextRef ssl_ctx;
+ curl_socket_t ssl_sockfd;
+ ssl_connect_state connecting_state;
+ bool ssl_direction; /* true if writing, false if reading */
+ size_t ssl_write_buffered_length;
+#endif /* USE_DARWINSSL */
+};
+
+struct ssl_config_data {
+ long version; /* what version the client wants to use */
+ long certverifyresult; /* result from the certificate verification */
+
+ bool verifypeer; /* set TRUE if this is desired */
+ bool verifyhost; /* set TRUE if CN/SAN must match hostname */
+ char *CApath; /* certificate dir (doesn't work on windows) */
+ char *CAfile; /* certificate to verify peer against */
+ const char *CRLfile; /* CRL to check certificate revocation */
+ const char *issuercert;/* optional issuer certificate filename */
+ char *random_file; /* path to file containing "random" data */
+ char *egdsocket; /* path to file containing the EGD daemon socket */
+ char *cipher_list; /* list of ciphers to use */
+ size_t max_ssl_sessions; /* SSL session id cache size */
+ curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
+ void *fsslctxp; /* parameter for call back */
+ bool sessionid; /* cache session IDs or not */
+ bool certinfo; /* gather lots of certificate info */
+
+#ifdef USE_TLS_SRP
+ char *username; /* TLS username (for, e.g., SRP) */
+ char *password; /* TLS password (for, e.g., SRP) */
+ enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */
+#endif
+};
+
+/* information stored about one single SSL session */
+struct curl_ssl_session {
+ char *name; /* host name for which this ID was used */
+ void *sessionid; /* as returned from the SSL layer */
+ size_t idsize; /* if known, otherwise 0 */
+ long age; /* just a number, the higher the more recent */
+ int remote_port; /* remote port to connect to */
+ struct ssl_config_data ssl_config; /* setup for this session */
+};
+
+/* Struct used for Digest challenge-response authentication */
+struct digestdata {
+ char *nonce;
+ char *cnonce;
+ char *realm;
+ int algo;
+ bool stale; /* set true for re-negotiation */
+ char *opaque;
+ char *qop;
+ char *algorithm;
+ int nc; /* nounce count */
+};
+
+typedef enum {
+ NTLMSTATE_NONE,
+ NTLMSTATE_TYPE1,
+ NTLMSTATE_TYPE2,
+ NTLMSTATE_TYPE3,
+ NTLMSTATE_LAST
+} curlntlm;
+
+#ifdef USE_WINDOWS_SSPI
+#include "curl_sspi.h"
+#endif
+
+#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
+#include <iconv.h>
+#endif
+
+/* Struct used for GSSAPI (Kerberos V5) authentication */
+#if defined(USE_WINDOWS_SSPI)
+struct kerberos5data {
+ CredHandle *credentials;
+ CtxtHandle *context;
+ TCHAR *spn;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ size_t token_max;
+ BYTE *output_token;
+};
+#endif
+
+/* Struct used for NTLM challenge-response authentication */
+struct ntlmdata {
+ curlntlm state;
+#ifdef USE_WINDOWS_SSPI
+ CredHandle handle;
+ CtxtHandle c_handle;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ size_t max_token_length;
+ BYTE *output_token;
+ int has_handles;
+ void *type_2;
+ unsigned long n_type_2;
+#else
+ unsigned int flags;
+ unsigned char nonce[8];
+ void* target_info; /* TargetInfo received in the ntlm type-2 message */
+ unsigned int target_info_len;
+#endif
+};
+
+#ifdef USE_SPNEGO
+struct negotiatedata {
+ /* When doing Negotiate (SPNEGO) auth, we first need to send a token
+ and then validate the received one. */
+ enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state;
+#ifdef HAVE_GSSAPI
+ OM_uint32 status;
+ gss_ctx_id_t context;
+ gss_name_t server_name;
+ gss_buffer_desc output_token;
+#else
+#ifdef USE_WINDOWS_SSPI
+ DWORD status;
+ CtxtHandle *context;
+ CredHandle *credentials;
+ SEC_WINNT_AUTH_IDENTITY identity;
+ SEC_WINNT_AUTH_IDENTITY *p_identity;
+ TCHAR *server_name;
+ size_t max_token_length;
+ BYTE *output_token;
+ size_t output_token_length;
+#endif
+#endif
+};
+#endif
+
+
+/*
+ * Boolean values that concerns this connection.
+ */
+struct ConnectBits {
+ /* always modify bits.close with the connclose() and connkeep() macros! */
+ bool close; /* if set, we close the connection after this request */
+ bool reuse; /* if set, this is a re-used connection */
+ bool proxy; /* if set, this transfer is done through a proxy - any type */
+ bool httpproxy; /* if set, this transfer is done through a http proxy */
+ bool user_passwd; /* do we use user+password for this connection? */
+ bool proxy_user_passwd; /* user+password for the proxy? */
+ bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6
+ IP address */
+ bool ipv6; /* we communicate with a site using an IPv6 address */
+
+ bool do_more; /* this is set TRUE if the ->curl_do_more() function is
+ supposed to be called, after ->curl_do() */
+ bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set
+ the first time on the first connect function call */
+ bool protoconnstart;/* the protocol layer has STARTED its operation after
+ the TCP layer connect */
+
+ bool retry; /* this connection is about to get closed and then
+ re-attempted at another connection. */
+ bool tunnel_proxy; /* if CONNECT is used to "tunnel" through the proxy.
+ This is implicit when SSL-protocols are used through
+ proxies, but can also be enabled explicitly by
+ apps */
+ bool authneg; /* TRUE when the auth phase has started, which means
+ that we are creating a request with an auth header,
+ but it is not the final request in the auth
+ negotiation. */
+ bool rewindaftersend;/* TRUE when the sending couldn't be stopped even
+ though it will be discarded. When the whole send
+ operation is done, we must call the data rewind
+ callback. */
+ bool ftp_use_epsv; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out
+ EPSV doesn't work we disable it for the forthcoming
+ requests */
+
+ bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
+ EPRT doesn't work we disable it for the forthcoming
+ requests */
+ bool netrc; /* name+password provided by netrc */
+ bool userpwd_in_url; /* name+password found in url */
+
+ bool done; /* set to FALSE when Curl_do() is called and set to TRUE
+ when Curl_done() is called, to prevent Curl_done() to
+ get invoked twice when the multi interface is
+ used. */
+ bool stream_was_rewound; /* Indicates that the stream was rewound after a
+ request read past the end of its response byte
+ boundary */
+ bool proxy_connect_closed; /* set true if a proxy disconnected the
+ connection in a CONNECT request with auth, so
+ that libcurl should reconnect and continue. */
+ bool bound; /* set true if bind() has already been done on this socket/
+ connection */
+ bool type_set; /* type= was used in the URL */
+};
+
+struct hostname {
+ char *rawalloc; /* allocated "raw" version of the name */
+ char *encalloc; /* allocated IDN-encoded version of the name */
+ char *name; /* name to use internally, might be encoded, might be raw */
+ const char *dispname; /* name to display, as 'name' might be encoded */
+};
+
+/*
+ * Flags on the keepon member of the Curl_transfer_keeper
+ */
+
+#define KEEP_NONE 0
+#define KEEP_RECV (1<<0) /* there is or may be data to read */
+#define KEEP_SEND (1<<1) /* there is or may be data to write */
+#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there
+ might still be data to read */
+#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there
+ might still be data to write */
+#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */
+#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */
+
+#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
+#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
+
+
+#ifdef HAVE_LIBZ
+typedef enum {
+ ZLIB_UNINIT, /* uninitialized */
+ ZLIB_INIT, /* initialized */
+ ZLIB_GZIP_HEADER, /* reading gzip header */
+ ZLIB_GZIP_INFLATING, /* inflating gzip stream */
+ ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
+} zlibInitState;
+#endif
+
+#ifdef CURLRES_ASYNCH
+struct Curl_async {
+ char *hostname;
+ int port;
+ struct Curl_dns_entry *dns;
+ bool done; /* set TRUE when the lookup is complete */
+ int status; /* if done is TRUE, this is the status from the callback */
+ void *os_specific; /* 'struct thread_data' for Windows */
+};
+#endif
+
+#define FIRSTSOCKET 0
+#define SECONDARYSOCKET 1
+
+/* These function pointer types are here only to allow easier typecasting
+ within the source when we need to cast between data pointers (such as NULL)
+ and function pointers. */
+typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
+typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
+
+enum expect100 {
+ EXP100_SEND_DATA, /* enough waiting, just send the body now */
+ EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
+ EXP100_SENDING_REQUEST, /* still sending the request but will wait for
+ the 100 header once done with the request */
+ EXP100_FAILED /* used on 417 Expectation Failed */
+};
+
+enum upgrade101 {
+ UPGR101_INIT, /* default state */
+ UPGR101_REQUESTED, /* upgrade requested */
+ UPGR101_RECEIVED, /* response received */
+ UPGR101_WORKING /* talking upgraded protocol */
+};
+
+enum negotiatenpn {
+ NPN_INIT, /* default state */
+ NPN_HTTP1_1, /* HTTP/1.1 negotiated */
+ NPN_HTTP2 /* HTTP2 (draft-xx) negotiated */
+};
+
+/*
+ * Request specific data in the easy handle (SessionHandle). Previously,
+ * these members were on the connectdata struct but since a conn struct may
+ * now be shared between different SessionHandles, we store connection-specific
+ * data here. This struct only keeps stuff that's interesting for *this*
+ * request, as it will be cleared between multiple ones
+ */
+struct SingleRequest {
+ curl_off_t size; /* -1 if unknown at this point */
+ curl_off_t *bytecountp; /* return number of bytes read or NULL */
+
+ curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
+ -1 means unlimited */
+ curl_off_t *writebytecountp; /* return number of bytes written or NULL */
+
+ curl_off_t bytecount; /* total number of bytes read */
+ curl_off_t writebytecount; /* number of bytes written */
+
+ long headerbytecount; /* only count received headers */
+ long deductheadercount; /* this amount of bytes doesn't count when we check
+ if anything has been transferred at the end of a
+ connection. We use this counter to make only a
+ 100 reply (without a following second response
+ code) result in a CURLE_GOT_NOTHING error code */
+
+ struct timeval start; /* transfer started at this time */
+ struct timeval now; /* current time */
+ bool header; /* incoming data has HTTP header */
+ enum {
+ HEADER_NORMAL, /* no bad header at all */
+ HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
+ is normal data */
+ HEADER_ALLBAD /* all was believed to be header */
+ } badheader; /* the header was deemed bad and will be
+ written as body */
+ int headerline; /* counts header lines to better track the
+ first one */
+ char *hbufp; /* points at *end* of header line */
+ size_t hbuflen;
+ char *str; /* within buf */
+ char *str_start; /* within buf */
+ char *end_ptr; /* within buf */
+ char *p; /* within headerbuff */
+ bool content_range; /* set TRUE if Content-Range: was found */
+ curl_off_t offset; /* possible resume offset read from the
+ Content-Range: header */
+ int httpcode; /* error code from the 'HTTP/1.? XXX' or
+ 'RTSP/1.? XXX' line */
+ struct timeval start100; /* time stamp to wait for the 100 code from */
+ enum expect100 exp100; /* expect 100 continue state */
+ enum upgrade101 upgr101; /* 101 upgrade state */
+
+ int auto_decoding; /* What content encoding. sec 3.5, RFC2616. */
+
+#define IDENTITY 0 /* No encoding */
+#define DEFLATE 1 /* zlib deflate [RFC 1950 & 1951] */
+#define GZIP 2 /* gzip algorithm [RFC 1952] */
+#define COMPRESS 3 /* Not handled, added for completeness */
+
+#ifdef HAVE_LIBZ
+ zlibInitState zlib_init; /* possible zlib init state;
+ undefined if Content-Encoding header. */
+ z_stream z; /* State structure for zlib. */
+#endif
+
+ time_t timeofdoc;
+ long bodywrites;
+
+ char *buf;
+ char *uploadbuf;
+ curl_socket_t maxfd;
+
+ int keepon;
+
+ bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload
+ and we're uploading the last chunk */
+
+ bool ignorebody; /* we read a response-body but we ignore it! */
+ bool ignorecl; /* This HTTP response has no body so we ignore the Content-
+ Length: header */
+
+ char *location; /* This points to an allocated version of the Location:
+ header data */
+ char *newurl; /* Set to the new URL to use when a redirect or a retry is
+ wanted */
+
+ /* 'upload_present' is used to keep a byte counter of how much data there is
+ still left in the buffer, aimed for upload. */
+ ssize_t upload_present;
+
+ /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
+ buffer, so the next read should read from where this pointer points to,
+ and the 'upload_present' contains the number of bytes available at this
+ position */
+ char *upload_fromhere;
+
+ bool chunk; /* if set, this is a chunked transfer-encoding */
+ bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding
+ on upload */
+ bool getheader; /* TRUE if header parsing is wanted */
+
+ bool forbidchunk; /* used only to explicitly forbid chunk-upload for
+ specific upload buffers. See readmoredata() in
+ http.c for details. */
+
+ void *protop; /* Allocated protocol-specific data. Each protocol
+ handler makes sure this points to data it needs. */
+};
+
+/*
+ * Specific protocol handler.
+ */
+
+struct Curl_handler {
+ const char * scheme; /* URL scheme name. */
+
+ /* Complement to setup_connection_internals(). */
+ CURLcode (*setup_connection)(struct connectdata *);
+
+ /* These two functions MUST be set to be protocol dependent */
+ CURLcode (*do_it)(struct connectdata *, bool *done);
+ Curl_done_func done;
+
+ /* If the curl_do() function is better made in two halves, this
+ * curl_do_more() function will be called afterwards, if set. For example
+ * for doing the FTP stuff after the PASV/PORT command.
+ */
+ Curl_do_more_func do_more;
+
+ /* This function *MAY* be set to a protocol-dependent function that is run
+ * after the connect() and everything is done, as a step in the connection.
+ * The 'done' pointer points to a bool that should be set to TRUE if the
+ * function completes before return. If it doesn't complete, the caller
+ * should call the curl_connecting() function until it is.
+ */
+ CURLcode (*connect_it)(struct connectdata *, bool *done);
+
+ /* See above. Currently only used for FTP. */
+ CURLcode (*connecting)(struct connectdata *, bool *done);
+ CURLcode (*doing)(struct connectdata *, bool *done);
+
+ /* Called from the multi interface during the PROTOCONNECT phase, and it
+ should then return a proper fd set */
+ int (*proto_getsock)(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+ /* Called from the multi interface during the DOING phase, and it should
+ then return a proper fd set */
+ int (*doing_getsock)(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+ /* Called from the multi interface during the DO_MORE phase, and it should
+ then return a proper fd set */
+ int (*domore_getsock)(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+ /* Called from the multi interface during the DO_DONE, PERFORM and
+ WAITPERFORM phases, and it should then return a proper fd set. Not setting
+ this will make libcurl use the generic default one. */
+ int (*perform_getsock)(const struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
+ /* This function *MAY* be set to a protocol-dependent function that is run
+ * by the curl_disconnect(), as a step in the disconnection. If the handler
+ * is called because the connection has been considered dead, dead_connection
+ * is set to TRUE.
+ */
+ CURLcode (*disconnect)(struct connectdata *, bool dead_connection);
+
+ /* If used, this function gets called from transfer.c:readwrite_data() to
+ allow the protocol to do extra reads/writes */
+ CURLcode (*readwrite)(struct SessionHandle *data, struct connectdata *conn,
+ ssize_t *nread, bool *readmore);
+
+ long defport; /* Default port. */
+ unsigned int protocol; /* See CURLPROTO_* - this needs to be the single
+ specific protocol bit */
+ unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */
+};
+
+#define PROTOPT_NONE 0 /* nothing extra */
+#define PROTOPT_SSL (1<<0) /* uses SSL */
+#define PROTOPT_DUAL (1<<1) /* this protocol uses two connections */
+#define PROTOPT_CLOSEACTION (1<<2) /* need action before socket close */
+/* some protocols will have to call the underlying functions without regard to
+ what exact state the socket signals. IE even if the socket says "readable",
+ the send function might need to be called while uploading, or vice versa.
+*/
+#define PROTOPT_DIRLOCK (1<<3)
+#define PROTOPT_NONETWORK (1<<4) /* protocol doesn't use the network! */
+#define PROTOPT_NEEDSPWD (1<<5) /* needs a password, and if none is set it
+ gets a default */
+#define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle
+ url query strings (?foo=bar) ! */
+#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
+ request instead of per connection */
+
+
+/* return the count of bytes sent, or -1 on error */
+typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ const void *buf, /* data to write */
+ size_t len, /* max amount to write */
+ CURLcode *err); /* error to return */
+
+/* return the count of bytes read, or -1 on error */
+typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ char *buf, /* store data here */
+ size_t len, /* max amount to read */
+ CURLcode *err); /* error to return */
+
+/*
+ * The connectdata struct contains all fields and variables that should be
+ * unique for an entire connection.
+ */
+struct connectdata {
+ /* 'data' is the CURRENT SessionHandle using this connection -- take great
+ caution that this might very well vary between different times this
+ connection is used! */
+ struct SessionHandle *data;
+
+ /* chunk is for HTTP chunked encoding, but is in the general connectdata
+ struct only because we can do just about any protocol through a HTTP proxy
+ and a HTTP proxy may in fact respond using chunked encoding */
+ struct Curl_chunker chunk;
+
+ curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
+ void *closesocket_client;
+
+ bool inuse; /* This is a marker for the connection cache logic. If this is
+ TRUE this handle is being used by an easy handle and cannot
+ be used by any other easy handle without careful
+ consideration (== only for pipelining). */
+
+ /**** Fields set when inited and not modified again */
+ long connection_id; /* Contains a unique number to make it easier to
+ track the connections in the log output */
+
+ /* 'dns_entry' is the particular host we use. This points to an entry in the
+ DNS cache and it will not get pruned while locked. It gets unlocked in
+ Curl_done(). This entry will be NULL if the connection is re-used as then
+ there is no name resolve done. */
+ struct Curl_dns_entry *dns_entry;
+
+ /* 'ip_addr' is the particular IP we connected to. It points to a struct
+ within the DNS cache, so this pointer is only valid as long as the DNS
+ cache entry remains locked. It gets unlocked in Curl_done() */
+ Curl_addrinfo *ip_addr;
+ Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
+
+ /* 'ip_addr_str' is the ip_addr data as a human readable string.
+ It remains available as long as the connection does, which is longer than
+ the ip_addr itself. */
+ char ip_addr_str[MAX_IPADR_LEN];
+
+ unsigned int scope; /* address scope for IPv6 */
+
+ int socktype; /* SOCK_STREAM or SOCK_DGRAM */
+
+ struct hostname host;
+ struct hostname proxy;
+
+ long port; /* which port to use locally */
+ int remote_port; /* what remote port to connect to, not the proxy port! */
+
+ /* 'primary_ip' and 'primary_port' get filled with peer's numerical
+ ip address and port number whenever an outgoing connection is
+ *attempted* from the primary socket to a remote address. When more
+ than one address is tried for a connection these will hold data
+ for the last attempt. When the connection is actually established
+ these are updated with data which comes directly from the socket. */
+
+ char primary_ip[MAX_IPADR_LEN];
+ long primary_port;
+
+ /* 'local_ip' and 'local_port' get filled with local's numerical
+ ip address and port number whenever an outgoing connection is
+ **established** from the primary socket to a remote address. */
+
+ char local_ip[MAX_IPADR_LEN];
+ long local_port;
+
+ char *user; /* user name string, allocated */
+ char *passwd; /* password string, allocated */
+ char *options; /* options string, allocated */
+
+ char *xoauth2_bearer; /* bearer token for xoauth2, allocated */
+
+ char *proxyuser; /* proxy user name string, allocated */
+ char *proxypasswd; /* proxy password string, allocated */
+ curl_proxytype proxytype; /* what kind of proxy that is in use */
+
+ int httpversion; /* the HTTP version*10 reported by the server */
+ int rtspversion; /* the RTSP version*10 reported by the server */
+
+ struct timeval now; /* "current" time */
+ struct timeval created; /* creation time */
+ curl_socket_t sock[2]; /* two sockets, the second is used for the data
+ transfer when doing FTP */
+ curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */
+ bool sock_accepted[2]; /* TRUE if the socket on this index was created with
+ accept() */
+ Curl_recv *recv[2];
+ Curl_send *send[2];
+
+ struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
+ struct ssl_config_data ssl_config;
+
+ struct ConnectBits bits; /* various state-flags for this connection */
+
+ /* connecttime: when connect() is called on the current IP address. Used to
+ be able to track when to move on to try next IP - but only when the multi
+ interface is used. */
+ struct timeval connecttime;
+ /* The two fields below get set in Curl_connecthost */
+ int num_addr; /* number of addresses to try to connect to */
+ long timeoutms_per_addr; /* how long time in milliseconds to spend on
+ trying to connect to each IP address */
+
+ const struct Curl_handler *handler; /* Connection's protocol handler */
+ const struct Curl_handler *given; /* The protocol first given */
+
+ long ip_version; /* copied from the SessionHandle at creation time */
+
+ /**** curl_get() phase fields */
+
+ curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */
+ curl_socket_t writesockfd; /* socket to write to, it may very
+ well be the same we read from.
+ CURL_SOCKET_BAD disables */
+
+ /** Dynamicly allocated strings, MUST be freed before this **/
+ /** struct is killed. **/
+ struct dynamically_allocated_data {
+ char *proxyuserpwd;
+ char *uagent;
+ char *accept_encoding;
+ char *userpwd;
+ char *rangeline;
+ char *ref;
+ char *host;
+ char *cookiehost;
+ char *rtsp_transport;
+ char *te; /* TE: request header */
+ } allocptr;
+
+ int sec_complete; /* if kerberos is enabled for this connection */
+#ifdef HAVE_GSSAPI
+ enum protection_level command_prot;
+ enum protection_level data_prot;
+ enum protection_level request_data_prot;
+ size_t buffer_size;
+ struct krb5buffer in_buffer;
+ void *app_data;
+ const struct Curl_sec_client_mech *mech;
+ struct sockaddr_in local_addr;
+#endif
+
+#if defined(USE_WINDOWS_SSPI) /* Consider moving some of the above GSS-API */
+ struct kerberos5data krb5; /* variables into the structure definition, */
+#endif /* however, some of them are ftp specific. */
+
+ /* the two following *_inuse fields are only flags, not counters in any way.
+ If TRUE it means the channel is in use, and if FALSE it means the channel
+ is up for grabs by one. */
+
+ bool readchannel_inuse; /* whether the read channel is in use by an easy
+ handle */
+ bool writechannel_inuse; /* whether the write channel is in use by an easy
+ handle */
+ struct curl_llist *send_pipe; /* List of handles waiting to
+ send on this pipeline */
+ struct curl_llist *recv_pipe; /* List of handles waiting to read
+ their responses on this pipeline */
+ char* master_buffer; /* The master buffer allocated on-demand;
+ used for pipelining. */
+ size_t read_pos; /* Current read position in the master buffer */
+ size_t buf_len; /* Length of the buffer?? */
+
+
+ curl_seek_callback seek_func; /* function that seeks the input */
+ void *seek_client; /* pointer to pass to the seek() above */
+
+ /*************** Request - specific items ************/
+
+ /* previously this was in the urldata struct */
+ curl_read_callback fread_func; /* function that reads the input */
+ void *fread_in; /* pointer to pass to the fread() above */
+
+ struct ntlmdata ntlm; /* NTLM differs from other authentication schemes
+ because it authenticates connections, not
+ single requests! */
+ struct ntlmdata proxyntlm; /* NTLM data for proxy */
+
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ /* used for communication with Samba's winbind daemon helper ntlm_auth */
+ curl_socket_t ntlm_auth_hlpr_socket;
+ pid_t ntlm_auth_hlpr_pid;
+ char* challenge_header;
+ char* response_header;
+#endif
+
+ char syserr_buf [256]; /* buffer for Curl_strerror() */
+
+#ifdef CURLRES_ASYNCH
+ /* data used for the asynch name resolve callback */
+ struct Curl_async async;
+#endif
+
+ /* These three are used for chunked-encoding trailer support */
+ char *trailer; /* allocated buffer to store trailer in */
+ int trlMax; /* allocated buffer size */
+ int trlPos; /* index of where to store data */
+
+ union {
+ struct ftp_conn ftpc;
+ struct http_conn httpc;
+ struct ssh_conn sshc;
+ struct tftp_state_data *tftpc;
+ struct imap_conn imapc;
+ struct pop3_conn pop3c;
+ struct smtp_conn smtpc;
+ struct rtsp_conn rtspc;
+ void *generic; /* RTMP and LDAP use this */
+ } proto;
+
+ int cselect_bits; /* bitmask of socket events */
+ int waitfor; /* current READ/WRITE bits to wait for */
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ int socks5_gssapi_enctype;
+#endif
+
+ bool verifypeer;
+ bool verifyhost;
+
+ /* When this connection is created, store the conditions for the local end
+ bind. This is stored before the actual bind and before any connection is
+ made and will serve the purpose of being used for comparison reasons so
+ that subsequent bound-requested connections aren't accidentally re-using
+ wrong connections. */
+ char *localdev;
+ unsigned short localport;
+ int localportrange;
+
+ /* tunnel as in tunnel through a HTTP proxy with CONNECT */
+ enum {
+ TUNNEL_INIT, /* init/default/no tunnel state */
+ TUNNEL_CONNECT, /* CONNECT has been sent off */
+ TUNNEL_COMPLETE /* CONNECT response received completely */
+ } tunnel_state[2]; /* two separate ones to allow FTP */
+ struct connectbundle *bundle; /* The bundle we are member of */
+
+ enum negotiatenpn negnpn;
+};
+
+/* The end of connectdata. */
+
+/*
+ * Struct to keep statistical and informational data.
+ */
+struct PureInfo {
+ int httpcode; /* Recent HTTP, FTP, or RTSP response code */
+ int httpproxycode; /* response code from proxy when received separate */
+ int httpversion; /* the http version number X.Y = X*10+Y */
+ long filetime; /* If requested, this is might get set. Set to -1 if the time
+ was unretrievable. We cannot have this of type time_t,
+ since time_t is unsigned on several platforms such as
+ OpenVMS. */
+ bool timecond; /* set to TRUE if the time condition didn't match, which
+ thus made the document NOT get fetched */
+ long header_size; /* size of read header(s) in bytes */
+ long request_size; /* the amount of bytes sent in the request(s) */
+ unsigned long proxyauthavail; /* what proxy auth types were announced */
+ unsigned long httpauthavail; /* what host auth types were announced */
+ long numconnects; /* how many new connection did libcurl created */
+ char *contenttype; /* the content type of the object */
+ char *wouldredirect; /* URL this would've been redirected to if asked to */
+
+ /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip'
+ and, 'conn_local_port' are copied over from the connectdata struct in
+ order to allow curl_easy_getinfo() to return this information even when
+ the session handle is no longer associated with a connection, and also
+ allow curl_easy_reset() to clear this information from the session handle
+ without disturbing information which is still alive, and that might be
+ reused, in the connection cache. */
+
+ char conn_primary_ip[MAX_IPADR_LEN];
+ long conn_primary_port;
+
+ char conn_local_ip[MAX_IPADR_LEN];
+ long conn_local_port;
+
+ struct curl_certinfo certs; /* info about the certs, only populated in
+ OpenSSL builds. Asked for with
+ CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+};
+
+
+struct Progress {
+ long lastshow; /* time() of the last displayed progress meter or NULL to
+ force redraw at next call */
+ curl_off_t size_dl; /* total expected size */
+ curl_off_t size_ul; /* total expected size */
+ curl_off_t downloaded; /* transferred so far */
+ curl_off_t uploaded; /* transferred so far */
+
+ curl_off_t current_speed; /* uses the currently fastest transfer */
+
+ bool callback; /* set when progress callback is used */
+ int width; /* screen width at download start */
+ int flags; /* see progress.h */
+
+ double timespent;
+
+ curl_off_t dlspeed;
+ curl_off_t ulspeed;
+
+ double t_nslookup;
+ double t_connect;
+ double t_appconnect;
+ double t_pretransfer;
+ double t_starttransfer;
+ double t_redirect;
+
+ struct timeval start;
+ struct timeval t_startsingle;
+ struct timeval t_startop;
+ struct timeval t_acceptdata;
+#define CURR_TIME (5+1) /* 6 entries for 5 seconds */
+
+ curl_off_t speeder[ CURR_TIME ];
+ struct timeval speeder_time[ CURR_TIME ];
+ int speeder_c;
+};
+
+typedef enum {
+ HTTPREQ_NONE, /* first in list */
+ HTTPREQ_GET,
+ HTTPREQ_POST,
+ HTTPREQ_POST_FORM, /* we make a difference internally */
+ HTTPREQ_PUT,
+ HTTPREQ_HEAD,
+ HTTPREQ_CUSTOM,
+ HTTPREQ_LAST /* last in list */
+} Curl_HttpReq;
+
+typedef enum {
+ RTSPREQ_NONE, /* first in list */
+ RTSPREQ_OPTIONS,
+ RTSPREQ_DESCRIBE,
+ RTSPREQ_ANNOUNCE,
+ RTSPREQ_SETUP,
+ RTSPREQ_PLAY,
+ RTSPREQ_PAUSE,
+ RTSPREQ_TEARDOWN,
+ RTSPREQ_GET_PARAMETER,
+ RTSPREQ_SET_PARAMETER,
+ RTSPREQ_RECORD,
+ RTSPREQ_RECEIVE,
+ RTSPREQ_LAST /* last in list */
+} Curl_RtspReq;
+
+/*
+ * Values that are generated, temporary or calculated internally for a
+ * "session handle" must be defined within the 'struct UrlState'. This struct
+ * will be used within the SessionHandle struct. When the 'SessionHandle'
+ * struct is cloned, this data MUST NOT be copied.
+ *
+ * Remember that any "state" information goes globally for the curl handle.
+ * Session-data MUST be put in the connectdata struct and here. */
+#define MAX_CURL_USER_LENGTH 256
+#define MAX_CURL_PASSWORD_LENGTH 256
+
+struct auth {
+ unsigned long want; /* Bitmask set to the authentication methods wanted by
+ app (with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH). */
+ unsigned long picked;
+ unsigned long avail; /* Bitmask for what the server reports to support for
+ this resource */
+ bool done; /* TRUE when the auth phase is done and ready to do the *actual*
+ request */
+ bool multi; /* TRUE if this is not yet authenticated but within the auth
+ multipass negotiation */
+ bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should
+ be RFC compliant */
+};
+
+struct UrlState {
+
+ /* Points to the connection cache */
+ struct conncache *conn_cache;
+
+ /* when curl_easy_perform() is called, the multi handle is "owned" by
+ the easy handle so curl_easy_cleanup() on such an easy handle will
+ also close the multi handle! */
+ bool multi_owned_by_easy;
+
+ /* buffers to store authentication data in, as parsed from input options */
+ struct timeval keeps_speed; /* for the progress meter really */
+
+ struct connectdata *lastconnect; /* The last connection, NULL if undefined */
+
+ char *headerbuff; /* allocated buffer to store headers in */
+ size_t headersize; /* size of the allocation */
+
+ char buffer[BUFSIZE+1]; /* download buffer */
+ char uploadbuffer[BUFSIZE+1]; /* upload buffer */
+ curl_off_t current_speed; /* the ProgressShow() funcion sets this,
+ bytes / second */
+ bool this_is_a_follow; /* this is a followed Location: request */
+
+ char *first_host; /* if set, this should be the host name that we will
+ sent authorization to, no else. Used to make Location:
+ following not keep sending user+password... This is
+ strdup() data.
+ */
+ struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
+ long sessionage; /* number of the most recent session */
+ char *tempwrite; /* allocated buffer to keep data in when a write
+ callback returns to make the connection paused */
+ size_t tempwritesize; /* size of the 'tempwrite' allocated buffer */
+ int tempwritetype; /* type of the 'tempwrite' buffer as a bitmask that is
+ used with Curl_client_write() */
+ char *scratch; /* huge buffer[BUFSIZE*2] 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. */
+ int os_errno; /* filled in with errno whenever an error occurs */
+#ifdef HAVE_SIGNAL
+ /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
+ void (*prev_signal)(int sig);
+#endif
+ bool allow_port; /* Is set.use_port allowed to take effect or not. This
+ is always set TRUE when curl_easy_perform() is called. */
+ struct digestdata digest; /* state data for host Digest auth */
+ struct digestdata proxydigest; /* state data for proxy Digest auth */
+
+#ifdef USE_SPNEGO
+ struct negotiatedata negotiate; /* state data for host Negotiate auth */
+ struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
+#endif
+
+ struct auth authhost; /* auth details for host */
+ struct auth authproxy; /* auth details for proxy */
+
+ bool authproblem; /* TRUE if there's some problem authenticating */
+
+ void *resolver; /* resolver state, if it is used in the URL state -
+ ares_channel f.e. */
+
+#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
+ ENGINE *engine;
+#endif /* USE_SSLEAY */
+ struct timeval expiretime; /* set this with Curl_expire() only */
+ struct Curl_tree timenode; /* for the splay stuff */
+ struct curl_llist *timeoutlist; /* list of pending timeouts */
+
+ /* a place to store the most recently set FTP entrypath */
+ char *most_recent_ftp_entrypath;
+
+ /* set after initial USER failure, to prevent an authentication loop */
+ bool ftp_trying_alternative;
+
+ int httpversion; /* the lowest HTTP version*10 reported by any server
+ involved in this request */
+ bool expect100header; /* TRUE if we added Expect: 100-continue */
+
+ bool pipe_broke; /* TRUE if the connection we were pipelined on broke
+ and we need to restart from the beginning */
+
+#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \
+ !defined(__SYMBIAN32__)
+/* do FTP line-end conversions on most platforms */
+#define CURL_DO_LINEEND_CONV
+ /* for FTP downloads: track CRLF sequences that span blocks */
+ bool prev_block_had_trailing_cr;
+ /* for FTP downloads: how many CRLFs did we converted to LFs? */
+ curl_off_t crlf_conversions;
+#endif
+ char *pathbuffer;/* allocated buffer to store the URL's path part in */
+ char *path; /* path to use, points to somewhere within the pathbuffer
+ area */
+ bool slash_removed; /* set TRUE if the 'path' points to a path where the
+ initial URL slash separator has been taken off */
+ bool use_range;
+ bool rangestringalloc; /* the range string is malloc()'ed */
+
+ char *range; /* range, if used. See README for detailed specification on
+ this syntax. */
+ curl_off_t resume_from; /* continue [ftp] transfer from here */
+
+ /* This RTSP state information survives requests and connections */
+ long rtsp_next_client_CSeq; /* the session's next client CSeq */
+ long rtsp_next_server_CSeq; /* the session's next server CSeq */
+ long rtsp_CSeq_recv; /* most recent CSeq received */
+
+ /* if true, force SSL connection retry (workaround for certain servers) */
+ bool ssl_connect_retry;
+ curl_off_t infilesize; /* size of file to upload, -1 means unknown.
+ Copied from set.filesize at start of operation */
+};
+
+
+/*
+ * This 'DynamicStatic' struct defines dynamic states that actually change
+ * values in the 'UserDefined' area, which MUST be taken into consideration
+ * if the UserDefined struct is cloned or similar. You can probably just
+ * copy these, but each one indicate a special action on other data.
+ */
+
+struct DynamicStatic {
+ char *url; /* work URL, copied from UserDefined */
+ bool url_alloc; /* URL string is malloc()'ed */
+ char *referer; /* referer string */
+ bool referer_alloc; /* referer sting is malloc()ed */
+ struct curl_slist *cookielist; /* list of cookie files set by
+ curl_easy_setopt(COOKIEFILE) calls */
+ struct curl_slist *resolve; /* set to point to the set.resolve list when
+ this should be dealt with in pretransfer */
+};
+
+/*
+ * This 'UserDefined' struct must only contain data that is set once to go
+ * for many (perhaps) independent connections. Values that are generated or
+ * calculated internally for the "session handle" MUST be defined within the
+ * 'struct UrlState' instead. The only exceptions MUST note the changes in
+ * the 'DynamicStatic' struct.
+ * Character pointer fields point to dynamic storage, unless otherwise stated.
+ */
+
+struct Curl_multi; /* declared and used only in multi.c */
+
+enum dupstring {
+ STRING_CERT, /* client certificate file name */
+ STRING_CERT_TYPE, /* format for certificate (default: PEM)*/
+ STRING_COOKIE, /* HTTP cookie string to send */
+ STRING_COOKIEJAR, /* dump all cookies to this file */
+ STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */
+ STRING_DEVICE, /* local network interface/address to use */
+ STRING_ENCODING, /* Accept-Encoding string */
+ STRING_FTP_ACCOUNT, /* ftp account data */
+ STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
+ STRING_FTPPORT, /* port to send with the FTP PORT command */
+ STRING_KEY, /* private key file name */
+ STRING_KEY_PASSWD, /* plain text private key password */
+ STRING_KEY_TYPE, /* format for private key (default: PEM) */
+ STRING_KRB_LEVEL, /* krb security level */
+ STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find
+ $HOME/.netrc */
+ STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */
+ STRING_PROXY, /* proxy to use */
+ STRING_SET_RANGE, /* range, if used */
+ STRING_SET_REFERER, /* custom string for the HTTP referer field */
+ STRING_SET_URL, /* what original URL to work on */
+ STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
+ STRING_SSL_CAFILE, /* certificate file to verify peer against */
+ STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
+ STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
+ STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
+ STRING_USERAGENT, /* User-Agent string */
+ STRING_SSL_CRLFILE, /* crl file to check certificate */
+ STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
+ STRING_USERNAME, /* <username>, if used */
+ STRING_PASSWORD, /* <password>, if used */
+ STRING_OPTIONS, /* <options>, if used */
+ STRING_PROXYUSERNAME, /* Proxy <username>, if used */
+ STRING_PROXYPASSWORD, /* Proxy <password>, if used */
+ STRING_NOPROXY, /* List of hosts which should not use the proxy, if
+ used */
+ STRING_RTSP_SESSION_ID, /* Session ID to use */
+ STRING_RTSP_STREAM_URI, /* Stream URI for this request */
+ STRING_RTSP_TRANSPORT, /* Transport for this session */
+#ifdef USE_LIBSSH2
+ STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
+ STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */
+ STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
+ STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
+#endif
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */
+#endif
+ STRING_MAIL_FROM,
+ STRING_MAIL_AUTH,
+
+#ifdef USE_TLS_SRP
+ STRING_TLSAUTH_USERNAME, /* TLS auth <username> */
+ STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
+#endif
+
+ STRING_BEARER, /* <bearer>, if used */
+
+ /* -- end of strings -- */
+ STRING_LAST /* not used, just an end-of-list marker */
+};
+
+struct UserDefined {
+ FILE *err; /* the stderr user data goes here */
+ void *debugdata; /* the data that will be passed to fdebug */
+ char *errorbuffer; /* (Static) store failure messages in here */
+ long proxyport; /* If non-zero, use this port number by default. If the
+ proxy string features a ":[port]" that one will override
+ this. */
+ void *out; /* the fetched file goes here */
+ void *in; /* the uploaded file is read from here */
+ void *writeheader; /* write the header to this if non-NULL */
+ void *rtp_out; /* write RTP to this if non-NULL */
+ long use_port; /* which port to use (when not using default) */
+ unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */
+ unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */
+ long followlocation; /* as in HTTP Location: */
+ long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
+ for infinity */
+
+ int keep_post; /* keep POSTs as POSTs after a 30x request; each
+ bit represents a request, from 301 to 303 */
+ bool free_referer; /* set TRUE if 'referer' points to a string we
+ allocated */
+ void *postfields; /* if POST, set the fields' values here */
+ curl_seek_callback seek_func; /* function that seeks the input */
+ curl_off_t postfieldsize; /* if POST, this might have a size to use instead
+ of strlen(), and then the data *may* be binary
+ (contain zero bytes) */
+ unsigned short localport; /* local port number to bind to */
+ int localportrange; /* number of additional port numbers to test in case the
+ 'localport' one can't be bind()ed */
+ curl_write_callback fwrite_func; /* function that stores the output */
+ curl_write_callback fwrite_header; /* function that stores headers */
+ curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */
+ curl_read_callback fread_func; /* function that reads the input */
+ int is_fread_set; /* boolean, has read callback been set to non-NULL? */
+ int is_fwrite_set; /* boolean, has write callback been set to non-NULL? */
+ curl_progress_callback fprogress; /* OLD and deprecated progress callback */
+ curl_xferinfo_callback fxferinfo; /* progress callback */
+ curl_debug_callback fdebug; /* function that write informational data */
+ curl_ioctl_callback ioctl_func; /* function for I/O control */
+ curl_sockopt_callback fsockopt; /* function for setting socket options */
+ void *sockopt_client; /* pointer to pass to the socket options callback */
+ curl_opensocket_callback fopensocket; /* function for checking/translating
+ the address and opening the
+ socket */
+ void* opensocket_client;
+ curl_closesocket_callback fclosesocket; /* function for closing the
+ socket */
+ void* closesocket_client;
+
+ void *seek_client; /* pointer to pass to the seek callback */
+ /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */
+ /* function to convert from the network encoding: */
+ curl_conv_callback convfromnetwork;
+ /* function to convert to the network encoding: */
+ curl_conv_callback convtonetwork;
+ /* function to convert from UTF-8 encoding: */
+ curl_conv_callback convfromutf8;
+
+ void *progress_client; /* pointer to pass to the progress callback */
+ void *ioctl_client; /* pointer to pass to the ioctl callback */
+ long timeout; /* in milliseconds, 0 means no timeout */
+ long connecttimeout; /* in milliseconds, 0 means no timeout */
+ long accepttimeout; /* in milliseconds, 0 means no timeout */
+ long server_response_timeout; /* in milliseconds, 0 means no timeout */
+ long tftp_blksize ; /* in bytes, 0 means use default */
+ curl_off_t filesize; /* size of file to upload, -1 means unknown */
+ long low_speed_limit; /* bytes/second */
+ long low_speed_time; /* number of seconds */
+ curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */
+ curl_off_t max_recv_speed; /* high speed limit in bytes/second for
+ download */
+ curl_off_t set_resume_from; /* continue [ftp] transfer from here */
+ struct curl_slist *headers; /* linked list of extra headers */
+ struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
+ struct curl_httppost *httppost; /* linked list of POST data */
+ bool sep_headers; /* handle host and proxy headers separately */
+ bool cookiesession; /* new cookie session? */
+ bool crlf; /* convert crlf on ftp upload(?) */
+ struct curl_slist *quote; /* after connection is established */
+ struct curl_slist *postquote; /* after the transfer */
+ struct curl_slist *prequote; /* before the transfer, after type */
+ struct curl_slist *source_quote; /* 3rd party quote */
+ struct curl_slist *source_prequote; /* in 3rd party transfer mode - before
+ the transfer on source host */
+ struct curl_slist *source_postquote; /* in 3rd party transfer mode - after
+ the transfer on source host */
+ struct curl_slist *telnet_options; /* linked list of telnet options */
+ struct curl_slist *resolve; /* list of names to add/remove from
+ DNS cache */
+ curl_TimeCond timecondition; /* kind of time/date comparison */
+ time_t timevalue; /* what time to compare with */
+ Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
+ long httpversion; /* when non-zero, a specific HTTP version requested to
+ be used in the library's request(s) */
+ struct ssl_config_data ssl; /* user defined SSL stuff */
+ curl_proxytype proxytype; /* what kind of proxy that is in use */
+ long dns_cache_timeout; /* DNS cache timeout */
+ long buffer_size; /* size of receive buffer to use */
+ void *private_data; /* application-private data */
+
+ struct curl_slist *http200aliases; /* linked list of aliases for http200 */
+
+ long ipver; /* the CURL_IPRESOLVE_* defines in the public header file
+ 0 - whatever, 1 - v2, 2 - v6 */
+
+ curl_off_t max_filesize; /* Maximum file size to download */
+
+ curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */
+
+ int ftp_create_missing_dirs; /* 1 - create directories that don't exist
+ 2 - the same but also allow MKD to fail once
+ */
+
+ curl_sshkeycallback ssh_keyfunc; /* key matching callback */
+ void *ssh_keyfunc_userp; /* custom pointer to callback */
+
+/* Here follows boolean settings that define how to behave during
+ this session. They are STATIC, set by libcurl users or at least initially
+ and they don't change during operations. */
+
+ bool printhost; /* printing host name in debug info */
+ bool get_filetime; /* get the time and get of the remote file */
+ bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */
+ bool prefer_ascii; /* ASCII rather than binary */
+ bool ftp_append; /* append, not overwrite, on upload */
+ bool ftp_list_only; /* switch FTP command for listing directories */
+ bool ftp_use_port; /* use the FTP PORT command */
+ bool hide_progress; /* don't use the progress meter */
+ bool http_fail_on_error; /* fail on HTTP error codes >= 300 */
+ bool http_follow_location; /* follow HTTP redirects */
+ bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */
+ bool http_disable_hostname_check_before_authentication;
+ bool include_header; /* include received protocol headers in data output */
+ bool http_set_referer; /* is a custom referer used */
+ bool http_auto_referer; /* set "correct" referer when following location: */
+ bool opt_no_body; /* as set with CURLOPT_NOBODY */
+ bool set_port; /* custom port number used */
+ bool upload; /* upload request */
+ enum CURL_NETRC_OPTION
+ use_netrc; /* defined in include/curl.h */
+ bool verbose; /* output verbosity */
+ bool krb; /* kerberos connection requested */
+ bool reuse_forbid; /* forbidden to be reused, close after use */
+ bool reuse_fresh; /* do not re-use an existing connection */
+ bool ftp_use_epsv; /* if EPSV is to be attempted or not */
+ bool ftp_use_eprt; /* if EPRT is to be attempted or not */
+ bool ftp_use_pret; /* if PRET is to be used before PASV or not */
+
+ curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
+ IMAP or POP3 or others! */
+ curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
+ curl_ftpccc ftp_ccc; /* FTP CCC options */
+ bool no_signal; /* do not use any signal/alarm handler */
+ bool global_dns_cache; /* subject for future removal */
+ bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */
+ bool ignorecl; /* ignore content length */
+ bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
+ us */
+ bool connect_only; /* make connection, let application use the socket */
+ bool ssl_enable_beast; /* especially allow this flaw for interoperability's
+ sake*/
+ long ssh_auth_types; /* allowed SSH auth types */
+ bool http_te_skip; /* pass the raw body data to the user, even when
+ transfer-encoded (chunked, compressed) */
+ bool http_ce_skip; /* pass the raw body data to the user, even when
+ content-encoded (chunked, compressed) */
+ long new_file_perms; /* Permissions to use when creating remote files */
+ long new_directory_perms; /* Permissions to use when creating remote dirs */
+ bool proxy_transfer_mode; /* set transfer mode (;type=<a|i>) when doing FTP
+ via an HTTP proxy */
+ char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
+ unsigned int scope; /* address scope for IPv6 */
+ long allowed_protocols;
+ long redir_protocols;
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ long socks5_gssapi_nec; /* flag to support nec socks5 server */
+#endif
+ struct curl_slist *mail_rcpt; /* linked list of mail recipients */
+ bool sasl_ir; /* Enable/disable SASL initial response */
+ /* Common RTSP header options */
+ Curl_RtspReq rtspreq; /* RTSP request type */
+ long rtspversion; /* like httpversion, for RTSP */
+ bool wildcardmatch; /* enable wildcard matching */
+ curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer
+ starts */
+ curl_chunk_end_callback chunk_end; /* called after part transferring
+ stopped */
+ curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds
+ to pattern (e.g. if WILDCARDMATCH is on) */
+ void *fnmatch_data;
+
+ long gssapi_delegation; /* GSS-API credential delegation, see the
+ documentation of CURLOPT_GSSAPI_DELEGATION */
+
+ bool tcp_keepalive; /* use TCP keepalives */
+ long tcp_keepidle; /* seconds in idle before sending keepalive probe */
+ long tcp_keepintvl; /* seconds between TCP keepalive probes */
+
+ size_t maxconnects; /* Max idle connections in the connection cache */
+
+ bool ssl_enable_npn; /* TLS NPN extension? */
+ bool ssl_enable_alpn; /* TLS ALPN extension? */
+
+ long expect_100_timeout; /* in milliseconds */
+};
+
+struct Names {
+ struct curl_hash *hostcache;
+ enum {
+ HCACHE_NONE, /* not pointing to anything */
+ HCACHE_GLOBAL, /* points to the (shrug) global one */
+ HCACHE_MULTI, /* points to a shared one in the multi handle */
+ HCACHE_SHARED /* points to a shared one in a shared object */
+ } hostcachetype;
+};
+
+/*
+ * The 'connectdata' struct MUST have all the connection oriented stuff as we
+ * may have several simultaneous connections and connection structs in memory.
+ *
+ * The 'struct UserDefined' must only contain data that is set once to go for
+ * many (perhaps) independent connections. Values that are generated or
+ * calculated internally for the "session handle" must be defined within the
+ * 'struct UrlState' instead.
+ */
+
+struct SessionHandle {
+ /* first, two fields for the linked list of these */
+ struct SessionHandle *next;
+ struct SessionHandle *prev;
+
+ struct connectdata *easy_conn; /* the "unit's" connection */
+
+ CURLMstate mstate; /* the handle's state */
+ CURLcode result; /* previous result */
+
+ struct Curl_message msg; /* A single posted message. */
+
+ /* Array with the plain socket numbers this handle takes care of, in no
+ particular order. Note that all sockets are added to the sockhash, where
+ the state etc are also kept. This array is mostly used to detect when a
+ socket is to be removed from the hash. See singlesocket(). */
+ curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
+ int numsocks;
+
+ struct Names dns;
+ struct Curl_multi *multi; /* if non-NULL, points to the multi handle
+ struct to which this "belongs" when used by
+ the multi interface */
+ struct Curl_multi *multi_easy; /* if non-NULL, points to the multi handle
+ struct to which this "belongs" when used
+ by the easy interface */
+ struct Curl_share *share; /* Share, handles global variable mutexing */
+ struct SingleRequest req; /* Request-specific data */
+ struct UserDefined set; /* values set by the libcurl user */
+ struct DynamicStatic change; /* possibly modified userdefined data */
+ struct CookieInfo *cookies; /* the cookies, read from files and servers.
+ NOTE that the 'cookie' field in the
+ UserDefined struct defines if the "engine"
+ is to be used or not. */
+ struct Progress progress; /* for all the progress meter data */
+ struct UrlState state; /* struct for fields used for state info and
+ other dynamic purposes */
+ struct WildcardData wildcard; /* wildcard download state info */
+ struct PureInfo info; /* stats, reports and info data */
+ struct curl_tlssessioninfo tsi; /* Information about the TLS session, only
+ valid after a client has asked for it */
+#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
+ iconv_t outbound_cd; /* for translating to the network encoding */
+ iconv_t inbound_cd; /* for translating from the network encoding */
+ iconv_t utf8_cd; /* for translating to UTF8 */
+#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
+ unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */
+};
+
+#define LIBCURL_NAME "libcurl"
+
+#endif /* HEADER_CURL_URLDATA_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/version.c b/external/libcurl_android/jni/libcurl/lib/version.c
new file mode 100755
index 00000000..788f3e9d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/version.c
@@ -0,0 +1,349 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "vtls/vtls.h"
+#include "http2.h"
+
+#define _MPRINTF_REPLACE /* use the internal *printf() functions */
+#include <curl/mprintf.h>
+
+#ifdef USE_ARES
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+# define CARES_STATICLIB
+# endif
+# include <ares.h>
+#endif
+
+#ifdef USE_LIBIDN
+#include <stringprep.h>
+#endif
+
+#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
+#include <iconv.h>
+#endif
+
+#ifdef USE_LIBRTMP
+#include <librtmp/rtmp.h>
+#endif
+
+#ifdef USE_LIBSSH2
+#include <libssh2.h>
+#endif
+
+#ifdef HAVE_LIBSSH2_VERSION
+/* get it run-time if possible */
+#define CURL_LIBSSH2_VERSION libssh2_version(0)
+#else
+/* use build-time if run-time not possible */
+#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION
+#endif
+
+char *curl_version(void)
+{
+ static char version[200];
+ char *ptr = version;
+ size_t len;
+ size_t left = sizeof(version);
+
+ strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION);
+ len = strlen(ptr);
+ left -= len;
+ ptr += len;
+
+ if(left > 1) {
+ len = Curl_ssl_version(ptr + 1, left - 1);
+
+ if(len > 0) {
+ *ptr = ' ';
+ left -= ++len;
+ ptr += len;
+ }
+ }
+
+#ifdef HAVE_LIBZ
+ len = snprintf(ptr, left, " zlib/%s", zlibVersion());
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_ARES
+ /* this function is only present in c-ares, not in the original ares */
+ len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL));
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_LIBIDN
+ if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
+ len = snprintf(ptr, left, " libidn/%s", stringprep_check_version(NULL));
+ left -= len;
+ ptr += len;
+ }
+#endif
+#ifdef USE_WIN32_IDN
+ len = snprintf(ptr, left, " WinIDN");
+ left -= len;
+ ptr += len;
+#endif
+#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
+#ifdef _LIBICONV_VERSION
+ len = snprintf(ptr, left, " iconv/%d.%d",
+ _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
+#else
+ /* version unknown */
+ len = snprintf(ptr, left, " iconv");
+#endif /* _LIBICONV_VERSION */
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_LIBSSH2
+ len = snprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION);
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_NGHTTP2
+ len = Curl_http2_ver(ptr, left);
+ left -= len;
+ ptr += len;
+#endif
+#ifdef USE_LIBRTMP
+ {
+ char suff[2];
+ if(RTMP_LIB_VERSION & 0xff) {
+ suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1;
+ suff[1] = '\0';
+ }
+ else
+ suff[0] = '\0';
+
+ snprintf(ptr, left, " librtmp/%d.%d%s",
+ RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
+ suff);
+/*
+ If another lib version is added below this one, this code would
+ also have to do:
+
+ len = what snprintf() returned
+
+ left -= len;
+ ptr += len;
+*/
+ }
+#endif
+
+ return version;
+}
+
+/* data for curl_version_info
+
+ Keep the list sorted alphabetically. It is also written so that each
+ protocol line has its own #if line to make things easier on the eye.
+ */
+
+static const char * const protocols[] = {
+#ifndef CURL_DISABLE_DICT
+ "dict",
+#endif
+#ifndef CURL_DISABLE_FILE
+ "file",
+#endif
+#ifndef CURL_DISABLE_FTP
+ "ftp",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
+ "ftps",
+#endif
+#ifndef CURL_DISABLE_GOPHER
+ "gopher",
+#endif
+#ifndef CURL_DISABLE_HTTP
+ "http",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ "https",
+#endif
+#ifndef CURL_DISABLE_IMAP
+ "imap",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
+ "imaps",
+#endif
+#ifndef CURL_DISABLE_LDAP
+ "ldap",
+#if !defined(CURL_DISABLE_LDAPS) && \
+ ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+ (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+ "ldaps",
+#endif
+#endif
+#ifndef CURL_DISABLE_POP3
+ "pop3",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
+ "pop3s",
+#endif
+#ifdef USE_LIBRTMP
+ "rtmp",
+#endif
+#ifndef CURL_DISABLE_RTSP
+ "rtsp",
+#endif
+#ifdef USE_LIBSSH2
+ "scp",
+#endif
+#ifdef USE_LIBSSH2
+ "sftp",
+#endif
+#ifndef CURL_DISABLE_SMTP
+ "smtp",
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
+ "smtps",
+#endif
+#ifndef CURL_DISABLE_TELNET
+ "telnet",
+#endif
+#ifndef CURL_DISABLE_TFTP
+ "tftp",
+#endif
+
+ NULL
+};
+
+static curl_version_info_data version_info = {
+ CURLVERSION_NOW,
+ LIBCURL_VERSION,
+ LIBCURL_VERSION_NUM,
+ OS, /* as found by configure or set by hand at build-time */
+ 0 /* features is 0 by default */
+#ifdef ENABLE_IPV6
+ | CURL_VERSION_IPV6
+#endif
+#ifdef USE_SSL
+ | CURL_VERSION_SSL
+#endif
+#ifdef USE_NTLM
+ | CURL_VERSION_NTLM
+#endif
+#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
+ | CURL_VERSION_NTLM_WB
+#endif
+#ifdef USE_SPNEGO
+ | CURL_VERSION_SPNEGO
+#endif
+#ifdef HAVE_GSSAPI
+ | CURL_VERSION_GSSAPI
+#endif
+#ifdef USE_WINDOWS_SSPI
+ | CURL_VERSION_SSPI
+#endif
+#ifdef HAVE_LIBZ
+ | CURL_VERSION_LIBZ
+#endif
+#ifdef DEBUGBUILD
+ | CURL_VERSION_DEBUG
+#endif
+#ifdef CURLDEBUG
+ | CURL_VERSION_CURLDEBUG
+#endif
+#ifdef CURLRES_ASYNCH
+ | CURL_VERSION_ASYNCHDNS
+#endif
+#if (CURL_SIZEOF_CURL_OFF_T > 4) && \
+ ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
+ | CURL_VERSION_LARGEFILE
+#endif
+#if defined(CURL_DOES_CONVERSIONS)
+ | CURL_VERSION_CONV
+#endif
+#if defined(USE_TLS_SRP)
+ | CURL_VERSION_TLSAUTH_SRP
+#endif
+#if defined(USE_NGHTTP2)
+ | CURL_VERSION_HTTP2
+#endif
+ ,
+ NULL, /* ssl_version */
+ 0, /* ssl_version_num, this is kept at zero */
+ NULL, /* zlib_version */
+ protocols,
+ NULL, /* c-ares version */
+ 0, /* c-ares version numerical */
+ NULL, /* libidn version */
+ 0, /* iconv version */
+ NULL, /* ssh lib version */
+};
+
+curl_version_info_data *curl_version_info(CURLversion stamp)
+{
+#ifdef USE_LIBSSH2
+ static char ssh_buffer[80];
+#endif
+
+#ifdef USE_SSL
+ static char ssl_buffer[80];
+ Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
+ version_info.ssl_version = ssl_buffer;
+#endif
+
+#ifdef HAVE_LIBZ
+ version_info.libz_version = zlibVersion();
+ /* libz left NULL if non-existing */
+#endif
+#ifdef USE_ARES
+ {
+ int aresnum;
+ version_info.ares = ares_version(&aresnum);
+ version_info.ares_num = aresnum;
+ }
+#endif
+#ifdef USE_LIBIDN
+ /* This returns a version string if we use the given version or later,
+ otherwise it returns NULL */
+ version_info.libidn = stringprep_check_version(LIBIDN_REQUIRED_VERSION);
+ if(version_info.libidn)
+ version_info.features |= CURL_VERSION_IDN;
+#elif defined(USE_WIN32_IDN)
+ version_info.features |= CURL_VERSION_IDN;
+#endif
+
+#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
+#ifdef _LIBICONV_VERSION
+ version_info.iconv_ver_num = _LIBICONV_VERSION;
+#else
+ /* version unknown */
+ version_info.iconv_ver_num = -1;
+#endif /* _LIBICONV_VERSION */
+#endif
+
+#ifdef USE_LIBSSH2
+ snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION);
+ version_info.libssh_version = ssh_buffer;
+#endif
+
+ (void)stamp; /* avoid compiler warnings, we don't use this */
+
+ return &version_info;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-axtls.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-axtls.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-axtls.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-curl_darwinssl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-curl_darwinssl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-curl_darwinssl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-curl_schannel.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-curl_schannel.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-curl_schannel.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-cyassl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-cyassl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-cyassl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-gskit.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-gskit.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-gskit.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-gtls.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-gtls.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-gtls.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-nss.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-nss.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-nss.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-openssl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-openssl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-openssl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-polarssl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-polarssl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-polarssl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-polarssl_threadlock.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-polarssl_threadlock.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-polarssl_threadlock.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-qssl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-qssl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-qssl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-vtls.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-vtls.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurl_la-vtls.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-axtls.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-axtls.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-axtls.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-curl_darwinssl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-curl_darwinssl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-curl_darwinssl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-curl_schannel.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-curl_schannel.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-curl_schannel.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-cyassl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-cyassl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-cyassl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-gskit.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-gskit.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-gskit.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-gtls.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-gtls.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-gtls.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-nss.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-nss.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-nss.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-openssl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-openssl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-openssl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-polarssl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-polarssl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-polarssl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-polarssl_threadlock.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-polarssl_threadlock.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-polarssl_threadlock.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-qssl.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-qssl.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-qssl.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-vtls.Plo b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-vtls.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/.deps/libcurlu_la-vtls.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/axtls.c b/external/libcurl_android/jni/libcurl/lib/vtls/axtls.c
new file mode 100755
index 00000000..1b577b15
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/axtls.c
@@ -0,0 +1,684 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
+ * Copyright (C) 2010 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all axTLS-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_AXTLS
+#include <axTLS/ssl.h>
+#include "axtls.h"
+
+#include "sendf.h"
+#include "inet_pton.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+#include "curl_memory.h"
+#include <unistd.h>
+/* The last #include file should be: */
+#include "memdebug.h"
+#include "hostcheck.h"
+
+
+/* Global axTLS init, called from Curl_ssl_init() */
+int Curl_axtls_init(void)
+{
+/* axTLS has no global init. Everything is done through SSL and SSL_CTX
+ * structs stored in connectdata structure. Perhaps can move to axtls.h.
+ */
+ return 1;
+}
+
+int Curl_axtls_cleanup(void)
+{
+ /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */
+ return 1;
+}
+
+static CURLcode map_error_to_curl(int axtls_err)
+{
+ switch (axtls_err) {
+ case SSL_ERROR_NOT_SUPPORTED:
+ case SSL_ERROR_INVALID_VERSION:
+ case -70: /* protocol version alert from server */
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ break;
+ case SSL_ERROR_NO_CIPHER:
+ return CURLE_SSL_CIPHER;
+ break;
+ case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
+ case SSL_ERROR_NO_CERT_DEFINED:
+ case -42: /* bad certificate alert from server */
+ case -43: /* unsupported cert alert from server */
+ case -44: /* cert revoked alert from server */
+ case -45: /* cert expired alert from server */
+ case -46: /* cert unknown alert from server */
+ return CURLE_SSL_CERTPROBLEM;
+ break;
+ case SSL_X509_ERROR(X509_NOT_OK):
+ case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
+ case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
+ case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
+ case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
+ case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
+ case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
+ case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
+ case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
+ return CURLE_PEER_FAILED_VERIFICATION;
+ break;
+ case -48: /* unknown ca alert from server */
+ return CURLE_SSL_CACERT;
+ break;
+ case -49: /* access denied alert from server */
+ return CURLE_REMOTE_ACCESS_DENIED;
+ break;
+ case SSL_ERROR_CONN_LOST:
+ case SSL_ERROR_SOCK_SETUP_FAILURE:
+ case SSL_ERROR_INVALID_HANDSHAKE:
+ case SSL_ERROR_INVALID_PROT_MSG:
+ case SSL_ERROR_INVALID_HMAC:
+ case SSL_ERROR_INVALID_SESSION:
+ case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */
+ case SSL_ERROR_FINISHED_INVALID:
+ case SSL_ERROR_NO_CLIENT_RENOG:
+ default:
+ return CURLE_SSL_CONNECT_ERROR;
+ break;
+ }
+}
+
+static Curl_recv axtls_recv;
+static Curl_send axtls_send;
+
+static void free_ssl_structs(struct ssl_connect_data *connssl)
+{
+ if(connssl->ssl) {
+ ssl_free (connssl->ssl);
+ connssl->ssl = NULL;
+ }
+ if(connssl->ssl_ctx) {
+ ssl_ctx_free(connssl->ssl_ctx);
+ connssl->ssl_ctx = NULL;
+ }
+}
+
+/*
+ * For both blocking and non-blocking connects, this function sets up the
+ * ssl context and state. This function is called after the TCP connect
+ * has completed.
+ */
+static CURLcode connect_prep(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ SSL_CTX *ssl_ctx;
+ SSL *ssl = NULL;
+ int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
+ int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
+ int i, ssl_fcn_return;
+ const uint8_t *ssl_sessionid;
+ size_t ssl_idsize;
+
+ /* Assuming users will not compile in custom key/cert to axTLS.
+ * Also, even for blocking connects, use axTLS non-blocking feature.
+ */
+ uint32_t client_option = SSL_NO_DEFAULT_KEY |
+ SSL_SERVER_VERIFY_LATER |
+ SSL_CONNECT_IN_PARTS;
+
+ if(conn->ssl[sockindex].state == ssl_connection_complete)
+ /* to make us tolerant against being called more than once for the
+ same connection */
+ return CURLE_OK;
+
+ /* axTLS only supports TLSv1 */
+ /* check to see if we've been told to use an explicit SSL/TLS version */
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ break;
+ default:
+ failf(data, "axTLS only supports TLS 1.0 and 1.1, "
+ "and it cannot be specified which one to use");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+#ifdef AXTLSDEBUG
+ client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
+#endif /* AXTLSDEBUG */
+
+ /* Allocate an SSL_CTX struct */
+ ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
+ if(ssl_ctx == NULL) {
+ failf(data, "unable to create client SSL context");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ conn->ssl[sockindex].ssl_ctx = ssl_ctx;
+ conn->ssl[sockindex].ssl = NULL;
+
+ /* Load the trusted CA cert bundle file */
+ if(data->set.ssl.CAfile) {
+ if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
+ != SSL_OK) {
+ infof(data, "error reading ca cert file %s \n",
+ data->set.ssl.CAfile);
+ if(data->set.ssl.verifypeer) {
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
+ }
+
+ /* gtls.c tasks we're skipping for now:
+ * 1) certificate revocation list checking
+ * 2) dns name assignment to host
+ * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore
+ * 4) set certificate priority. axTLS ignores type and sends certs in
+ * order added. can probably ignore this.
+ */
+
+ /* Load client certificate */
+ if(data->set.str[STRING_CERT]) {
+ i=0;
+ /* Instead of trying to analyze cert type here, let axTLS try them all. */
+ while(cert_types[i] != 0) {
+ ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
+ data->set.str[STRING_CERT], NULL);
+ if(ssl_fcn_return == SSL_OK) {
+ infof(data, "successfully read cert file %s \n",
+ data->set.str[STRING_CERT]);
+ break;
+ }
+ i++;
+ }
+ /* Tried all cert types, none worked. */
+ if(cert_types[i] == 0) {
+ failf(data, "%s is not x509 or pkcs12 format",
+ data->set.str[STRING_CERT]);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* Load client key.
+ If a pkcs12 file successfully loaded a cert, then there's nothing to do
+ because the key has already been loaded. */
+ if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
+ i=0;
+ /* Instead of trying to analyze key type here, let axTLS try them all. */
+ while(key_types[i] != 0) {
+ ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
+ data->set.str[STRING_KEY], NULL);
+ if(ssl_fcn_return == SSL_OK) {
+ infof(data, "successfully read key file %s \n",
+ data->set.str[STRING_KEY]);
+ break;
+ }
+ i++;
+ }
+ /* Tried all key types, none worked. */
+ if(key_types[i] == 0) {
+ failf(data, "Failure: %s is not a supported key file",
+ data->set.str[STRING_KEY]);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* gtls.c does more here that is being left out for now
+ * 1) set session credentials. can probably ignore since axtls puts this
+ * info in the ssl_ctx struct
+ * 2) setting up callbacks. these seem gnutls specific
+ */
+
+ /* In axTLS, handshaking happens inside ssl_client_new. */
+ if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
+ /* we got a session id, use it! */
+ infof (data, "SSL re-using session ID\n");
+ ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
+ ssl_sessionid, (uint8_t)ssl_idsize);
+ }
+ else
+ ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
+
+ conn->ssl[sockindex].ssl = ssl;
+ return CURLE_OK;
+}
+
+/*
+ * For both blocking and non-blocking connects, this function finalizes the
+ * SSL connection.
+ */
+static CURLcode connect_finish(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ SSL *ssl = conn->ssl[sockindex].ssl;
+ const uint8_t *ssl_sessionid;
+ size_t ssl_idsize;
+ const char *peer_CN;
+ uint32_t dns_altname_index;
+ const char *dns_altname;
+ int8_t found_subject_alt_names = 0;
+ int8_t found_subject_alt_name_matching_conn = 0;
+
+ /* Here, gtls.c gets the peer certificates and fails out depending on
+ * settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
+ */
+
+ /* Verify server's certificate */
+ if(data->set.ssl.verifypeer) {
+ if(ssl_verify_cert(ssl) != SSL_OK) {
+ Curl_axtls_close(conn, sockindex);
+ failf(data, "server cert verify failed");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ else
+ infof(data, "\t server certificate verification SKIPPED\n");
+
+ /* Here, gtls.c does issuer verification. axTLS has no straightforward
+ * equivalent, so omitting for now.*/
+
+ /* Here, gtls.c does the following
+ * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but
+ * it seems useful. This is now implemented, by Oscar Koeroo
+ * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert
+ * 3) displays a bunch of cert information. axTLS doesn't support most of
+ * this, but a couple fields are available.
+ */
+
+ /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
+ risk of an inifite loop */
+ for(dns_altname_index = 0; ; dns_altname_index++) {
+ dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
+ if(dns_altname == NULL) {
+ break;
+ }
+ found_subject_alt_names = 1;
+
+ infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
+ dns_altname, conn->host.name);
+ if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
+ found_subject_alt_name_matching_conn = 1;
+ break;
+ }
+ }
+
+ /* RFC2818 checks */
+ if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
+ if(data->set.ssl.verifyhost) {
+ /* Break connection ! */
+ Curl_axtls_close(conn, sockindex);
+ failf(data, "\tsubjectAltName(s) do not match %s\n",
+ conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\tsubjectAltName(s) do not match %s\n",
+ conn->host.dispname);
+ }
+ else if(found_subject_alt_names == 0) {
+ /* Per RFC2818, when no Subject Alt Names were available, examine the peer
+ CN as a legacy fallback */
+ peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
+ if(peer_CN == NULL) {
+ if(data->set.ssl.verifyhost) {
+ Curl_axtls_close(conn, sockindex);
+ failf(data, "unable to obtain common name from peer certificate");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "unable to obtain common name from peer certificate");
+ }
+ else {
+ if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
+ if(data->set.ssl.verifyhost) {
+ /* Break connection ! */
+ Curl_axtls_close(conn, sockindex);
+ failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
+ peer_CN, conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
+ peer_CN, conn->host.dispname);
+ }
+ }
+ }
+
+ /* General housekeeping */
+ conn->ssl[sockindex].state = ssl_connection_complete;
+ conn->recv[sockindex] = axtls_recv;
+ conn->send[sockindex] = axtls_send;
+
+ /* Put our freshly minted SSL session in cache */
+ ssl_idsize = ssl_get_session_id_size(ssl);
+ ssl_sessionid = ssl_get_session_id(ssl);
+ if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
+ != CURLE_OK)
+ infof (data, "failed to add session to cache\n");
+
+ return CURLE_OK;
+}
+
+/*
+ * Use axTLS's non-blocking connection feature to open an SSL connection.
+ * This is called after a TCP connection is already established.
+ */
+CURLcode Curl_axtls_connect_nonblocking(
+ struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ CURLcode conn_step;
+ int ssl_fcn_return;
+ int i;
+
+ *done = FALSE;
+ /* connectdata is calloc'd and connecting_state is only changed in this
+ function, so this is safe, as the state is effectively initialized. */
+ if(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
+ conn_step = connect_prep(conn, sockindex);
+ if(conn_step != CURLE_OK) {
+ Curl_axtls_close(conn, sockindex);
+ return conn_step;
+ }
+ conn->ssl[sockindex].connecting_state = ssl_connect_2;
+ }
+
+ if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
+ /* Check to make sure handshake was ok. */
+ if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
+ /* Loop to perform more work in between sleeps. This is work around the
+ fact that axtls does not expose any knowledge about when work needs
+ to be performed. This can save ~25% of time on SSL handshakes. */
+ for(i=0; i<5; i++) {
+ ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
+ if(ssl_fcn_return < 0) {
+ Curl_axtls_close(conn, sockindex);
+ ssl_display_error(ssl_fcn_return); /* goes to stdout. */
+ return map_error_to_curl(ssl_fcn_return);
+ }
+ return CURLE_OK;
+ }
+ }
+ infof (conn->data, "handshake completed successfully\n");
+ conn->ssl[sockindex].connecting_state = ssl_connect_3;
+ }
+
+ if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
+ conn_step = connect_finish(conn, sockindex);
+ if(conn_step != CURLE_OK) {
+ Curl_axtls_close(conn, sockindex);
+ return conn_step;
+ }
+
+ /* Reset connect state */
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* Unrecognized state. Things are very bad. */
+ conn->ssl[sockindex].state = ssl_connection_none;
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ /* Return value perhaps not strictly correct, but distinguishes the issue.*/
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+}
+
+
+/*
+ * This function is called after the TCP connect has completed. Setup the TLS
+ * layer and do all necessary magic for a blocking connect.
+ */
+CURLcode
+Curl_axtls_connect(struct connectdata *conn,
+ int sockindex)
+
+{
+ CURLcode conn_step = connect_prep(conn, sockindex);
+ int ssl_fcn_return;
+ SSL *ssl = conn->ssl[sockindex].ssl;
+
+ if(conn_step != CURLE_OK) {
+ Curl_axtls_close(conn, sockindex);
+ return conn_step;
+ }
+
+ /* Check to make sure handshake was ok. */
+ while(ssl_handshake_status(ssl) != SSL_OK) {
+ ssl_fcn_return = ssl_read(ssl, NULL);
+ if(ssl_fcn_return < 0) {
+ Curl_axtls_close(conn, sockindex);
+ ssl_display_error(ssl_fcn_return); /* goes to stdout. */
+ return map_error_to_curl(ssl_fcn_return);
+ }
+ usleep(10000);
+ /* TODO: check for timeout as this could hang indefinitely otherwise */
+ }
+ infof (conn->data, "handshake completed successfully\n");
+
+ conn_step = connect_finish(conn, sockindex);
+ if(conn_step != CURLE_OK) {
+ Curl_axtls_close(conn, sockindex);
+ return conn_step;
+ }
+
+ return CURLE_OK;
+}
+
+/* return number of sent (non-SSL) bytes */
+static ssize_t axtls_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *err)
+{
+ /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
+ int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
+
+ infof(conn->data, " axtls_send\n");
+
+ if(rc < 0 ) {
+ *err = map_error_to_curl(rc);
+ rc = -1; /* generic error code for send failure */
+ }
+
+ *err = CURLE_OK;
+ return rc;
+}
+
+void Curl_axtls_close_all(struct SessionHandle *data)
+{
+ (void)data;
+ infof(data, " Curl_axtls_close_all\n");
+}
+
+void Curl_axtls_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ infof(conn->data, " Curl_axtls_close\n");
+
+ /* line from openssl.c: (void)SSL_shutdown(connssl->ssl);
+ axTLS compat layer does nothing for SSL_shutdown */
+
+ /* The following line is from openssl.c. There seems to be no axTLS
+ equivalent. ssl_free and ssl_ctx_free close things.
+ SSL_set_connect_state(connssl->handle); */
+
+ free_ssl_structs(connssl);
+}
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
+{
+ /* Outline taken from openssl.c since functions are in axTLS compat layer.
+ axTLS's error set is much smaller, so a lot of error-handling was removed.
+ */
+ int retval = 0;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ uint8_t *buf;
+ ssize_t nread;
+
+ infof(conn->data, " Curl_axtls_shutdown\n");
+
+ /* This has only been tested on the proftpd server, and the mod_tls code
+ sends a close notify alert without waiting for a close notify alert in
+ response. Thus we wait for a close notify alert from the server, but
+ we do not send one. Let's hope other servers do the same... */
+
+ /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
+ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
+ (void)SSL_shutdown(connssl->ssl);
+ */
+
+ if(connssl->ssl) {
+ int what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ if(what > 0) {
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server. buf is managed internally by
+ axTLS and will be released upon calling ssl_free via
+ free_ssl_structs. */
+ nread = (ssize_t)ssl_read(connssl->ssl, &buf);
+
+ if(nread < SSL_OK) {
+ failf(data, "close notify alert not received during shutdown");
+ retval = -1;
+ }
+ }
+ else if(0 == what) {
+ /* timeout */
+ failf(data, "SSL shutdown timeout");
+ }
+ else {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ retval = -1;
+ }
+
+ free_ssl_structs(connssl);
+ }
+ return retval;
+}
+
+static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ CURLcode *err)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
+ ssize_t ret = 0;
+ uint8_t *read_buf;
+
+ infof(conn->data, " axtls_recv\n");
+
+ *err = CURLE_OK;
+ if(connssl) {
+ ret = ssl_read(connssl->ssl, &read_buf);
+ if(ret > SSL_OK) {
+ /* ssl_read returns SSL_OK if there is more data to read, so if it is
+ larger, then all data has been read already. */
+ memcpy(buf, read_buf,
+ (size_t)ret > buffersize ? buffersize : (size_t)ret);
+ }
+ else if(ret == SSL_OK) {
+ /* more data to be read, signal caller to call again */
+ *err = CURLE_AGAIN;
+ ret = -1;
+ }
+ else if(ret == -3) {
+ /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
+ team approves proposed fix. */
+ Curl_axtls_close(conn, num);
+ }
+ else {
+ failf(conn->data, "axTLS recv error (%d)", ret);
+ *err = map_error_to_curl((int) ret);
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+int Curl_axtls_check_cxn(struct connectdata *conn)
+{
+ /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
+ axTLS compat layer always returns the last argument, so connection is
+ always alive? */
+
+ infof(conn->data, " Curl_axtls_check_cxn\n");
+ return 1; /* connection still in place */
+}
+
+void Curl_axtls_session_free(void *ptr)
+{
+ (void)ptr;
+ /* free the ID */
+ /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL
+ compatibility layer does nothing, so we do nothing too. */
+}
+
+size_t Curl_axtls_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "axTLS/%s", ssl_version());
+}
+
+int Curl_axtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+ static bool ssl_seeded = FALSE;
+ (void)data;
+ if(!ssl_seeded) {
+ ssl_seeded = TRUE;
+ /* Initialize the seed if not already done. This call is not exactly thread
+ * safe (and neither is the ssl_seeded check), but the worst effect of a
+ * race condition is that some global resources will leak. */
+ RNG_initialize();
+ }
+ get_random(length, entropy);
+ return 0;
+}
+
+#endif /* USE_AXTLS */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/axtls.h b/external/libcurl_android/jni/libcurl/lib/vtls/axtls.h
new file mode 100755
index 00000000..0459cf22
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/axtls.h
@@ -0,0 +1,72 @@
+#ifndef HEADER_CURL_AXTLS_H
+#define HEADER_CURL_AXTLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, DirecTV
+ * contact: Eric Hu <ehu@directv.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifdef USE_AXTLS
+#include "curl/curl.h"
+#include "urldata.h"
+
+int Curl_axtls_init(void);
+int Curl_axtls_cleanup(void);
+CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex);
+CURLcode Curl_axtls_connect_nonblocking(
+ struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+/* tell axTLS to close down all open information regarding connections (and
+ thus session ID caching etc) */
+void Curl_axtls_close_all(struct SessionHandle *data);
+
+ /* close a SSL connection */
+void Curl_axtls_close(struct connectdata *conn, int sockindex);
+
+void Curl_axtls_session_free(void *ptr);
+size_t Curl_axtls_version(char *buffer, size_t size);
+int Curl_axtls_shutdown(struct connectdata *conn, int sockindex);
+int Curl_axtls_check_cxn(struct connectdata *conn);
+int Curl_axtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length);
+
+/* API setup for axTLS */
+#define curlssl_init Curl_axtls_init
+#define curlssl_cleanup Curl_axtls_cleanup
+#define curlssl_connect Curl_axtls_connect
+#define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking
+#define curlssl_session_free(x) Curl_axtls_session_free(x)
+#define curlssl_close_all Curl_axtls_close_all
+#define curlssl_close Curl_axtls_close
+#define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y)
+#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_axtls_version
+#define curlssl_check_cxn(x) Curl_axtls_check_cxn(x)
+#define curlssl_data_pending(x,y) (x=x, y=y, 0)
+#define curlssl_random(x,y,z) Curl_axtls_random(x,y,z)
+#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS
+#endif /* USE_AXTLS */
+#endif /* HEADER_CURL_AXTLS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/curl_darwinssl.c b/external/libcurl_android/jni/libcurl/lib/vtls/curl_darwinssl.c
new file mode 100755
index 00000000..f229c6fe
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/curl_darwinssl.c
@@ -0,0 +1,2485 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all iOS and Mac OS X SecureTransport-specific code for the
+ * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
+ */
+
+#include "curl_setup.h"
+
+#include "urldata.h" /* for the SessionHandle definition */
+#include "curl_base64.h"
+#include "strtok.h"
+
+#ifdef USE_DARWINSSL
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <Security/Security.h>
+#include <Security/SecureTransport.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CommonCrypto/CommonDigest.h>
+
+/* The Security framework has changed greatly between iOS and different OS X
+ versions, and we will try to support as many of them as we can (back to
+ Leopard and iOS 5) by using macros and weak-linking.
+
+ IMPORTANT: If TLS 1.1 and 1.2 support are important for you on OS X, then
+ you must build this project against the 10.8 SDK or later. */
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
+#error "The darwinssl back-end requires Leopard or later."
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
+
+#define CURL_BUILD_IOS 0
+#define CURL_BUILD_IOS_7 0
+#define CURL_BUILD_MAC 1
+/* This is the maximum API level we are allowed to use when building: */
+#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
+/* These macros mean "the following code is present to allow runtime backward
+ compatibility with at least this cat or earlier":
+ (You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET
+ environmental variable.) */
+#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
+#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
+#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
+#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
+#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
+
+#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
+#define CURL_BUILD_IOS 1
+#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
+#define CURL_BUILD_MAC 0
+#define CURL_BUILD_MAC_10_5 0
+#define CURL_BUILD_MAC_10_6 0
+#define CURL_BUILD_MAC_10_7 0
+#define CURL_BUILD_MAC_10_8 0
+#define CURL_SUPPORT_MAC_10_5 0
+#define CURL_SUPPORT_MAC_10_6 0
+#define CURL_SUPPORT_MAC_10_7 0
+#define CURL_SUPPORT_MAC_10_8 0
+
+#else
+#error "The darwinssl back-end requires iOS or OS X."
+#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
+
+#if CURL_BUILD_MAC
+#include <sys/sysctl.h>
+#endif /* CURL_BUILD_MAC */
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "connect.h"
+#include "select.h"
+#include "vtls.h"
+#include "curl_darwinssl.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* From MacTypes.h (which we can't include because it isn't present in iOS: */
+#define ioErr -36
+#define paramErr -50
+
+/* The following two functions were ripped from Apple sample code,
+ * with some modifications: */
+static OSStatus SocketRead(SSLConnectionRef connection,
+ void *data, /* owned by
+ * caller, data
+ * RETURNED */
+ size_t *dataLength) /* IN/OUT */
+{
+ size_t bytesToGo = *dataLength;
+ size_t initLen = bytesToGo;
+ UInt8 *currData = (UInt8 *)data;
+ /*int sock = *(int *)connection;*/
+ struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
+ int sock = connssl->ssl_sockfd;
+ OSStatus rtn = noErr;
+ size_t bytesRead;
+ ssize_t rrtn;
+ int theErr;
+
+ *dataLength = 0;
+
+ for(;;) {
+ bytesRead = 0;
+ rrtn = read(sock, currData, bytesToGo);
+ if(rrtn <= 0) {
+ /* this is guesswork... */
+ theErr = errno;
+ if(rrtn == 0) { /* EOF = server hung up */
+ /* the framework will turn this into errSSLClosedNoNotify */
+ rtn = errSSLClosedGraceful;
+ }
+ else /* do the switch */
+ switch(theErr) {
+ case ENOENT:
+ /* connection closed */
+ rtn = errSSLClosedGraceful;
+ break;
+ case ECONNRESET:
+ rtn = errSSLClosedAbort;
+ break;
+ case EAGAIN:
+ rtn = errSSLWouldBlock;
+ connssl->ssl_direction = false;
+ break;
+ default:
+ rtn = ioErr;
+ break;
+ }
+ break;
+ }
+ else {
+ bytesRead = rrtn;
+ }
+ bytesToGo -= bytesRead;
+ currData += bytesRead;
+
+ if(bytesToGo == 0) {
+ /* filled buffer with incoming data, done */
+ break;
+ }
+ }
+ *dataLength = initLen - bytesToGo;
+
+ return rtn;
+}
+
+static OSStatus SocketWrite(SSLConnectionRef connection,
+ const void *data,
+ size_t *dataLength) /* IN/OUT */
+{
+ size_t bytesSent = 0;
+ /*int sock = *(int *)connection;*/
+ struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
+ int sock = connssl->ssl_sockfd;
+ ssize_t length;
+ size_t dataLen = *dataLength;
+ const UInt8 *dataPtr = (UInt8 *)data;
+ OSStatus ortn;
+ int theErr;
+
+ *dataLength = 0;
+
+ do {
+ length = write(sock,
+ (char*)dataPtr + bytesSent,
+ dataLen - bytesSent);
+ } while((length > 0) &&
+ ( (bytesSent += length) < dataLen) );
+
+ if(length <= 0) {
+ theErr = errno;
+ if(theErr == EAGAIN) {
+ ortn = errSSLWouldBlock;
+ connssl->ssl_direction = true;
+ }
+ else {
+ ortn = ioErr;
+ }
+ }
+ else {
+ ortn = noErr;
+ }
+ *dataLength = bytesSent;
+ return ortn;
+}
+
+CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
+ switch (cipher) {
+ /* SSL version 3.0 */
+ case SSL_RSA_WITH_NULL_MD5:
+ return "SSL_RSA_WITH_NULL_MD5";
+ break;
+ case SSL_RSA_WITH_NULL_SHA:
+ return "SSL_RSA_WITH_NULL_SHA";
+ break;
+ case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
+ return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
+ break;
+ case SSL_RSA_WITH_RC4_128_MD5:
+ return "SSL_RSA_WITH_RC4_128_MD5";
+ break;
+ case SSL_RSA_WITH_RC4_128_SHA:
+ return "SSL_RSA_WITH_RC4_128_SHA";
+ break;
+ case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
+ return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
+ break;
+ case SSL_RSA_WITH_IDEA_CBC_SHA:
+ return "SSL_RSA_WITH_IDEA_CBC_SHA";
+ break;
+ case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ return "SSL_RSA_WITH_DES_CBC_SHA";
+ break;
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DH_DSS_WITH_DES_CBC_SHA:
+ return "SSL_DH_DSS_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DH_RSA_WITH_DES_CBC_SHA:
+ return "SSL_DH_RSA_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
+ return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
+ break;
+ case SSL_DH_anon_WITH_RC4_128_MD5:
+ return "SSL_DH_anon_WITH_RC4_128_MD5";
+ break;
+ case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
+ return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
+ break;
+ case SSL_DH_anon_WITH_DES_CBC_SHA:
+ return "SSL_DH_anon_WITH_DES_CBC_SHA";
+ break;
+ case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
+ return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
+ break;
+ case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
+ return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
+ break;
+ /* TLS 1.0 with AES (RFC 3268)
+ (Apparently these are used in SSLv3 implementations as well.) */
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
+ break;
+ /* SSL version 2.0 */
+ case SSL_RSA_WITH_RC2_CBC_MD5:
+ return "SSL_RSA_WITH_RC2_CBC_MD5";
+ break;
+ case SSL_RSA_WITH_IDEA_CBC_MD5:
+ return "SSL_RSA_WITH_IDEA_CBC_MD5";
+ break;
+ case SSL_RSA_WITH_DES_CBC_MD5:
+ return "SSL_RSA_WITH_DES_CBC_MD5";
+ break;
+ case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
+ return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
+ break;
+ }
+ return "SSL_NULL_WITH_NULL_NULL";
+}
+
+CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
+ switch(cipher) {
+ /* TLS 1.0 with AES (RFC 3268) */
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA:
+ return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA:
+ return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
+ break;
+#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
+ /* TLS 1.0 with ECDSA (RFC 4492) */
+ case TLS_ECDH_ECDSA_WITH_NULL_SHA:
+ return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
+ break;
+ case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_NULL_SHA:
+ return "TLS_ECDH_RSA_WITH_NULL_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_NULL_SHA:
+ return "TLS_ECDHE_RSA_WITH_NULL_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_NULL_SHA:
+ return "TLS_ECDH_anon_WITH_NULL_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_RC4_128_SHA:
+ return "TLS_ECDH_anon_WITH_RC4_128_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
+ return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
+ return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
+ break;
+#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ /* TLS 1.2 (RFC 5246) */
+ case TLS_RSA_WITH_NULL_MD5:
+ return "TLS_RSA_WITH_NULL_MD5";
+ break;
+ case TLS_RSA_WITH_NULL_SHA:
+ return "TLS_RSA_WITH_NULL_SHA";
+ break;
+ case TLS_RSA_WITH_RC4_128_MD5:
+ return "TLS_RSA_WITH_RC4_128_MD5";
+ break;
+ case TLS_RSA_WITH_RC4_128_SHA:
+ return "TLS_RSA_WITH_RC4_128_SHA";
+ break;
+ case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_RSA_WITH_NULL_SHA256:
+ return "TLS_RSA_WITH_NULL_SHA256";
+ break;
+ case TLS_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_RSA_WITH_AES_256_CBC_SHA256:
+ return "TLS_RSA_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+ return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+ return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+ return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+ return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+ return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
+ break;
+ case TLS_DH_anon_WITH_RC4_128_MD5:
+ return "TLS_DH_anon_WITH_RC4_128_MD5";
+ break;
+ case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
+ return "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
+ return "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
+ break;
+ /* TLS 1.2 with AES GCM (RFC 5288) */
+ case TLS_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+ return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+ return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+ return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+ return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
+ return "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
+ return "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
+ break;
+ /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+ return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+ return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+ return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+ return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+ return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_EMPTY_RENEGOTIATION_INFO_SCSV:
+ return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
+ break;
+#else
+ case SSL_RSA_WITH_NULL_MD5:
+ return "TLS_RSA_WITH_NULL_MD5";
+ break;
+ case SSL_RSA_WITH_NULL_SHA:
+ return "TLS_RSA_WITH_NULL_SHA";
+ break;
+ case SSL_RSA_WITH_RC4_128_MD5:
+ return "TLS_RSA_WITH_RC4_128_MD5";
+ break;
+ case SSL_RSA_WITH_RC4_128_SHA:
+ return "TLS_RSA_WITH_RC4_128_SHA";
+ break;
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case SSL_DH_anon_WITH_RC4_128_MD5:
+ return "TLS_DH_anon_WITH_RC4_128_MD5";
+ break;
+ case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
+ break;
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
+ /* TLS PSK (RFC 4279): */
+ case TLS_PSK_WITH_RC4_128_SHA:
+ return "TLS_PSK_WITH_RC4_128_SHA";
+ break;
+ case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_PSK_WITH_AES_128_CBC_SHA:
+ return "TLS_PSK_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_PSK_WITH_AES_256_CBC_SHA:
+ return "TLS_PSK_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_RC4_128_SHA:
+ return "TLS_DHE_PSK_WITH_RC4_128_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_RC4_128_SHA:
+ return "TLS_RSA_PSK_WITH_RC4_128_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+ return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
+ break;
+ /* More TLS PSK (RFC 4785): */
+ case TLS_PSK_WITH_NULL_SHA:
+ return "TLS_PSK_WITH_NULL_SHA";
+ break;
+ case TLS_DHE_PSK_WITH_NULL_SHA:
+ return "TLS_DHE_PSK_WITH_NULL_SHA";
+ break;
+ case TLS_RSA_PSK_WITH_NULL_SHA:
+ return "TLS_RSA_PSK_WITH_NULL_SHA";
+ break;
+ /* Even more TLS PSK (RFC 5487): */
+ case TLS_PSK_WITH_AES_128_GCM_SHA256:
+ return "TLS_PSK_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_PSK_WITH_AES_256_GCM_SHA384:
+ return "TLS_PSK_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+ return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
+ break;
+ case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ return "TLS_PSK_WITH_AES_256_GCM_SHA384";
+ break;
+ case TLS_PSK_WITH_AES_128_CBC_SHA256:
+ return "TLS_PSK_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_PSK_WITH_AES_256_CBC_SHA384:
+ return "TLS_PSK_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_PSK_WITH_NULL_SHA256:
+ return "TLS_PSK_WITH_NULL_SHA256";
+ break;
+ case TLS_PSK_WITH_NULL_SHA384:
+ return "TLS_PSK_WITH_NULL_SHA384";
+ break;
+ case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+ return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_DHE_PSK_WITH_NULL_SHA256:
+ return "TLS_DHE_PSK_WITH_NULL_SHA256";
+ break;
+ case TLS_DHE_PSK_WITH_NULL_SHA384:
+ return "TLS_RSA_PSK_WITH_NULL_SHA384";
+ break;
+ case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+ return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
+ break;
+ case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+ return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
+ break;
+ case TLS_RSA_PSK_WITH_NULL_SHA256:
+ return "TLS_RSA_PSK_WITH_NULL_SHA256";
+ break;
+ case TLS_RSA_PSK_WITH_NULL_SHA384:
+ return "TLS_RSA_PSK_WITH_NULL_SHA384";
+ break;
+#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
+ }
+ return "TLS_NULL_WITH_NULL_NULL";
+}
+
+#if CURL_BUILD_MAC
+CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
+{
+ int mib[2];
+ char *os_version;
+ size_t os_version_len;
+ char *os_version_major, *os_version_minor/*, *os_version_point*/;
+ char *tok_buf;
+
+ /* Get the Darwin kernel version from the kernel using sysctl(): */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_OSRELEASE;
+ if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
+ return;
+ os_version = malloc(os_version_len*sizeof(char));
+ if(!os_version)
+ return;
+ if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) {
+ free(os_version);
+ return;
+ }
+
+ /* Parse the version: */
+ os_version_major = strtok_r(os_version, ".", &tok_buf);
+ os_version_minor = strtok_r(NULL, ".", &tok_buf);
+ /*os_version_point = strtok_r(NULL, ".", &tok_buf);*/
+ *major = atoi(os_version_major);
+ *minor = atoi(os_version_minor);
+ free(os_version);
+}
+#endif /* CURL_BUILD_MAC */
+
+/* Apple provides a myriad of ways of getting information about a certificate
+ into a string. Some aren't available under iOS or newer cats. So here's
+ a unified function for getting a string describing the certificate that
+ ought to work in all cats starting with Leopard. */
+CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
+{
+ CFStringRef server_cert_summary = CFSTR("(null)");
+
+#if CURL_BUILD_IOS
+ /* iOS: There's only one way to do this. */
+ server_cert_summary = SecCertificateCopySubjectSummary(cert);
+#else
+#if CURL_BUILD_MAC_10_7
+ /* Lion & later: Get the long description if we can. */
+ if(SecCertificateCopyLongDescription != NULL)
+ server_cert_summary =
+ SecCertificateCopyLongDescription(NULL, cert, NULL);
+ else
+#endif /* CURL_BUILD_MAC_10_7 */
+#if CURL_BUILD_MAC_10_6
+ /* Snow Leopard: Get the certificate summary. */
+ if(SecCertificateCopySubjectSummary != NULL)
+ server_cert_summary = SecCertificateCopySubjectSummary(cert);
+ else
+#endif /* CURL_BUILD_MAC_10_6 */
+ /* Leopard is as far back as we go... */
+ (void)SecCertificateCopyCommonName(cert, &server_cert_summary);
+#endif /* CURL_BUILD_IOS */
+ return server_cert_summary;
+}
+
+#if CURL_SUPPORT_MAC_10_6
+/* The SecKeychainSearch API was deprecated in Lion, and using it will raise
+ deprecation warnings, so let's not compile this unless it's necessary: */
+static OSStatus CopyIdentityWithLabelOldSchool(char *label,
+ SecIdentityRef *out_c_a_k)
+{
+ OSStatus status = errSecItemNotFound;
+ SecKeychainAttributeList attr_list;
+ SecKeychainAttribute attr;
+ SecKeychainSearchRef search = NULL;
+ SecCertificateRef cert = NULL;
+
+ /* Set up the attribute list: */
+ attr_list.count = 1L;
+ attr_list.attr = &attr;
+
+ /* Set up our lone search criterion: */
+ attr.tag = kSecLabelItemAttr;
+ attr.data = label;
+ attr.length = (UInt32)strlen(label);
+
+ /* Start searching: */
+ status = SecKeychainSearchCreateFromAttributes(NULL,
+ kSecCertificateItemClass,
+ &attr_list,
+ &search);
+ if(status == noErr) {
+ status = SecKeychainSearchCopyNext(search,
+ (SecKeychainItemRef *)&cert);
+ if(status == noErr && cert) {
+ /* If we found a certificate, does it have a private key? */
+ status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
+ CFRelease(cert);
+ }
+ }
+
+ if(search)
+ CFRelease(search);
+ return status;
+}
+#endif /* CURL_SUPPORT_MAC_10_6 */
+
+static OSStatus CopyIdentityWithLabel(char *label,
+ SecIdentityRef *out_cert_and_key)
+{
+ OSStatus status = errSecItemNotFound;
+
+#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
+ /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
+ kSecClassIdentity was introduced in Lion. If both exist, let's use them
+ to find the certificate. */
+ if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
+ CFTypeRef keys[4];
+ CFTypeRef values[4];
+ CFDictionaryRef query_dict;
+ CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
+ kCFStringEncodingUTF8);
+
+ /* Set up our search criteria and expected results: */
+ values[0] = kSecClassIdentity; /* we want a certificate and a key */
+ keys[0] = kSecClass;
+ values[1] = kCFBooleanTrue; /* we want a reference */
+ keys[1] = kSecReturnRef;
+ values[2] = kSecMatchLimitOne; /* one is enough, thanks */
+ keys[2] = kSecMatchLimit;
+ /* identity searches need a SecPolicyRef in order to work */
+ values[3] = SecPolicyCreateSSL(false, label_cf);
+ keys[3] = kSecMatchPolicy;
+ query_dict = CFDictionaryCreate(NULL, (const void **)keys,
+ (const void **)values, 4L,
+ &kCFCopyStringDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFRelease(values[3]);
+ CFRelease(label_cf);
+
+ /* Do we have a match? */
+ status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
+ CFRelease(query_dict);
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_6
+ /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
+ status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
+#endif /* CURL_SUPPORT_MAC_10_7 */
+ }
+#elif CURL_SUPPORT_MAC_10_6
+ /* For developers building on older cats, we have no choice but to fall back
+ to SecKeychainSearch. */
+ status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
+#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+ return status;
+}
+
+static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
+ const char *cPassword,
+ SecIdentityRef *out_cert_and_key)
+{
+ OSStatus status = errSecItemNotFound;
+ CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL,
+ (const UInt8 *)cPath, strlen(cPath), false);
+ CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
+ cPassword, kCFStringEncodingUTF8) : NULL;
+ CFDataRef pkcs_data = NULL;
+
+ /* We can import P12 files on iOS or OS X 10.7 or later: */
+ /* These constants are documented as having first appeared in 10.6 but they
+ raise linker errors when used on that cat for some reason. */
+#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
+ if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
+ NULL, NULL, &status)) {
+ const void *cKeys[] = {kSecImportExportPassphrase};
+ const void *cValues[] = {password};
+ CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
+ password ? 1L : 0L, NULL, NULL);
+ CFArrayRef items = NULL;
+
+ /* Here we go: */
+ status = SecPKCS12Import(pkcs_data, options, &items);
+ if(status == noErr && items && CFArrayGetCount(items)) {
+ CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
+ const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
+ kSecImportItemIdentity);
+
+ /* Retain the identity; we don't care about any other data... */
+ CFRetain(temp_identity);
+ *out_cert_and_key = (SecIdentityRef)temp_identity;
+ }
+
+ if(items)
+ CFRelease(items);
+ CFRelease(options);
+ CFRelease(pkcs_data);
+ }
+#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+ if(password)
+ CFRelease(password);
+ CFRelease(pkcs_url);
+ return status;
+}
+
+/* This code was borrowed from nss.c, with some modifications:
+ * Determine whether the nickname passed in is a filename that needs to
+ * be loaded as a PEM or a regular NSS nickname.
+ *
+ * returns 1 for a file
+ * returns 0 for not a file
+ */
+CF_INLINE bool is_file(const char *filename)
+{
+ struct_stat st;
+
+ if(filename == NULL)
+ return false;
+
+ if(stat(filename, &st) == 0)
+ return S_ISREG(st.st_mode);
+ return false;
+}
+
+static CURLcode darwinssl_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif /* ENABLE_IPV6 */
+ size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
+ SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
+ char *ssl_sessionid;
+ size_t ssl_sessionid_len;
+ OSStatus err = noErr;
+#if CURL_BUILD_MAC
+ int darwinver_maj = 0, darwinver_min = 0;
+
+ GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
+#endif /* CURL_BUILD_MAC */
+
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
+ if(connssl->ssl_ctx)
+ CFRelease(connssl->ssl_ctx);
+ connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
+ if(!connssl->ssl_ctx) {
+ failf(data, "SSL: couldn't create a context!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ /* The old ST API does not exist under iOS, so don't compile it: */
+#if CURL_SUPPORT_MAC_10_8
+ if(connssl->ssl_ctx)
+ (void)SSLDisposeContext(connssl->ssl_ctx);
+ err = SSLNewContext(false, &(connssl->ssl_ctx));
+ if(err != noErr) {
+ failf(data, "SSL: couldn't create a context: OSStatus %d", err);
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#else
+ if(connssl->ssl_ctx)
+ (void)SSLDisposeContext(connssl->ssl_ctx);
+ err = SSLNewContext(false, &(connssl->ssl_ctx));
+ if(err != noErr) {
+ failf(data, "SSL: couldn't create a context: OSStatus %d", err);
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+ connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */
+
+ /* check to see if we've been told to use an explicit SSL/TLS version */
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ if(SSLSetProtocolVersionMax != NULL) {
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_DEFAULT: default:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+ }
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_8
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocolAll,
+ false);
+ switch (data->set.ssl.version) {
+ case CURL_SSLVERSION_DEFAULT: default:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol3,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol3,
+ true);
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol2,
+ true);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ break;
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#else
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
+ switch(data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol3,
+ true);
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ failf(data, "Your version of the OS does not support TLSv1.1");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_TLSv1_2:
+ failf(data, "Your version of the OS does not support TLSv1.2");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_SSLv2:
+ err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol2,
+ true);
+ if(err != noErr) {
+ failf(data, "Your version of the OS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocol3,
+ true);
+ break;
+ }
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+
+ if(data->set.str[STRING_KEY]) {
+ infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
+ "Transport. The private key must be in the Keychain.\n");
+ }
+
+ if(data->set.str[STRING_CERT]) {
+ SecIdentityRef cert_and_key = NULL;
+ bool is_cert_file = is_file(data->set.str[STRING_CERT]);
+
+ /* User wants to authenticate with a client cert. Look for it:
+ If we detect that this is a file on disk, then let's load it.
+ Otherwise, assume that the user wants to use an identity loaded
+ from the Keychain. */
+ if(is_cert_file) {
+ if(!data->set.str[STRING_CERT_TYPE])
+ infof(data, "WARNING: SSL: Certificate type not set, assuming "
+ "PKCS#12 format.\n");
+ else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
+ strlen(data->set.str[STRING_CERT_TYPE])) != 0)
+ infof(data, "WARNING: SSL: The Security framework only supports "
+ "loading identities that are in PKCS#12 format.\n");
+
+ err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
+ data->set.str[STRING_KEY_PASSWD], &cert_and_key);
+ }
+ else
+ err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
+
+ if(err == noErr) {
+ SecCertificateRef cert = NULL;
+ CFTypeRef certs_c[1];
+ CFArrayRef certs;
+
+ /* If we found one, print it out: */
+ err = SecIdentityCopyCertificate(cert_and_key, &cert);
+ if(err == noErr) {
+ CFStringRef cert_summary = CopyCertSubject(cert);
+ char cert_summary_c[128];
+
+ if(cert_summary) {
+ memset(cert_summary_c, 0, 128);
+ if(CFStringGetCString(cert_summary,
+ cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Client certificate: %s\n", cert_summary_c);
+ }
+ CFRelease(cert_summary);
+ CFRelease(cert);
+ }
+ }
+ certs_c[0] = cert_and_key;
+ certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
+ &kCFTypeArrayCallBacks);
+ err = SSLSetCertificate(connssl->ssl_ctx, certs);
+ if(certs)
+ CFRelease(certs);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ CFRelease(cert_and_key);
+ }
+ else {
+ switch(err) {
+ case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
+ failf(data, "SSL: Incorrect password for the certificate \"%s\" "
+ "and its private key.", data->set.str[STRING_CERT]);
+ break;
+ case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
+ failf(data, "SSL: Couldn't make sense of the data in the "
+ "certificate \"%s\" and its private key.",
+ data->set.str[STRING_CERT]);
+ break;
+ case -25260: /* errSecPassphraseRequired */
+ failf(data, "SSL The certificate \"%s\" requires a password.",
+ data->set.str[STRING_CERT]);
+ break;
+ case errSecItemNotFound:
+ failf(data, "SSL: Can't find the certificate \"%s\" and its private "
+ "key in the Keychain.", data->set.str[STRING_CERT]);
+ break;
+ default:
+ failf(data, "SSL: Can't load the certificate \"%s\" and its private "
+ "key: OSStatus %d", data->set.str[STRING_CERT], err);
+ break;
+ }
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* SSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+ * anyway. In the latter case the result of the verification is checked with
+ * SSL_get_verify_result() below. */
+#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
+ /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
+ a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
+ works, it doesn't work as expected under Snow Leopard or Lion.
+ So we need to call SSLSetEnableCertVerify() on those older cats in order
+ to disable certificate validation if the user turned that off.
+ (SecureTransport will always validate the certificate chain by
+ default.) */
+ /* (Note: Darwin 12.x.x is Mountain Lion.) */
+#if CURL_BUILD_MAC
+ if(SSLSetSessionOption != NULL && darwinver_maj >= 12) {
+#else
+ if(SSLSetSessionOption != NULL) {
+#endif /* CURL_BUILD_MAC */
+ bool break_on_auth = !data->set.ssl.verifypeer ||
+ data->set.str[STRING_SSL_CAFILE];
+ err = SSLSetSessionOption(connssl->ssl_ctx,
+ kSSLSessionOptionBreakOnServerAuth,
+ break_on_auth);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_8
+ err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+ data->set.ssl.verifypeer?true:false);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#else
+ err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+ data->set.ssl.verifypeer?true:false);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
+
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]);
+
+ if(!is_cert_file) {
+ failf(data, "SSL: can't load CA certificate file %s",
+ data->set.str[STRING_SSL_CAFILE]);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ if(!data->set.ssl.verifypeer) {
+ failf(data, "SSL: CA certificate set, but certificate verification "
+ "is disabled");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* Configure hostname check. SNI is used if available.
+ * Both hostname check and SNI require SSLSetPeerDomainName().
+ * Also: the verifyhost setting influences SNI usage */
+ if(data->set.ssl.verifyhost) {
+ err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
+ strlen(conn->host.name));
+
+ if(err != noErr) {
+ infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
+ err);
+ }
+
+ if((Curl_inet_pton(AF_INET, conn->host.name, &addr))
+ #ifdef ENABLE_IPV6
+ || (Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+ #endif
+ ) {
+ infof(data, "WARNING: using IP address, SNI is being disabled by "
+ "the OS.\n");
+ }
+ }
+
+ /* Disable cipher suites that ST supports but are not safe. These ciphers
+ are unlikely to be used in any case since ST gives other ciphers a much
+ higher priority, but it's probably better that we not connect at all than
+ to give the user a false sense of security if the server only supports
+ insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
+ (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count);
+ all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
+ allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
+ if(all_ciphers && allowed_ciphers &&
+ SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
+ &all_ciphers_count) == noErr) {
+ for(i = 0UL ; i < all_ciphers_count ; i++) {
+#if CURL_BUILD_MAC
+ /* There's a known bug in early versions of Mountain Lion where ST's ECC
+ ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
+ Work around the problem here by disabling those ciphers if we are
+ running in an affected version of OS X. */
+ if(darwinver_maj == 12 && darwinver_min <= 3 &&
+ all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
+ continue;
+ }
+#endif /* CURL_BUILD_MAC */
+ switch(all_ciphers[i]) {
+ /* Disable NULL ciphersuites: */
+ case SSL_NULL_WITH_NULL_NULL:
+ case SSL_RSA_WITH_NULL_MD5:
+ case SSL_RSA_WITH_NULL_SHA:
+ case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
+ case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
+ case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
+ case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
+ case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
+ case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
+ case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
+ case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
+ case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
+ case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
+ case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
+ case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
+ case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
+ case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
+ case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
+ /* Disable anonymous ciphersuites: */
+ case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
+ case SSL_DH_anon_WITH_RC4_128_MD5:
+ case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_anon_WITH_DES_CBC_SHA:
+ case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA:
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA:
+ case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
+ case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
+ case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
+ case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
+ case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
+ case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
+ case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
+ case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
+ case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
+ /* Disable weak key ciphersuites: */
+ case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
+ case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
+ case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ case SSL_DH_DSS_WITH_DES_CBC_SHA:
+ case SSL_DH_RSA_WITH_DES_CBC_SHA:
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ /* Disable IDEA: */
+ case SSL_RSA_WITH_IDEA_CBC_SHA:
+ case SSL_RSA_WITH_IDEA_CBC_MD5:
+ break;
+ default: /* enable everything else */
+ allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
+ break;
+ }
+ }
+ err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers,
+ allowed_ciphers_count);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+ Curl_safefree(all_ciphers);
+ Curl_safefree(allowed_ciphers);
+ failf(data, "SSL: Failed to allocate memory for allowed ciphers");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ Curl_safefree(all_ciphers);
+ Curl_safefree(allowed_ciphers);
+
+#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
+ /* We want to enable 1/n-1 when using a CBC cipher unless the user
+ specifically doesn't want us doing that: */
+ if(SSLSetSessionOption != NULL)
+ SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
+ !data->set.ssl_enable_beast);
+#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
+
+ /* Check if there's a cached ID we can/should use here! */
+ if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
+ &ssl_sessionid_len)) {
+ /* we got a session id, use it! */
+ err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof(data, "SSL re-using session ID\n");
+ }
+ /* If there isn't one, then let's make one up! This has to be done prior
+ to starting the handshake. */
+ else {
+ CURLcode retcode;
+
+ ssl_sessionid = malloc(256*sizeof(char));
+ ssl_sessionid_len = snprintf(ssl_sessionid, 256, "curl:%s:%hu",
+ conn->host.name, conn->remote_port);
+ err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ retcode = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
+ if(retcode!= CURLE_OK) {
+ failf(data, "failed to store ssl session");
+ return retcode;
+ }
+ }
+
+ err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* pass the raw socket into the SSL layers */
+ /* We need to store the FD in a constant memory address, because
+ * SSLSetConnection() will not copy that address. I've found that
+ * conn->sock[sockindex] may change on its own. */
+ connssl->ssl_sockfd = sockfd;
+ err = SSLSetConnection(connssl->ssl_ctx, connssl);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetConnection() failed: %d", err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+}
+
+static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
+{
+ char *sep_start, *sep_end, *cert_start, *cert_end;
+ size_t i, j, err;
+ size_t len;
+ unsigned char *b64;
+
+ /* Jump through the separators at the beginning of the certificate. */
+ sep_start = strstr(in, "-----");
+ if(sep_start == NULL)
+ return 0;
+ cert_start = strstr(sep_start + 1, "-----");
+ if(cert_start == NULL)
+ return -1;
+
+ cert_start += 5;
+
+ /* Find separator after the end of the certificate. */
+ cert_end = strstr(cert_start, "-----");
+ if(cert_end == NULL)
+ return -1;
+
+ sep_end = strstr(cert_end + 1, "-----");
+ if(sep_end == NULL)
+ return -1;
+ sep_end += 5;
+
+ len = cert_end - cert_start;
+ b64 = malloc(len + 1);
+ if(!b64)
+ return -1;
+
+ /* Create base64 string without linefeeds. */
+ for(i = 0, j = 0; i < len; i++) {
+ if(cert_start[i] != '\r' && cert_start[i] != '\n')
+ b64[j++] = cert_start[i];
+ }
+ b64[j] = '\0';
+
+ err = Curl_base64_decode((const char *)b64, out, outlen);
+ free(b64);
+ if(err) {
+ free(*out);
+ return -1;
+ }
+
+ return sep_end - in;
+}
+
+static int read_cert(const char *file, unsigned char **out, size_t *outlen)
+{
+ int fd;
+ ssize_t n, len = 0, cap = 512;
+ unsigned char buf[cap], *data;
+
+ fd = open(file, 0);
+ if(fd < 0)
+ return -1;
+
+ data = malloc(cap);
+ if(!data) {
+ close(fd);
+ return -1;
+ }
+
+ for(;;) {
+ n = read(fd, buf, sizeof(buf));
+ if(n < 0) {
+ close(fd);
+ free(data);
+ return -1;
+ }
+ else if(n == 0) {
+ close(fd);
+ break;
+ }
+
+ if(len + n >= cap) {
+ cap *= 2;
+ data = realloc(data, cap);
+ if(!data) {
+ close(fd);
+ return -1;
+ }
+ }
+
+ memcpy(data + len, buf, n);
+ len += n;
+ }
+ data[len] = '\0';
+
+ *out = data;
+ *outlen = len;
+
+ return 0;
+}
+
+static int sslerr_to_curlerr(struct SessionHandle *data, int err)
+{
+ switch(err) {
+ case errSSLXCertChainInvalid:
+ failf(data, "SSL certificate problem: Invalid certificate chain");
+ return CURLE_SSL_CACERT;
+ case errSSLUnknownRootCert:
+ failf(data, "SSL certificate problem: Untrusted root certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLNoRootCert:
+ failf(data, "SSL certificate problem: No root certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLCertExpired:
+ failf(data, "SSL certificate problem: Certificate chain had an "
+ "expired certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLBadCert:
+ failf(data, "SSL certificate problem: Couldn't understand the server "
+ "certificate format");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLHostNameMismatch:
+ failf(data, "SSL certificate peer hostname mismatch");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ default:
+ failf(data, "SSL unexpected certificate error %d", err);
+ return CURLE_SSL_CACERT;
+ }
+}
+
+static int append_cert_to_array(struct SessionHandle *data,
+ unsigned char *buf, size_t buflen,
+ CFMutableArrayRef array)
+{
+ CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
+ if(!certdata) {
+ failf(data, "SSL: failed to allocate array for CA certificate");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ SecCertificateRef cacert =
+ SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
+ CFRelease(certdata);
+ if(!cacert) {
+ failf(data, "SSL: failed to create SecCertificate from CA certificate");
+ return CURLE_SSL_CACERT;
+ }
+
+ /* Check if cacert is valid. */
+ CFStringRef subject = CopyCertSubject(cacert);
+ if(subject) {
+ char subject_cbuf[128];
+ memset(subject_cbuf, 0, 128);
+ if(!CFStringGetCString(subject,
+ subject_cbuf,
+ 128,
+ kCFStringEncodingUTF8)) {
+ CFRelease(cacert);
+ failf(data, "SSL: invalid CA certificate subject");
+ return CURLE_SSL_CACERT;
+ }
+ CFRelease(subject);
+ }
+ else {
+ CFRelease(cacert);
+ failf(data, "SSL: invalid CA certificate");
+ return CURLE_SSL_CACERT;
+ }
+
+ CFArrayAppendValue(array, cacert);
+ CFRelease(cacert);
+
+ return CURLE_OK;
+}
+
+static int verify_cert(const char *cafile, struct SessionHandle *data,
+ SSLContextRef ctx)
+{
+ int n = 0, rc;
+ long res;
+ unsigned char *certbuf, *der;
+ size_t buflen, derlen, offset = 0;
+
+ if(read_cert(cafile, &certbuf, &buflen) < 0) {
+ failf(data, "SSL: failed to read or invalid CA certificate");
+ return CURLE_SSL_CACERT;
+ }
+
+ /*
+ * Certbuf now contains the contents of the certificate file, which can be
+ * - a single DER certificate,
+ * - a single PEM certificate or
+ * - a bunch of PEM certificates (certificate bundle).
+ *
+ * Go through certbuf, and convert any PEM certificate in it into DER
+ * format.
+ */
+ CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeArrayCallBacks);
+ if(array == NULL) {
+ free(certbuf);
+ failf(data, "SSL: out of memory creating CA certificate array");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ while(offset < buflen) {
+ n++;
+
+ /*
+ * Check if the certificate is in PEM format, and convert it to DER. If
+ * this fails, we assume the certificate is in DER format.
+ */
+ res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
+ if(res < 0) {
+ free(certbuf);
+ CFRelease(array);
+ failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle",
+ n, offset);
+ return CURLE_SSL_CACERT;
+ }
+ offset += res;
+
+ if(res == 0 && offset == 0) {
+ /* This is not a PEM file, probably a certificate in DER format. */
+ rc = append_cert_to_array(data, certbuf, buflen, array);
+ free(certbuf);
+ if(rc != CURLE_OK) {
+ CFRelease(array);
+ return rc;
+ }
+ break;
+ }
+ else if(res == 0) {
+ /* No more certificates in the bundle. */
+ free(certbuf);
+ break;
+ }
+
+ rc = append_cert_to_array(data, der, derlen, array);
+ free(der);
+ if(rc != CURLE_OK) {
+ free(certbuf);
+ CFRelease(array);
+ return rc;
+ }
+ }
+
+ SecTrustRef trust;
+ OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
+ if(trust == NULL) {
+ failf(data, "SSL: error getting certificate chain");
+ CFRelease(array);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else if(ret != noErr) {
+ CFRelease(array);
+ return sslerr_to_curlerr(data, ret);
+ }
+
+ ret = SecTrustSetAnchorCertificates(trust, array);
+ if(ret != noErr) {
+ CFRelease(trust);
+ return sslerr_to_curlerr(data, ret);
+ }
+ ret = SecTrustSetAnchorCertificatesOnly(trust, true);
+ if(ret != noErr) {
+ CFRelease(trust);
+ return sslerr_to_curlerr(data, ret);
+ }
+
+ SecTrustResultType trust_eval = 0;
+ ret = SecTrustEvaluate(trust, &trust_eval);
+ CFRelease(array);
+ CFRelease(trust);
+ if(ret != noErr) {
+ return sslerr_to_curlerr(data, ret);
+ }
+
+ switch (trust_eval) {
+ case kSecTrustResultUnspecified:
+ case kSecTrustResultProceed:
+ return CURLE_OK;
+
+ case kSecTrustResultRecoverableTrustFailure:
+ case kSecTrustResultDeny:
+ default:
+ failf(data, "SSL: certificate verification failed (result: %d)",
+ trust_eval);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+}
+
+static CURLcode
+darwinssl_connect_step2(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ OSStatus err;
+ SSLCipherSuite cipher;
+ SSLProtocol protocol = 0;
+
+ DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
+ || ssl_connect_2_reading == connssl->connecting_state
+ || ssl_connect_2_writing == connssl->connecting_state);
+
+ /* Here goes nothing: */
+ err = SSLHandshake(connssl->ssl_ctx);
+
+ if(err != noErr) {
+ switch (err) {
+ case errSSLWouldBlock: /* they're not done with us yet */
+ connssl->connecting_state = connssl->ssl_direction ?
+ ssl_connect_2_writing : ssl_connect_2_reading;
+ return CURLE_OK;
+
+ /* The below is errSSLServerAuthCompleted; it's not defined in
+ Leopard's headers */
+ case -9841:
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data,
+ connssl->ssl_ctx);
+ if(res != CURLE_OK)
+ return res;
+ }
+ /* the documentation says we need to call SSLHandshake() again */
+ return darwinssl_connect_step2(conn, sockindex);
+
+ /* These are all certificate problems with the server: */
+ case errSSLXCertChainInvalid:
+ failf(data, "SSL certificate problem: Invalid certificate chain");
+ return CURLE_SSL_CACERT;
+ case errSSLUnknownRootCert:
+ failf(data, "SSL certificate problem: Untrusted root certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLNoRootCert:
+ failf(data, "SSL certificate problem: No root certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLCertExpired:
+ failf(data, "SSL certificate problem: Certificate chain had an "
+ "expired certificate");
+ return CURLE_SSL_CACERT;
+ case errSSLBadCert:
+ failf(data, "SSL certificate problem: Couldn't understand the server "
+ "certificate format");
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* These are all certificate problems with the client: */
+ case errSecAuthFailed:
+ failf(data, "SSL authentication failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLPeerHandshakeFail:
+ failf(data, "SSL peer handshake failed, the server most likely "
+ "requires a client certificate to connect");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLPeerUnknownCA:
+ failf(data, "SSL server rejected the client certificate due to "
+ "the certificate being signed by an unknown certificate "
+ "authority");
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* This error is raised if the server's cert didn't match the server's
+ host name: */
+ case errSSLHostNameMismatch:
+ failf(data, "SSL certificate peer verification failed, the "
+ "certificate did not match \"%s\"\n", conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+
+ /* Generic handshake errors: */
+ case errSSLConnectionRefused:
+ failf(data, "Server dropped the connection during the SSL handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLClosedAbort:
+ failf(data, "Server aborted the SSL handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLNegotiation:
+ failf(data, "Could not negotiate an SSL cipher suite with the server");
+ return CURLE_SSL_CONNECT_ERROR;
+ /* Sometimes paramErr happens with buggy ciphers: */
+ case paramErr: case errSSLInternal:
+ failf(data, "Internal SSL engine error encountered during the "
+ "SSL handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ case errSSLFatalAlert:
+ failf(data, "Fatal SSL engine error encountered during the SSL "
+ "handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unknown SSL protocol error in connection to %s:%d",
+ conn->host.name, err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+ /* we have been connected fine, we're not waiting for anything else. */
+ connssl->connecting_state = ssl_connect_3;
+
+ /* Informational message */
+ (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
+ (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
+ switch (protocol) {
+ case kSSLProtocol2:
+ infof(data, "SSL 2.0 connection using %s\n",
+ SSLCipherNameForNumber(cipher));
+ break;
+ case kSSLProtocol3:
+ infof(data, "SSL 3.0 connection using %s\n",
+ SSLCipherNameForNumber(cipher));
+ break;
+ case kTLSProtocol1:
+ infof(data, "TLS 1.0 connection using %s\n",
+ TLSCipherNameForNumber(cipher));
+ break;
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ case kTLSProtocol11:
+ infof(data, "TLS 1.1 connection using %s\n",
+ TLSCipherNameForNumber(cipher));
+ break;
+ case kTLSProtocol12:
+ infof(data, "TLS 1.2 connection using %s\n",
+ TLSCipherNameForNumber(cipher));
+ break;
+#endif
+ default:
+ infof(data, "Unknown protocol connection\n");
+ break;
+ }
+
+ return CURLE_OK;
+ }
+}
+
+static CURLcode
+darwinssl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CFStringRef server_cert_summary;
+ char server_cert_summary_c[128];
+ CFArrayRef server_certs = NULL;
+ SecCertificateRef server_cert;
+ OSStatus err;
+ CFIndex i, count;
+ SecTrustRef trust = NULL;
+
+ /* There is no step 3!
+ * Well, okay, if verbose mode is on, let's print the details of the
+ * server certificates. */
+#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
+#if CURL_BUILD_IOS
+#pragma unused(server_certs)
+ err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+ /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
+ a null trust, so be on guard for that: */
+ if(err == noErr && trust) {
+ count = SecTrustGetCertificateCount(trust);
+ for(i = 0L ; i < count ; i++) {
+ server_cert = SecTrustGetCertificateAtIndex(trust, i);
+ server_cert_summary = CopyCertSubject(server_cert);
+ memset(server_cert_summary_c, 0, 128);
+ if(CFStringGetCString(server_cert_summary,
+ server_cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ }
+ CFRelease(server_cert_summary);
+ }
+ CFRelease(trust);
+ }
+#else
+ /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
+ The function SecTrustGetCertificateAtIndex() is officially present
+ in Lion, but it is unfortunately also present in Snow Leopard as
+ private API and doesn't work as expected. So we have to look for
+ a different symbol to make sure this code is only executed under
+ Lion or later. */
+ if(SecTrustEvaluateAsync != NULL) {
+#pragma unused(server_certs)
+ err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+ /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
+ a null trust, so be on guard for that: */
+ if(err == noErr && trust) {
+ count = SecTrustGetCertificateCount(trust);
+ for(i = 0L ; i < count ; i++) {
+ server_cert = SecTrustGetCertificateAtIndex(trust, i);
+ server_cert_summary = CopyCertSubject(server_cert);
+ memset(server_cert_summary_c, 0, 128);
+ if(CFStringGetCString(server_cert_summary,
+ server_cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ }
+ CFRelease(server_cert_summary);
+ }
+ CFRelease(trust);
+ }
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_8
+ err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+ /* Just in case SSLCopyPeerCertificates() returns null too... */
+ if(err == noErr && server_certs) {
+ count = CFArrayGetCount(server_certs);
+ for(i = 0L ; i < count ; i++) {
+ server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
+ i);
+
+ server_cert_summary = CopyCertSubject(server_cert);
+ memset(server_cert_summary_c, 0, 128);
+ if(CFStringGetCString(server_cert_summary,
+ server_cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ }
+ CFRelease(server_cert_summary);
+ }
+ CFRelease(server_certs);
+ }
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#endif /* CURL_BUILD_IOS */
+#else
+#pragma unused(trust)
+ err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+ if(err == noErr) {
+ count = CFArrayGetCount(server_certs);
+ for(i = 0L ; i < count ; i++) {
+ server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
+ server_cert_summary = CopyCertSubject(server_cert);
+ memset(server_cert_summary_c, 0, 128);
+ if(CFStringGetCString(server_cert_summary,
+ server_cert_summary_c,
+ 128,
+ kCFStringEncodingUTF8)) {
+ infof(data, "Server certificate: %s\n", server_cert_summary_c);
+ }
+ CFRelease(server_cert_summary);
+ }
+ CFRelease(server_certs);
+ }
+#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+
+ connssl->connecting_state = ssl_connect_done;
+ return CURLE_OK;
+}
+
+static Curl_recv darwinssl_recv;
+static Curl_send darwinssl_send;
+
+static CURLcode
+darwinssl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode retcode;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1==connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ retcode = darwinssl_connect_step1(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing ==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading ==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if this
+ * connection is done nonblocking and this loop would execute again. This
+ * permits the owner of a multi handle to abort a connection attempt
+ * before step2 has completed while ensuring that a client using select()
+ * or epoll() will always have a valid fdset to wait on.
+ */
+ retcode = darwinssl_connect_step2(conn, sockindex);
+ if(retcode || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return retcode;
+
+ } /* repeat step2 until all transactions are done. */
+
+
+ if(ssl_connect_3==connssl->connecting_state) {
+ retcode = darwinssl_connect_step3(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ if(ssl_connect_done==connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = darwinssl_recv;
+ conn->send[sockindex] = darwinssl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+CURLcode
+Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return darwinssl_connect_common(conn, sockindex, TRUE, done);
+}
+
+CURLcode
+Curl_darwinssl_connect(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode;
+ bool done = FALSE;
+
+ retcode = darwinssl_connect_common(conn, sockindex, FALSE, &done);
+
+ if(retcode)
+ return retcode;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->ssl_ctx) {
+ (void)SSLClose(connssl->ssl_ctx);
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ if(SSLCreateContext != NULL)
+ CFRelease(connssl->ssl_ctx);
+#if CURL_SUPPORT_MAC_10_8
+ else
+ (void)SSLDisposeContext(connssl->ssl_ctx);
+#endif /* CURL_SUPPORT_MAC_10_8 */
+#else
+ (void)SSLDisposeContext(connssl->ssl_ctx);
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+ connssl->ssl_ctx = NULL;
+ }
+ connssl->ssl_sockfd = 0;
+}
+
+void Curl_darwinssl_close_all(struct SessionHandle *data)
+{
+ /* SecureTransport doesn't separate sessions from contexts, so... */
+ (void)data;
+}
+
+int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ ssize_t nread;
+ int what;
+ int rc;
+ char buf[120];
+
+ if(!connssl->ssl_ctx)
+ return 0;
+
+ if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
+ return 0;
+
+ Curl_darwinssl_close(conn, sockindex);
+
+ rc = 0;
+
+ what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+
+ for(;;) {
+ if(what < 0) {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ rc = -1;
+ break;
+ }
+
+ if(!what) { /* timeout */
+ failf(data, "SSL shutdown timeout");
+ break;
+ }
+
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server. No way to SSL_Read now, so use read(). */
+
+ nread = read(conn->sock[sockindex], buf, sizeof(buf));
+
+ if(nread < 0) {
+ failf(data, "read: %s", strerror(errno));
+ rc = -1;
+ }
+
+ if(nread <= 0)
+ break;
+
+ what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
+ }
+
+ return rc;
+}
+
+void Curl_darwinssl_session_free(void *ptr)
+{
+ /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
+ cached session ID inside the Security framework. There is a private
+ function that does this, but I don't want to have to explain to you why I
+ got your application rejected from the App Store due to the use of a
+ private API, so the best we can do is free up our own char array that we
+ created way back in darwinssl_connect_step1... */
+ Curl_safefree(ptr);
+}
+
+size_t Curl_darwinssl_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "SecureTransport");
+}
+
+/*
+ * This function uses SSLGetSessionState to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+int Curl_darwinssl_check_cxn(struct connectdata *conn)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+ OSStatus err;
+ SSLSessionState state;
+
+ if(connssl->ssl_ctx) {
+ err = SSLGetSessionState(connssl->ssl_ctx, &state);
+ if(err == noErr)
+ return state == kSSLConnected || state == kSSLHandshake;
+ return -1;
+ }
+ return 0;
+}
+
+bool Curl_darwinssl_data_pending(const struct connectdata *conn,
+ int connindex)
+{
+ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
+ OSStatus err;
+ size_t buffer;
+
+ if(connssl->ssl_ctx) { /* SSL is in use */
+ err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer);
+ if(err == noErr)
+ return buffer > 0UL;
+ return false;
+ }
+ else
+ return false;
+}
+
+int Curl_darwinssl_random(unsigned char *entropy,
+ size_t length)
+{
+ /* arc4random_buf() isn't available on cats older than Lion, so let's
+ do this manually for the benefit of the older cats. */
+ size_t i;
+ u_int32_t random_number = 0;
+
+ for(i = 0 ; i < length ; i++) {
+ if(i % sizeof(u_int32_t) == 0)
+ random_number = arc4random();
+ entropy[i] = random_number & 0xFF;
+ random_number >>= 8;
+ }
+ i = random_number = 0;
+ return 0;
+}
+
+void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
+{
+ (void)md5len;
+ (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
+}
+
+static ssize_t darwinssl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ /*struct SessionHandle *data = conn->data;*/
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ size_t processed = 0UL;
+ OSStatus err;
+
+ /* The SSLWrite() function works a little differently than expected. The
+ fourth argument (processed) is currently documented in Apple's
+ documentation as: "On return, the length, in bytes, of the data actually
+ written."
+
+ Now, one could interpret that as "written to the socket," but actually,
+ it returns the amount of data that was written to a buffer internal to
+ the SSLContextRef instead. So it's possible for SSLWrite() to return
+ errSSLWouldBlock and a number of bytes "written" because those bytes were
+ encrypted and written to a buffer, not to the socket.
+
+ So if this happens, then we need to keep calling SSLWrite() over and
+ over again with no new data until it quits returning errSSLWouldBlock. */
+
+ /* Do we have buffered data to write from the last time we were called? */
+ if(connssl->ssl_write_buffered_length) {
+ /* Write the buffered data: */
+ err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
+ switch (err) {
+ case noErr:
+ /* processed is always going to be 0 because we didn't write to
+ the buffer, so return how much was written to the socket */
+ processed = connssl->ssl_write_buffered_length;
+ connssl->ssl_write_buffered_length = 0UL;
+ break;
+ case errSSLWouldBlock: /* argh, try again */
+ *curlcode = CURLE_AGAIN;
+ return -1L;
+ default:
+ failf(conn->data, "SSLWrite() returned error %d", err);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1L;
+ }
+ }
+ else {
+ /* We've got new data to write: */
+ err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
+ if(err != noErr) {
+ switch (err) {
+ case errSSLWouldBlock:
+ /* Data was buffered but not sent, we have to tell the caller
+ to try sending again, and remember how much was buffered */
+ connssl->ssl_write_buffered_length = len;
+ *curlcode = CURLE_AGAIN;
+ return -1L;
+ default:
+ failf(conn->data, "SSLWrite() returned error %d", err);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1L;
+ }
+ }
+ }
+ return (ssize_t)processed;
+}
+
+static ssize_t darwinssl_recv(struct connectdata *conn,
+ int num,
+ char *buf,
+ size_t buffersize,
+ CURLcode *curlcode)
+{
+ /*struct SessionHandle *data = conn->data;*/
+ struct ssl_connect_data *connssl = &conn->ssl[num];
+ size_t processed = 0UL;
+ OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
+
+ if(err != noErr) {
+ switch (err) {
+ case errSSLWouldBlock: /* return how much we read (if anything) */
+ if(processed)
+ return (ssize_t)processed;
+ *curlcode = CURLE_AGAIN;
+ return -1L;
+ break;
+
+ /* errSSLClosedGraceful - server gracefully shut down the SSL session
+ errSSLClosedNoNotify - server hung up on us instead of sending a
+ closure alert notice, read() is returning 0
+ Either way, inform the caller that the server disconnected. */
+ case errSSLClosedGraceful:
+ case errSSLClosedNoNotify:
+ *curlcode = CURLE_OK;
+ return -1L;
+ break;
+
+ default:
+ failf(conn->data, "SSLRead() return error %d", err);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1L;
+ break;
+ }
+ }
+ return (ssize_t)processed;
+}
+
+#endif /* USE_DARWINSSL */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/curl_darwinssl.h b/external/libcurl_android/jni/libcurl/lib/vtls/curl_darwinssl.h
new file mode 100755
index 00000000..f5c03d83
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/curl_darwinssl.h
@@ -0,0 +1,77 @@
+#ifndef HEADER_CURL_DARWINSSL_H
+#define HEADER_CURL_DARWINSSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_DARWINSSL
+
+CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex);
+
+CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+/* this function doesn't actually do anything */
+void Curl_darwinssl_close_all(struct SessionHandle *data);
+
+/* close a SSL connection */
+void Curl_darwinssl_close(struct connectdata *conn, int sockindex);
+
+void Curl_darwinssl_session_free(void *ptr);
+size_t Curl_darwinssl_version(char *buffer, size_t size);
+int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex);
+int Curl_darwinssl_check_cxn(struct connectdata *conn);
+bool Curl_darwinssl_data_pending(const struct connectdata *conn,
+ int connindex);
+
+int Curl_darwinssl_random(unsigned char *entropy,
+ size_t length);
+void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len);
+
+/* this backend provides these functions: */
+#define have_curlssl_md5sum 1
+
+/* API setup for SecureTransport */
+#define curlssl_init() (1)
+#define curlssl_cleanup() Curl_nop_stmt
+#define curlssl_connect Curl_darwinssl_connect
+#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking
+#define curlssl_session_free(x) Curl_darwinssl_session_free(x)
+#define curlssl_close_all Curl_darwinssl_close_all
+#define curlssl_close Curl_darwinssl_close
+#define curlssl_shutdown(x,y) 0
+#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_darwinssl_version
+#define curlssl_check_cxn Curl_darwinssl_check_cxn
+#define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y)
+#define curlssl_random(x,y,z) Curl_darwinssl_random(y,z)
+#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
+#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
+
+#endif /* USE_DARWINSSL */
+#endif /* HEADER_CURL_DARWINSSL_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/curl_schannel.c b/external/libcurl_android/jni/libcurl/lib/vtls/curl_schannel.c
new file mode 100755
index 00000000..e4e595ea
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/curl_schannel.c
@@ -0,0 +1,1346 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2014, Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all SChannel-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ */
+
+/*
+ * Based upon the PolarSSL implementation in polarssl.c and polarssl.h:
+ * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ *
+ * Based upon the CyaSSL implementation in cyassl.c and cyassl.h:
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * Thanks for code and inspiration!
+ */
+
+/*
+ * TODO list for TLS/SSL implementation:
+ * - implement client certificate authentication
+ * - implement custom server certificate validation
+ * - implement cipher/algorithm option
+ *
+ * Related articles on MSDN:
+ * - Getting a Certificate for Schannel
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa375447.aspx
+ * - Specifying Schannel Ciphers and Cipher Strengths
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa380161.aspx
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_SCHANNEL
+
+#ifndef USE_WINDOWS_SSPI
+# error "Can't compile SCHANNEL support without SSPI."
+#endif
+
+#include "curl_sspi.h"
+#include "curl_schannel.h"
+#include "vtls.h"
+#include "sendf.h"
+#include "connect.h" /* for the connect timeout */
+#include "strerror.h"
+#include "select.h" /* for the socket readyness */
+#include "inet_pton.h" /* for IP addr SNI check */
+#include "curl_multibyte.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Uncomment to force verbose output
+ * #define infof(x, y, ...) printf(y, __VA_ARGS__)
+ * #define failf(x, y, ...) printf(y, __VA_ARGS__)
+ */
+
+static Curl_recv schannel_recv;
+static Curl_send schannel_send;
+
+#ifdef _WIN32_WCE
+static CURLcode verify_certificate(struct connectdata *conn, int sockindex);
+#endif
+
+static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
+ void *BufDataPtr, unsigned long BufByteSize)
+{
+ buffer->cbBuffer = BufByteSize;
+ buffer->BufferType = BufType;
+ buffer->pvBuffer = BufDataPtr;
+}
+
+static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
+ unsigned long NumArrElem)
+{
+ desc->ulVersion = SECBUFFER_VERSION;
+ desc->pBuffers = BufArr;
+ desc->cBuffers = NumArrElem;
+}
+
+static CURLcode
+schannel_connect_step1(struct connectdata *conn, int sockindex)
+{
+ ssize_t written = -1;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SecBuffer outbuf;
+ SecBufferDesc outbuf_desc;
+ SCHANNEL_CRED schannel_cred;
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+ struct curl_schannel_cred *old_cred = NULL;
+ struct in_addr addr;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+ TCHAR *host_name;
+ CURLcode code;
+
+ infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
+ conn->host.name, conn->remote_port);
+
+ /* check for an existing re-usable credential handle */
+ if(!Curl_ssl_getsessionid(conn, (void**)&old_cred, NULL)) {
+ connssl->cred = old_cred;
+ infof(data, "schannel: re-using existing credential handle\n");
+ }
+ else {
+ /* setup Schannel API options */
+ memset(&schannel_cred, 0, sizeof(schannel_cred));
+ schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
+
+ if(data->set.ssl.verifypeer) {
+#ifdef _WIN32_WCE
+ /* certificate validation on CE doesn't seem to work right; we'll
+ do it following a more manual process. */
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
+ SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+#else
+ schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
+ SCH_CRED_REVOCATION_CHECK_CHAIN;
+#endif
+ infof(data, "schannel: checking server certificate revocation\n");
+ }
+ else {
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
+ SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+ infof(data, "schannel: disable server certificate revocation checks\n");
+ }
+
+ if(!data->set.ssl.verifyhost) {
+ schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
+ infof(data, "schannel: verifyhost setting prevents Schannel from "
+ "comparing the supplied target name with the subject "
+ "names in server certificates. Also disables SNI.\n");
+ }
+
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_TLSv1:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
+ SP_PROT_TLS1_1_CLIENT |
+ SP_PROT_TLS1_2_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
+ break;
+ default:
+ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
+ SP_PROT_TLS1_1_CLIENT |
+ SP_PROT_TLS1_2_CLIENT |
+ SP_PROT_SSL3_CLIENT;
+ break;
+ }
+
+ /* allocate memory for the re-usable credential handle */
+ connssl->cred = (struct curl_schannel_cred *)
+ malloc(sizeof(struct curl_schannel_cred));
+ if(!connssl->cred) {
+ failf(data, "schannel: unable to allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memset(connssl->cred, 0, sizeof(struct curl_schannel_cred));
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx */
+ sspi_status = s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
+ SECPKG_CRED_OUTBOUND, NULL, &schannel_cred, NULL, NULL,
+ &connssl->cred->cred_handle, &connssl->cred->time_stamp);
+
+ if(sspi_status != SEC_E_OK) {
+ if(sspi_status == SEC_E_WRONG_PRINCIPAL)
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ else
+ failf(data, "schannel: AcquireCredentialsHandle failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ Curl_safefree(connssl->cred);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* Warn if SNI is disabled due to use of an IP address */
+ if(Curl_inet_pton(AF_INET, conn->host.name, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, conn->host.name, &addr6)
+#endif
+ ) {
+ infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
+ }
+
+ /* setup output buffer */
+ InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
+ InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
+
+ /* setup request flags */
+ connssl->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
+ ISC_REQ_STREAM;
+
+ /* allocate memory for the security context handle */
+ connssl->ctxt = (struct curl_schannel_ctxt *)
+ malloc(sizeof(struct curl_schannel_ctxt));
+ if(!connssl->ctxt) {
+ failf(data, "schannel: unable to allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
+
+ host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ if(!host_name)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */
+
+ sspi_status = s_pSecFn->InitializeSecurityContext(
+ &connssl->cred->cred_handle, NULL, host_name,
+ connssl->req_flags, 0, 0, NULL, 0, &connssl->ctxt->ctxt_handle,
+ &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+
+ Curl_unicodefree(host_name);
+
+ if(sspi_status != SEC_I_CONTINUE_NEEDED) {
+ if(sspi_status == SEC_E_WRONG_PRINCIPAL)
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ else
+ failf(data, "schannel: initial InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ Curl_safefree(connssl->ctxt);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ infof(data, "schannel: sending initial handshake data: "
+ "sending %lu bytes...\n", outbuf.cbBuffer);
+
+ /* send initial handshake data which is now stored in output buffer */
+ code = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
+ outbuf.cbBuffer, &written);
+ s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
+ if((code != CURLE_OK) || (outbuf.cbBuffer != (size_t)written)) {
+ failf(data, "schannel: failed to send initial handshake data: "
+ "sent %zd of %lu bytes", written, outbuf.cbBuffer);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ infof(data, "schannel: sent initial handshake data: "
+ "sent %zd bytes\n", written);
+
+ /* continue to second handshake step */
+ connssl->connecting_state = ssl_connect_2;
+
+ return CURLE_OK;
+}
+
+static CURLcode
+schannel_connect_step2(struct connectdata *conn, int sockindex)
+{
+ int i;
+ ssize_t nread = -1, written = -1;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SecBuffer outbuf[2];
+ SecBufferDesc outbuf_desc;
+ SecBuffer inbuf[2];
+ SecBufferDesc inbuf_desc;
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+ TCHAR *host_name;
+ CURLcode code;
+ bool doread;
+
+ doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
+
+ infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
+ conn->host.name, conn->remote_port);
+
+ if(!connssl->cred || !connssl->ctxt)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* buffer to store previously received and encrypted data */
+ if(connssl->encdata_buffer == NULL) {
+ connssl->encdata_offset = 0;
+ connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+ connssl->encdata_buffer = malloc(connssl->encdata_length);
+ if(connssl->encdata_buffer == NULL) {
+ failf(data, "schannel: unable to allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* if we need a bigger buffer to read a full message, increase buffer now */
+ if(connssl->encdata_length - connssl->encdata_offset <
+ CURL_SCHANNEL_BUFFER_FREE_SIZE) {
+ /* increase internal encrypted data buffer */
+ connssl->encdata_length *= CURL_SCHANNEL_BUFFER_STEP_FACTOR;
+ connssl->encdata_buffer = realloc(connssl->encdata_buffer,
+ connssl->encdata_length);
+
+ if(connssl->encdata_buffer == NULL) {
+ failf(data, "schannel: unable to re-allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ for(;;) {
+ if(doread) {
+ /* read encrypted handshake data from socket */
+ code = Curl_read_plain(conn->sock[sockindex],
+ (char *) (connssl->encdata_buffer + connssl->encdata_offset),
+ connssl->encdata_length - connssl->encdata_offset,
+ &nread);
+ if(code == CURLE_AGAIN) {
+ if(connssl->connecting_state != ssl_connect_2_writing)
+ connssl->connecting_state = ssl_connect_2_reading;
+ infof(data, "schannel: failed to receive handshake, "
+ "need more data\n");
+ return CURLE_OK;
+ }
+ else if((code != CURLE_OK) || (nread == 0)) {
+ failf(data, "schannel: failed to receive handshake, "
+ "SSL/TLS connection failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* increase encrypted data buffer offset */
+ connssl->encdata_offset += nread;
+ }
+
+ infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
+ connssl->encdata_offset, connssl->encdata_length);
+
+ /* setup input buffers */
+ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset),
+ curlx_uztoul(connssl->encdata_offset));
+ InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
+ InitSecBufferDesc(&inbuf_desc, inbuf, 2);
+
+ /* setup output buffers */
+ InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
+ InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
+ InitSecBufferDesc(&outbuf_desc, outbuf, 2);
+
+ if(inbuf[0].pvBuffer == NULL) {
+ failf(data, "schannel: unable to allocate memory");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* copy received handshake data into input buffer */
+ memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
+ connssl->encdata_offset);
+
+ host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ if(!host_name)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */
+
+ sspi_status = s_pSecFn->InitializeSecurityContext(
+ &connssl->cred->cred_handle, &connssl->ctxt->ctxt_handle,
+ host_name, connssl->req_flags, 0, 0, &inbuf_desc, 0, NULL,
+ &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+
+ Curl_unicodefree(host_name);
+
+ /* free buffer for received handshake data */
+ Curl_safefree(inbuf[0].pvBuffer);
+
+ /* check if the handshake was incomplete */
+ if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ infof(data, "schannel: received incomplete message, need more data\n");
+ return CURLE_OK;
+ }
+
+ /* check if the handshake needs to be continued */
+ if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) {
+ for(i = 0; i < 2; i++) {
+ /* search for handshake tokens that need to be send */
+ if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
+ infof(data, "schannel: sending next handshake data: "
+ "sending %lu bytes...\n", outbuf[i].cbBuffer);
+
+ /* send handshake token to server */
+ code = Curl_write_plain(conn, conn->sock[sockindex],
+ outbuf[i].pvBuffer, outbuf[i].cbBuffer,
+ &written);
+ if((code != CURLE_OK) || (outbuf[i].cbBuffer != (size_t)written)) {
+ failf(data, "schannel: failed to send next handshake data: "
+ "sent %zd of %lu bytes", written, outbuf[i].cbBuffer);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* free obsolete buffer */
+ if(outbuf[i].pvBuffer != NULL) {
+ s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer);
+ }
+ }
+ }
+ else {
+ if(sspi_status == SEC_E_WRONG_PRINCIPAL)
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ else
+ failf(data, "schannel: next InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* check if there was additional remaining encrypted data */
+ if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
+ infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer);
+ /*
+ There are two cases where we could be getting extra data here:
+ 1) If we're renegotiating a connection and the handshake is already
+ complete (from the server perspective), it can encrypted app data
+ (not handshake data) in an extra buffer at this point.
+ 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a
+ connection and this extra data is part of the handshake.
+ We should process the data immediately; waiting for the socket to
+ be ready may fail since the server is done sending handshake data.
+ */
+ /* check if the remaining data is less than the total amount
+ and therefore begins after the already processed data */
+ if(connssl->encdata_offset > inbuf[1].cbBuffer) {
+ memmove(connssl->encdata_buffer,
+ (connssl->encdata_buffer + connssl->encdata_offset) -
+ inbuf[1].cbBuffer, inbuf[1].cbBuffer);
+ connssl->encdata_offset = inbuf[1].cbBuffer;
+ if(sspi_status == SEC_I_CONTINUE_NEEDED) {
+ doread = FALSE;
+ continue;
+ }
+ }
+ }
+ else {
+ connssl->encdata_offset = 0;
+ }
+ break;
+ }
+
+ /* check if the handshake needs to be continued */
+ if(sspi_status == SEC_I_CONTINUE_NEEDED) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+
+ /* check if the handshake is complete */
+ if(sspi_status == SEC_E_OK) {
+ connssl->connecting_state = ssl_connect_3;
+ infof(data, "schannel: SSL/TLS handshake complete\n");
+ }
+
+#ifdef _WIN32_WCE
+ /* Windows CE doesn't do any server certificate validation.
+ We have to do it manually. */
+ if(data->set.ssl.verifypeer)
+ return verify_certificate(conn, sockindex);
+#endif
+
+ return CURLE_OK;
+}
+
+static CURLcode
+schannel_connect_step3(struct connectdata *conn, int sockindex)
+{
+ CURLcode retcode = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct curl_schannel_cred *old_cred = NULL;
+ int incache;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+ infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
+ conn->host.name, conn->remote_port);
+
+ if(!connssl->cred)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* check if the required context attributes are met */
+ if(connssl->ret_flags != connssl->req_flags) {
+ if(!(connssl->ret_flags & ISC_RET_SEQUENCE_DETECT))
+ failf(data, "schannel: failed to setup sequence detection");
+ if(!(connssl->ret_flags & ISC_RET_REPLAY_DETECT))
+ failf(data, "schannel: failed to setup replay detection");
+ if(!(connssl->ret_flags & ISC_RET_CONFIDENTIALITY))
+ failf(data, "schannel: failed to setup confidentiality");
+ if(!(connssl->ret_flags & ISC_RET_ALLOCATED_MEMORY))
+ failf(data, "schannel: failed to setup memory allocation");
+ if(!(connssl->ret_flags & ISC_RET_STREAM))
+ failf(data, "schannel: failed to setup stream orientation");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* increment the reference counter of the credential/session handle */
+ if(connssl->cred && connssl->ctxt) {
+ connssl->cred->refcount++;
+ infof(data, "schannel: incremented credential handle refcount = %d\n",
+ connssl->cred->refcount);
+ }
+
+ /* save the current session data for possible re-use */
+ incache = !(Curl_ssl_getsessionid(conn, (void**)&old_cred, NULL));
+ if(incache) {
+ if(old_cred != connssl->cred) {
+ infof(data, "schannel: old credential handle is stale, removing\n");
+ Curl_ssl_delsessionid(conn, (void*)old_cred);
+ incache = FALSE;
+ }
+ }
+ if(!incache) {
+ retcode = Curl_ssl_addsessionid(conn, (void*)connssl->cred,
+ sizeof(struct curl_schannel_cred));
+ if(retcode) {
+ failf(data, "schannel: failed to store credential handle");
+ return retcode;
+ }
+ else {
+ connssl->cred->cached = TRUE;
+ infof(data, "schannel: stored credential handle in session cache\n");
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return CURLE_OK;
+}
+
+static CURLcode
+schannel_connect_common(struct connectdata *conn, int sockindex,
+ bool nonblocking, bool *done)
+{
+ CURLcode retcode;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1 == connssl->connecting_state) {
+ /* check out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL/TLS connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ retcode = schannel_connect_step1(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL/TLS connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing ==
+ connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading ==
+ connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking ? 0 : timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL/TLS connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if
+ * this connection is part of a multi handle and this loop would
+ * execute again. This permits the owner of a multi handle to
+ * abort a connection attempt before step2 has completed while
+ * ensuring that a client using select() or epoll() will always
+ * have a valid fdset to wait on.
+ */
+ retcode = schannel_connect_step2(conn, sockindex);
+ if(retcode || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return retcode;
+
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ retcode = schannel_connect_step3(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = schannel_recv;
+ conn->send[sockindex] = schannel_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* reset our connection state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+static ssize_t
+schannel_send(struct connectdata *conn, int sockindex,
+ const void *buf, size_t len, CURLcode *err)
+{
+ ssize_t written = -1;
+ size_t data_len = 0;
+ unsigned char *data = NULL;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SecBuffer outbuf[4];
+ SecBufferDesc outbuf_desc;
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+ CURLcode code;
+
+ /* check if the maximum stream sizes were queried */
+ if(connssl->stream_sizes.cbMaximumMessage == 0) {
+ sspi_status = s_pSecFn->QueryContextAttributes(
+ &connssl->ctxt->ctxt_handle,
+ SECPKG_ATTR_STREAM_SIZES,
+ &connssl->stream_sizes);
+ if(sspi_status != SEC_E_OK) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ }
+
+ /* check if the buffer is longer than the maximum message length */
+ if(len > connssl->stream_sizes.cbMaximumMessage) {
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ /* calculate the complete message length and allocate a buffer for it */
+ data_len = connssl->stream_sizes.cbHeader + len +
+ connssl->stream_sizes.cbTrailer;
+ data = (unsigned char*) malloc(data_len);
+ if(data == NULL) {
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ /* setup output buffers (header, data, trailer, empty) */
+ InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
+ data, connssl->stream_sizes.cbHeader);
+ InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
+ data + connssl->stream_sizes.cbHeader, curlx_uztoul(len));
+ InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
+ data + connssl->stream_sizes.cbHeader + len,
+ connssl->stream_sizes.cbTrailer);
+ InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
+ InitSecBufferDesc(&outbuf_desc, outbuf, 4);
+
+ /* copy data into output buffer */
+ memcpy(outbuf[1].pvBuffer, buf, len);
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */
+ sspi_status = s_pSecFn->EncryptMessage(&connssl->ctxt->ctxt_handle, 0,
+ &outbuf_desc, 0);
+
+ /* check if the message was encrypted */
+ if(sspi_status == SEC_E_OK) {
+ written = 0;
+
+ /* send the encrypted message including header, data and trailer */
+ len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
+
+ /*
+ It's important to send the full message which includes the header,
+ encrypted payload, and trailer. Until the client receives all the
+ data a coherent message has not been delivered and the client
+ can't read any of it.
+
+ If we wanted to buffer the unwritten encrypted bytes, we would
+ tell the client that all data it has requested to be sent has been
+ sent. The unwritten encrypted bytes would be the first bytes to
+ send on the next invocation.
+ Here's the catch with this - if we tell the client that all the
+ bytes have been sent, will the client call this method again to
+ send the buffered data? Looking at who calls this function, it
+ seems the answer is NO.
+ */
+
+ /* send entire message or fail */
+ while(len > (size_t)written) {
+ ssize_t this_write;
+ long timeleft;
+ int what;
+
+ this_write = 0;
+
+ timeleft = Curl_timeleft(conn->data, NULL, FALSE);
+ if(timeleft < 0) {
+ /* we already got the timeout */
+ failf(conn->data, "schannel: timed out sending data "
+ "(bytes sent: %zd)", written);
+ *err = CURLE_OPERATION_TIMEDOUT;
+ written = -1;
+ break;
+ }
+
+ what = Curl_socket_ready(CURL_SOCKET_BAD, conn->sock[sockindex],
+ timeleft);
+ if(what < 0) {
+ /* fatal error */
+ failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ *err = CURLE_SEND_ERROR;
+ written = -1;
+ break;
+ }
+ else if(0 == what) {
+ failf(conn->data, "schannel: timed out sending data "
+ "(bytes sent: %zd)", written);
+ *err = CURLE_OPERATION_TIMEDOUT;
+ written = -1;
+ break;
+ }
+ /* socket is writable */
+
+ code = Curl_write_plain(conn, conn->sock[sockindex], data + written,
+ len - written, &this_write);
+ if(code == CURLE_AGAIN)
+ continue;
+ else if(code != CURLE_OK) {
+ *err = code;
+ written = -1;
+ break;
+ }
+
+ written += this_write;
+ }
+ }
+ else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) {
+ *err = CURLE_OUT_OF_MEMORY;
+ }
+ else{
+ *err = CURLE_SEND_ERROR;
+ }
+
+ Curl_safefree(data);
+
+ if(len == (size_t)written)
+ /* Encrypted message including header, data and trailer entirely sent.
+ The return value is the number of unencrypted bytes that were sent. */
+ written = outbuf[1].cbBuffer;
+
+ return written;
+}
+
+static ssize_t
+schannel_recv(struct connectdata *conn, int sockindex,
+ char *buf, size_t len, CURLcode *err)
+{
+ size_t size = 0;
+ ssize_t nread = 0, ret = -1;
+ CURLcode retcode;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ bool done = FALSE;
+ SecBuffer inbuf[4];
+ SecBufferDesc inbuf_desc;
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+
+ infof(data, "schannel: client wants to read %zu bytes\n", len);
+ *err = CURLE_OK;
+
+ /* buffer to store previously received and decrypted data */
+ if(connssl->decdata_buffer == NULL) {
+ connssl->decdata_offset = 0;
+ connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+ connssl->decdata_buffer = malloc(connssl->decdata_length);
+ if(connssl->decdata_buffer == NULL) {
+ failf(data, "schannel: unable to allocate memory");
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ }
+
+ /* increase buffer in order to fit the requested amount of data */
+ while(connssl->encdata_length - connssl->encdata_offset <
+ CURL_SCHANNEL_BUFFER_FREE_SIZE || connssl->encdata_length < len) {
+ /* increase internal encrypted data buffer */
+ connssl->encdata_length *= CURL_SCHANNEL_BUFFER_STEP_FACTOR;
+ connssl->encdata_buffer = realloc(connssl->encdata_buffer,
+ connssl->encdata_length);
+
+ if(connssl->encdata_buffer == NULL) {
+ failf(data, "schannel: unable to re-allocate memory");
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ }
+
+ /* read encrypted data from socket */
+ infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
+ connssl->encdata_offset, connssl->encdata_length);
+ size = connssl->encdata_length - connssl->encdata_offset;
+ if(size > 0) {
+ *err = Curl_read_plain(conn->sock[sockindex],
+ (char *) (connssl->encdata_buffer + connssl->encdata_offset),
+ size, &nread);
+ /* check for received data */
+ if(*err != CURLE_OK)
+ ret = -1;
+ else {
+ if(nread > 0)
+ /* increase encrypted data buffer offset */
+ connssl->encdata_offset += nread;
+ ret = nread;
+ }
+ infof(data, "schannel: encrypted data got %zd\n", ret);
+ }
+
+ infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
+ connssl->encdata_offset, connssl->encdata_length);
+
+ /* check if we still have some data in our buffers */
+ while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK &&
+ connssl->decdata_offset < len) {
+ /* prepare data buffer for DecryptMessage call */
+ InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer,
+ curlx_uztoul(connssl->encdata_offset));
+
+ /* we need 3 more empty input buffers for possible output */
+ InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
+ InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
+ InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
+
+ InitSecBufferDesc(&inbuf_desc, inbuf, 4);
+
+ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx */
+ sspi_status = s_pSecFn->DecryptMessage(&connssl->ctxt->ctxt_handle,
+ &inbuf_desc, 0, NULL);
+
+ /* check if we need more data */
+ if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
+ infof(data, "schannel: failed to decrypt data, need more data\n");
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+
+ /* check if everything went fine (server may want to renegotiate
+ context) */
+ if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE ||
+ sspi_status == SEC_I_CONTEXT_EXPIRED) {
+ /* check for successfully decrypted data */
+ if(inbuf[1].BufferType == SECBUFFER_DATA) {
+ infof(data, "schannel: decrypted data length: %lu\n",
+ inbuf[1].cbBuffer);
+
+ /* increase buffer in order to fit the received amount of data */
+ size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ?
+ inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE;
+ while(connssl->decdata_length - connssl->decdata_offset < size ||
+ connssl->decdata_length < len) {
+ /* increase internal decrypted data buffer */
+ connssl->decdata_length *= CURL_SCHANNEL_BUFFER_STEP_FACTOR;
+ connssl->decdata_buffer = realloc(connssl->decdata_buffer,
+ connssl->decdata_length);
+
+ if(connssl->decdata_buffer == NULL) {
+ failf(data, "schannel: unable to re-allocate memory");
+ *err = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
+ }
+
+ /* copy decrypted data to internal buffer */
+ size = inbuf[1].cbBuffer;
+ if(size > 0) {
+ memcpy(connssl->decdata_buffer + connssl->decdata_offset,
+ inbuf[1].pvBuffer, size);
+ connssl->decdata_offset += size;
+ }
+
+ infof(data, "schannel: decrypted data added: %zu\n", size);
+ infof(data, "schannel: decrypted data cached: offset %zu length %zu\n",
+ connssl->decdata_offset, connssl->decdata_length);
+ }
+
+ /* check for remaining encrypted data */
+ if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
+ infof(data, "schannel: encrypted data length: %lu\n",
+ inbuf[3].cbBuffer);
+
+ /* check if the remaining data is less than the total amount
+ * and therefore begins after the already processed data
+ */
+ if(connssl->encdata_offset > inbuf[3].cbBuffer) {
+ /* move remaining encrypted data forward to the beginning of
+ buffer */
+ memmove(connssl->encdata_buffer,
+ (connssl->encdata_buffer + connssl->encdata_offset) -
+ inbuf[3].cbBuffer, inbuf[3].cbBuffer);
+ connssl->encdata_offset = inbuf[3].cbBuffer;
+ }
+
+ infof(data, "schannel: encrypted data cached: offset %zu length %zu\n",
+ connssl->encdata_offset, connssl->encdata_length);
+ }
+ else{
+ /* reset encrypted buffer offset, because there is no data remaining */
+ connssl->encdata_offset = 0;
+ }
+ }
+
+ /* check if server wants to renegotiate the connection context */
+ if(sspi_status == SEC_I_RENEGOTIATE) {
+ infof(data, "schannel: remote party requests SSL/TLS renegotiation\n");
+
+ /* begin renegotiation */
+ infof(data, "schannel: renegotiating SSL/TLS connection\n");
+ connssl->state = ssl_connection_negotiating;
+ connssl->connecting_state = ssl_connect_2_writing;
+ retcode = schannel_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ *err = retcode;
+ else {
+ infof(data, "schannel: SSL/TLS connection renegotiated\n");
+ /* now retry receiving data */
+ return schannel_recv(conn, sockindex, buf, len, err);
+ }
+ }
+ }
+
+ infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
+ connssl->decdata_offset, connssl->decdata_length);
+
+ /* copy requested decrypted data to supplied buffer */
+ size = len < connssl->decdata_offset ? len : connssl->decdata_offset;
+ if(size > 0) {
+ memcpy(buf, connssl->decdata_buffer, size);
+ ret = size;
+
+ /* move remaining decrypted data forward to the beginning of buffer */
+ memmove(connssl->decdata_buffer, connssl->decdata_buffer + size,
+ connssl->decdata_offset - size);
+ connssl->decdata_offset -= size;
+
+ infof(data, "schannel: decrypted data returned %zd\n", size);
+ infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
+ connssl->decdata_offset, connssl->decdata_length);
+ }
+
+ /* check if the server closed the connection */
+ if(ret <= 0 && ( /* special check for Windows 2000 Professional */
+ sspi_status == SEC_I_CONTEXT_EXPIRED || (sspi_status == SEC_E_OK &&
+ connssl->encdata_offset > 0 && connssl->encdata_buffer[0] == 0x15))) {
+ infof(data, "schannel: server closed the connection\n");
+ *err = CURLE_OK;
+ return 0;
+ }
+
+ /* check if something went wrong and we need to return an error */
+ if(ret < 0 && sspi_status != SEC_E_OK) {
+ infof(data, "schannel: failed to read data from server: %s\n",
+ Curl_sspi_strerror(conn, sspi_status));
+ *err = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ return ret;
+}
+
+CURLcode
+Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex,
+ bool *done)
+{
+ return schannel_connect_common(conn, sockindex, TRUE, done);
+}
+
+CURLcode
+Curl_schannel_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode retcode;
+ bool done = FALSE;
+
+ retcode = schannel_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ return retcode;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
+{
+ const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->use) /* SSL/TLS is in use */
+ return (connssl->encdata_offset > 0 ||
+ connssl->decdata_offset > 0 ) ? TRUE : FALSE;
+ else
+ return FALSE;
+}
+
+void Curl_schannel_close(struct connectdata *conn, int sockindex)
+{
+ if(conn->ssl[sockindex].use)
+ /* if the SSL/TLS channel hasn't been shut down yet, do that now. */
+ Curl_ssl_shutdown(conn, sockindex);
+}
+
+int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
+{
+ /* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
+ * Shutting Down an Schannel Connection
+ */
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
+ conn->host.name, conn->remote_port);
+
+ if(connssl->cred && connssl->ctxt) {
+ SecBufferDesc BuffDesc;
+ SecBuffer Buffer;
+ SECURITY_STATUS sspi_status;
+ SecBuffer outbuf;
+ SecBufferDesc outbuf_desc;
+ CURLcode code;
+ TCHAR *host_name;
+ DWORD dwshut = SCHANNEL_SHUTDOWN;
+
+ InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
+ InitSecBufferDesc(&BuffDesc, &Buffer, 1);
+
+ sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle,
+ &BuffDesc);
+
+ if(sspi_status != SEC_E_OK)
+ failf(data, "schannel: ApplyControlToken failure: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+
+ host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+ if(!host_name)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* setup output buffer */
+ InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
+ InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
+
+ sspi_status = s_pSecFn->InitializeSecurityContext(
+ &connssl->cred->cred_handle,
+ &connssl->ctxt->ctxt_handle,
+ host_name,
+ connssl->req_flags,
+ 0,
+ 0,
+ NULL,
+ 0,
+ &connssl->ctxt->ctxt_handle,
+ &outbuf_desc,
+ &connssl->ret_flags,
+ &connssl->ctxt->time_stamp);
+
+ Curl_unicodefree(host_name);
+
+ if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
+ /* send close message which is in output buffer */
+ ssize_t written;
+ code = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
+ outbuf.cbBuffer, &written);
+
+ s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
+ if((code != CURLE_OK) || (outbuf.cbBuffer != (size_t)written)) {
+ infof(data, "schannel: failed to send close msg: %s"
+ " (bytes written: %zd)\n", curl_easy_strerror(code), written);
+ }
+ }
+
+ /* free SSPI Schannel API security context handle */
+ if(connssl->ctxt) {
+ infof(data, "schannel: clear security context handle\n");
+ s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle);
+ Curl_safefree(connssl->ctxt);
+ }
+
+ /* free SSPI Schannel API credential handle */
+ if(connssl->cred) {
+ /* decrement the reference counter of the credential/session handle */
+ if(connssl->cred->refcount > 0) {
+ connssl->cred->refcount--;
+ infof(data, "schannel: decremented credential handle refcount = %d\n",
+ connssl->cred->refcount);
+ }
+
+ /* if the handle was not cached and the refcount is zero */
+ if(!connssl->cred->cached && connssl->cred->refcount == 0) {
+ infof(data, "schannel: clear credential handle\n");
+ s_pSecFn->FreeCredentialsHandle(&connssl->cred->cred_handle);
+ Curl_safefree(connssl->cred);
+ }
+ }
+ }
+
+ /* free internal buffer for received encrypted data */
+ if(connssl->encdata_buffer != NULL) {
+ Curl_safefree(connssl->encdata_buffer);
+ connssl->encdata_length = 0;
+ connssl->encdata_offset = 0;
+ }
+
+ /* free internal buffer for received decrypted data */
+ if(connssl->decdata_buffer != NULL) {
+ Curl_safefree(connssl->decdata_buffer);
+ connssl->decdata_length = 0;
+ connssl->decdata_offset = 0;
+ }
+
+ return CURLE_OK;
+}
+
+void Curl_schannel_session_free(void *ptr)
+{
+ struct curl_schannel_cred *cred = ptr;
+
+ if(cred && cred->cached && cred->refcount == 0) {
+ s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+ Curl_safefree(cred);
+ }
+}
+
+int Curl_schannel_init(void)
+{
+ return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
+}
+
+void Curl_schannel_cleanup(void)
+{
+ Curl_sspi_global_cleanup();
+}
+
+size_t Curl_schannel_version(char *buffer, size_t size)
+{
+ size = snprintf(buffer, size, "WinSSL");
+
+ return size;
+}
+
+int Curl_schannel_random(unsigned char *entropy, size_t length)
+{
+ HCRYPTPROV hCryptProv = 0;
+
+ if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ return 1;
+
+ if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
+ CryptReleaseContext(hCryptProv, 0UL);
+ return 1;
+ }
+
+ CryptReleaseContext(hCryptProv, 0UL);
+ return 0;
+}
+
+#ifdef _WIN32_WCE
+static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+{
+ SECURITY_STATUS status;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode result = CURLE_OK;
+ CERT_CONTEXT *pCertContextServer = NULL;
+ const CERT_CHAIN_CONTEXT *pChainContext = NULL;
+
+ status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
+
+ if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ failf(data, "schannel: Failed to read remote certificate context: %s",
+ Curl_sspi_strerror(conn, status));
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK) {
+ CERT_CHAIN_PARA ChainPara;
+ memset(&ChainPara, 0, sizeof(ChainPara));
+ ChainPara.cbSize = sizeof(ChainPara);
+
+ if(!CertGetCertificateChain(NULL,
+ pCertContextServer,
+ NULL,
+ pCertContextServer->hCertStore,
+ &ChainPara,
+ 0,
+ NULL,
+ &pChainContext)) {
+ failf(data, "schannel: CertGetCertificateChain failed: %s",
+ Curl_sspi_strerror(conn, GetLastError()));
+ pChainContext = NULL;
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK) {
+ CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
+ DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED|
+ CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
+ dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
+ if(dwTrustErrorMask) {
+ if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_PARTIAL_CHAIN");
+ if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_UNTRUSTED_ROOT");
+ if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_NOT_TIME_VALID");
+ failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
+ dwTrustErrorMask);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(data->set.ssl.verifyhost) {
+ TCHAR cert_hostname_buff[128];
+ xcharp_u hostname;
+ xcharp_u cert_hostname;
+ DWORD len;
+
+ cert_hostname.const_tchar_ptr = cert_hostname_buff;
+ hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name);
+
+ len = CertGetNameString(pCertContextServer,
+ CERT_NAME_DNS_TYPE,
+ 0,
+ NULL,
+ cert_hostname.tchar_ptr,
+ 128);
+ if(len > 0 && *cert_hostname.tchar_ptr == '*') {
+ /* this is a wildcard cert. try matching the last len - 1 chars */
+ int hostname_len = strlen(conn->host.name);
+ cert_hostname.tchar_ptr++;
+ if(_tcsicmp(cert_hostname.const_tchar_ptr,
+ hostname.const_tchar_ptr + hostname_len - len + 2) != 0)
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr,
+ cert_hostname.const_tchar_ptr) != 0) {
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ if(result == CURLE_PEER_FAILED_VERIFICATION) {
+ char *_cert_hostname;
+ _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr);
+ failf(data, "schannel: CertGetNameString() certificate hostname "
+ "(%s) did not match connection (%s)",
+ _cert_hostname, conn->host.name);
+ Curl_unicodefree(_cert_hostname);
+ }
+ Curl_unicodefree(hostname.tchar_ptr);
+ }
+ }
+
+ if(pChainContext)
+ CertFreeCertificateChain(pChainContext);
+
+ if(pCertContextServer)
+ CertFreeCertificateContext(pCertContextServer);
+
+ return result;
+}
+#endif /* _WIN32_WCE */
+
+#endif /* USE_SCHANNEL */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/curl_schannel.h b/external/libcurl_android/jni/libcurl/lib/vtls/curl_schannel.h
new file mode 100755
index 00000000..700516b3
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/curl_schannel.h
@@ -0,0 +1,137 @@
+#ifndef HEADER_CURL_SCHANNEL_H
+#define HEADER_CURL_SCHANNEL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_SCHANNEL
+
+#include "urldata.h"
+
+#ifndef UNISP_NAME_A
+#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
+#endif
+
+#ifndef UNISP_NAME_W
+#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
+#endif
+
+#ifndef UNISP_NAME
+#ifdef UNICODE
+#define UNISP_NAME UNISP_NAME_W
+#else
+#define UNISP_NAME UNISP_NAME_A
+#endif
+#endif
+
+#ifndef SP_PROT_SSL2_CLIENT
+#define SP_PROT_SSL2_CLIENT 0x00000008
+#endif
+
+#ifndef SP_PROT_SSL3_CLIENT
+#define SP_PROT_SSL3_CLIENT 0x00000008
+#endif
+
+#ifndef SP_PROT_TLS1_CLIENT
+#define SP_PROT_TLS1_CLIENT 0x00000080
+#endif
+
+#ifndef SP_PROT_TLS1_0_CLIENT
+#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT
+#endif
+
+#ifndef SP_PROT_TLS1_1_CLIENT
+#define SP_PROT_TLS1_1_CLIENT 0x00000200
+#endif
+
+#ifndef SP_PROT_TLS1_2_CLIENT
+#define SP_PROT_TLS1_2_CLIENT 0x00000800
+#endif
+
+#ifndef SECBUFFER_ALERT
+#define SECBUFFER_ALERT 17
+#endif
+
+#ifndef ISC_RET_REPLAY_DETECT
+#define ISC_RET_REPLAY_DETECT 0x00000004
+#endif
+
+#ifndef ISC_RET_SEQUENCE_DETECT
+#define ISC_RET_SEQUENCE_DETECT 0x00000008
+#endif
+
+#ifndef ISC_RET_CONFIDENTIALITY
+#define ISC_RET_CONFIDENTIALITY 0x00000010
+#endif
+
+#ifndef ISC_RET_ALLOCATED_MEMORY
+#define ISC_RET_ALLOCATED_MEMORY 0x00000100
+#endif
+
+#ifndef ISC_RET_STREAM
+#define ISC_RET_STREAM 0x00008000
+#endif
+
+
+#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
+#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
+#define CURL_SCHANNEL_BUFFER_STEP_FACTOR 2
+
+
+CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex);
+
+CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex);
+void Curl_schannel_close(struct connectdata *conn, int sockindex);
+int Curl_schannel_shutdown(struct connectdata *conn, int sockindex);
+void Curl_schannel_session_free(void *ptr);
+
+int Curl_schannel_init(void);
+void Curl_schannel_cleanup(void);
+size_t Curl_schannel_version(char *buffer, size_t size);
+
+int Curl_schannel_random(unsigned char *entropy, size_t length);
+
+/* API setup for Schannel */
+#define curlssl_init Curl_schannel_init
+#define curlssl_cleanup Curl_schannel_cleanup
+#define curlssl_connect Curl_schannel_connect
+#define curlssl_connect_nonblocking Curl_schannel_connect_nonblocking
+#define curlssl_session_free Curl_schannel_session_free
+#define curlssl_close_all(x) (x=x, CURLE_NOT_BUILT_IN)
+#define curlssl_close Curl_schannel_close
+#define curlssl_shutdown Curl_schannel_shutdown
+#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_schannel_version
+#define curlssl_check_cxn(x) (x=x, -1)
+#define curlssl_data_pending Curl_schannel_data_pending
+#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL
+#define curlssl_random(x,y,z) ((void)x, Curl_schannel_random(y,z))
+
+#endif /* USE_SCHANNEL */
+#endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/cyassl.c b/external/libcurl_android/jni/libcurl/lib/vtls/cyassl.c
new file mode 100755
index 00000000..9b5c7c61
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/cyassl.c
@@ -0,0 +1,655 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_CYASSL
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "cyassl.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "rawstr.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+#include "curl_memory.h"
+
+#include <cyassl/ssl.h>
+#ifdef HAVE_CYASSL_ERROR_SSL_H
+#include <cyassl/error-ssl.h>
+#else
+#include <cyassl/error.h>
+#endif
+#include <cyassl/ctaocrypt/random.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+static Curl_recv cyassl_recv;
+static Curl_send cyassl_send;
+
+
+static int do_file_type(const char *type)
+{
+ if(!type || !type[0])
+ return SSL_FILETYPE_PEM;
+ if(Curl_raw_equal(type, "PEM"))
+ return SSL_FILETYPE_PEM;
+ if(Curl_raw_equal(type, "DER"))
+ return SSL_FILETYPE_ASN1;
+ return -1;
+}
+
+/*
+ * This function loads all the client/CA certificates and CRLs. Setup the TLS
+ * layer and do all necessary magic.
+ */
+static CURLcode
+cyassl_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+ SSL_METHOD* req_method = NULL;
+ void* ssl_sessionid = NULL;
+ curl_socket_t sockfd = conn->sock[sockindex];
+
+ if(conssl->state == ssl_connection_complete)
+ return CURLE_OK;
+
+ /* CyaSSL doesn't support SSLv2 */
+ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ failf(data, "CyaSSL does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* check to see if we've been told to use an explicit SSL/TLS version */
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ /* we try to figure out version */
+ req_method = SSLv23_client_method();
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ infof(data, "CyaSSL cannot be configured to use TLS 1.0-1.2, "
+ "TLS 1.0 is used exclusively\n");
+ req_method = TLSv1_client_method();
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ req_method = TLSv1_client_method();
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ req_method = TLSv1_1_client_method();
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ req_method = TLSv1_2_client_method();
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ req_method = SSLv3_client_method();
+ break;
+ default:
+ req_method = TLSv1_client_method();
+ }
+
+ if(!req_method) {
+ failf(data, "SSL: couldn't create a method!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(conssl->ctx)
+ SSL_CTX_free(conssl->ctx);
+ conssl->ctx = SSL_CTX_new(req_method);
+
+ if(!conssl->ctx) {
+ failf(data, "SSL: couldn't create a context!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifndef NO_FILESYSTEM
+ /* load trusted cacert */
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ if(!SSL_CTX_load_verify_locations(conssl->ctx,
+ data->set.str[STRING_SSL_CAFILE],
+ data->set.str[STRING_SSL_CAPATH])) {
+ if(data->set.ssl.verifypeer) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data,"error setting certificate verify locations:\n"
+ " CAfile: %s\n CApath: %s",
+ data->set.str[STRING_SSL_CAFILE]?
+ data->set.str[STRING_SSL_CAFILE]: "none",
+ data->set.str[STRING_SSL_CAPATH]?
+ data->set.str[STRING_SSL_CAPATH] : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Just continue with a warning if no strict certificate
+ verification is required. */
+ infof(data, "error setting certificate verify locations,"
+ " continuing anyway:\n");
+ }
+ }
+ else {
+ /* Everything is fine. */
+ infof(data, "successfully set certificate verify locations:\n");
+ }
+ infof(data,
+ " CAfile: %s\n"
+ " CApath: %s\n",
+ data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
+ "none",
+ data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
+ "none");
+ }
+
+ /* Load the client certificate, and private key */
+ if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
+ int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
+
+ if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
+ file_type) != 1) {
+ failf(data, "unable to use client certificate (no key or wrong pass"
+ " phrase?)");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
+ if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
+ file_type) != 1) {
+ failf(data, "unable to set private key");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+#else
+ if(CyaSSL_no_filesystem_verify(conssl->ctx)!= SSL_SUCCESS) {
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif /* NO_FILESYSTEM */
+
+ /* SSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+ * anyway. In the latter case the result of the verification is checked with
+ * SSL_get_verify_result() below. */
+ SSL_CTX_set_verify(conssl->ctx,
+ data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
+ NULL);
+
+ /* Let's make an SSL structure */
+ if(conssl->handle)
+ SSL_free(conssl->handle);
+ conssl->handle = SSL_new(conssl->ctx);
+ if(!conssl->handle) {
+ failf(data, "SSL: couldn't create a context (handle)!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Check if there's a cached ID we can/should use here! */
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+ /* we got a session id, use it! */
+ if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
+ failf(data, "SSL: SSL_set_session failed: %s",
+ ERR_error_string(SSL_get_error(conssl->handle, 0),NULL));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof (data, "SSL re-using session ID\n");
+ }
+
+ /* pass the raw socket into the SSL layer */
+ if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
+ failf(data, "SSL: SSL_set_fd failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ conssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+}
+
+
+static CURLcode
+cyassl_connect_step2(struct connectdata *conn,
+ int sockindex)
+{
+ int ret = -1;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+
+ infof(data, "CyaSSL: Connecting to %s:%d\n",
+ conn->host.name, conn->remote_port);
+
+ conn->recv[sockindex] = cyassl_recv;
+ conn->send[sockindex] = cyassl_send;
+
+ /* Enable RFC2818 checks */
+ if(data->set.ssl.verifyhost) {
+ ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
+ if(ret == SSL_FAILURE)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ ret = SSL_connect(conssl->handle);
+ if(ret != 1) {
+ char error_buffer[80];
+ int detail = SSL_get_error(conssl->handle, ret);
+
+ if(SSL_ERROR_WANT_READ == detail) {
+ conssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+ else if(SSL_ERROR_WANT_WRITE == detail) {
+ conssl->connecting_state = ssl_connect_2_writing;
+ return CURLE_OK;
+ }
+ /* There is no easy way to override only the CN matching.
+ * This will enable the override of both mismatching SubjectAltNames
+ * as also mismatching CN fields */
+ else if(DOMAIN_NAME_MISMATCH == detail) {
+#if 1
+ failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
+ conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+#else
+ /* When the CyaSSL_check_domain_name() is used and you desire to continue
+ * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0',
+ * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only
+ * way to do this is currently to switch the CyaSSL_check_domain_name()
+ * in and out based on the 'data->set.ssl.verifyhost' value. */
+ if(data->set.ssl.verifyhost) {
+ failf(data,
+ "\tsubject alt name(s) or common name do not match \"%s\"\n",
+ conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else {
+ infof(data,
+ "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
+ conn->host.dispname);
+ return CURLE_OK;
+ }
+#endif
+ }
+#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
+ else if(ASN_NO_SIGNER_E == detail) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "\tCA signer not available for verification\n");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Just continue with a warning if no strict certificate
+ verification is required. */
+ infof(data, "CA signer not available for verification, "
+ "continuing anyway\n");
+ }
+ }
+#endif
+ else {
+ failf(data, "SSL_connect failed with error %d: %s", detail,
+ ERR_error_string(detail, error_buffer));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ conssl->connecting_state = ssl_connect_3;
+ infof(data, "SSL connected\n");
+
+ return CURLE_OK;
+}
+
+
+static CURLcode
+cyassl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode = CURLE_OK;
+ void *old_ssl_sessionid=NULL;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ int incache;
+ SSL_SESSION *our_ssl_sessionid;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+ our_ssl_sessionid = SSL_get_session(connssl->handle);
+
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+ if(!incache) {
+ retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
+ 0 /* unknown size */);
+ if(retcode) {
+ failf(data, "failed to store ssl session");
+ return retcode;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return retcode;
+}
+
+
+static ssize_t cyassl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ char error_buffer[80];
+ int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
+ int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+
+ if(rc < 0) {
+ int err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+
+ switch(err) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_write() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ failf(conn->data, "SSL write: %s, errno %d",
+ ERR_error_string(err, error_buffer),
+ SOCKERRNO);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+ }
+ return rc;
+}
+
+void Curl_cyassl_close_all(struct SessionHandle *data)
+{
+ (void)data;
+}
+
+void Curl_cyassl_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *conssl = &conn->ssl[sockindex];
+
+ if(conssl->handle) {
+ (void)SSL_shutdown(conssl->handle);
+ SSL_free (conssl->handle);
+ conssl->handle = NULL;
+ }
+ if(conssl->ctx) {
+ SSL_CTX_free (conssl->ctx);
+ conssl->ctx = NULL;
+ }
+}
+
+static ssize_t cyassl_recv(struct connectdata *conn,
+ int num,
+ char *buf,
+ size_t buffersize,
+ CURLcode *curlcode)
+{
+ char error_buffer[80];
+ int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ int nread = SSL_read(conn->ssl[num].handle, buf, buffsize);
+
+ if(nread < 0) {
+ int err = SSL_get_error(conn->ssl[num].handle, nread);
+
+ switch(err) {
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_read() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ failf(conn->data, "SSL read: %s, errno %d",
+ ERR_error_string(err, error_buffer),
+ SOCKERRNO);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+ }
+ return nread;
+}
+
+
+void Curl_cyassl_session_free(void *ptr)
+{
+ (void)ptr;
+ /* CyaSSL reuses sessions on own, no free */
+}
+
+
+size_t Curl_cyassl_version(char *buffer, size_t size)
+{
+#ifdef CYASSL_VERSION
+ return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
+#else
+ return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
+#endif
+}
+
+
+int Curl_cyassl_init(void)
+{
+ if(CyaSSL_Init() == 0)
+ return 1;
+
+ return -1;
+}
+
+
+bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
+{
+ if(conn->ssl[connindex].handle) /* SSL is in use */
+ return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+ else
+ return FALSE;
+}
+
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
+{
+ int retval = 0;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->handle) {
+ SSL_free (connssl->handle);
+ connssl->handle = NULL;
+ }
+ return retval;
+}
+
+
+static CURLcode
+cyassl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode retcode;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1==connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ retcode = cyassl_connect_step1(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if
+ * this connection is part of a multi handle and this loop would
+ * execute again. This permits the owner of a multi handle to
+ * abort a connection attempt before step2 has completed while
+ * ensuring that a client using select() or epoll() will always
+ * have a valid fdset to wait on.
+ */
+ retcode = cyassl_connect_step2(conn, sockindex);
+ if(retcode || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return retcode;
+
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3==connssl->connecting_state) {
+ retcode = cyassl_connect_step3(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ if(ssl_connect_done==connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = cyassl_recv;
+ conn->send[sockindex] = cyassl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+
+CURLcode
+Curl_cyassl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return cyassl_connect_common(conn, sockindex, TRUE, done);
+}
+
+
+CURLcode
+Curl_cyassl_connect(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode;
+ bool done = FALSE;
+
+ retcode = cyassl_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ return retcode;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+int Curl_cyassl_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+ RNG rng;
+ (void)data;
+ if(InitRng(&rng))
+ return 1;
+ if(RNG_GenerateBlock(&rng, entropy, length))
+ return 1;
+ return 0;
+}
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/cyassl.h b/external/libcurl_android/jni/libcurl/lib/vtls/cyassl.h
new file mode 100755
index 00000000..b10b607d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/cyassl.h
@@ -0,0 +1,69 @@
+#ifndef HEADER_CURL_CYASSL_H
+#define HEADER_CURL_CYASSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_CYASSL
+
+CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex);
+bool Curl_cyassl_data_pending(const struct connectdata* conn,int connindex);
+int Curl_cyassl_shutdown(struct connectdata* conn, int sockindex);
+
+/* tell CyaSSL to close down all open information regarding connections (and
+ thus session ID caching etc) */
+void Curl_cyassl_close_all(struct SessionHandle *data);
+
+ /* close a SSL connection */
+void Curl_cyassl_close(struct connectdata *conn, int sockindex);
+
+void Curl_cyassl_session_free(void *ptr);
+size_t Curl_cyassl_version(char *buffer, size_t size);
+int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex);
+int Curl_cyassl_init(void);
+CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+int Curl_cyassl_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length);
+
+/* API setup for CyaSSL */
+#define curlssl_init Curl_cyassl_init
+#define curlssl_cleanup() Curl_nop_stmt
+#define curlssl_connect Curl_cyassl_connect
+#define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking
+#define curlssl_session_free(x) Curl_cyassl_session_free(x)
+#define curlssl_close_all Curl_cyassl_close_all
+#define curlssl_close Curl_cyassl_close
+#define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y)
+#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_cyassl_version
+#define curlssl_check_cxn(x) (x=x, -1)
+#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y)
+#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z)
+#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
+
+#endif /* USE_CYASSL */
+#endif /* HEADER_CURL_CYASSL_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/gskit.c b/external/libcurl_android/jni/libcurl/lib/vtls/gskit.c
new file mode 100755
index 00000000..0f8b08f2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/gskit.c
@@ -0,0 +1,1053 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_GSKIT
+
+#include <gskssl.h>
+#include <qsoasync.h>
+
+/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
+#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
+#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
+#endif
+
+#ifndef GSK_TLSV10_CIPHER_SPECS
+#define GSK_TLSV10_CIPHER_SPECS 236
+#endif
+
+#ifndef GSK_TLSV11_CIPHER_SPECS
+#define GSK_TLSV11_CIPHER_SPECS 237
+#endif
+
+#ifndef GSK_TLSV12_CIPHER_SPECS
+#define GSK_TLSV12_CIPHER_SPECS 238
+#endif
+
+#ifndef GSK_PROTOCOL_TLSV11
+#define GSK_PROTOCOL_TLSV11 437
+#endif
+
+#ifndef GSK_PROTOCOL_TLSV12
+#define GSK_PROTOCOL_TLSV12 438
+#endif
+
+#ifndef GSK_FALSE
+#define GSK_FALSE 0
+#endif
+
+#ifndef GSK_TRUE
+#define GSK_TRUE 1
+#endif
+
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "gskit.h"
+#include "vtls.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "strequal.h"
+#include "x509asn1.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+
+/* SSL version flags. */
+#define CURL_GSKPROTO_SSLV2 0
+#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
+#define CURL_GSKPROTO_SSLV3 1
+#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
+#define CURL_GSKPROTO_TLSV10 2
+#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
+#define CURL_GSKPROTO_TLSV11 3
+#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
+#define CURL_GSKPROTO_TLSV12 4
+#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
+#define CURL_GSKPROTO_LAST 5
+
+
+/* Supported ciphers. */
+typedef struct {
+ const char *name; /* Cipher name. */
+ const char *gsktoken; /* Corresponding token for GSKit String. */
+ unsigned int versions; /* SSL version flags. */
+} gskit_cipher;
+
+static const gskit_cipher ciphertable[] = {
+ { "null-md5", "01",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "null-sha", "02",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "exp-rc4-md5", "03",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
+ { "rc4-md5", "04",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "rc4-sha", "05",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "exp-rc2-cbc-md5", "06",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
+ { "exp-des-cbc-sha", "09",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK },
+ { "des-cbc3-sha", "0A",
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
+ { "aes128-sha", "2F",
+ CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
+ CURL_GSKPROTO_TLSV12_MASK },
+ { "aes256-sha", "35",
+ CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
+ CURL_GSKPROTO_TLSV12_MASK },
+ { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
+ { "aes128-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
+ { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
+ { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
+ { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
+ { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
+ { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
+ { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
+ { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
+ { (const char *) NULL, (const char *) NULL, 0 }
+};
+
+
+static bool is_separator(char c)
+{
+ /* Return whether character is a cipher list separator. */
+ switch (c) {
+ case ' ':
+ case '\t':
+ case ':':
+ case ',':
+ case ';':
+ return true;
+ }
+ return false;
+}
+
+
+static CURLcode gskit_status(struct SessionHandle *data, int rc,
+ const char *procname, CURLcode defcode)
+{
+ CURLcode cc;
+
+ /* Process GSKit status and map it to a CURLcode. */
+ switch (rc) {
+ case GSK_OK:
+ case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
+ return CURLE_OK;
+ case GSK_KEYRING_OPEN_ERROR:
+ case GSK_OS400_ERROR_NO_ACCESS:
+ return CURLE_SSL_CACERT_BADFILE;
+ case GSK_INSUFFICIENT_STORAGE:
+ return CURLE_OUT_OF_MEMORY;
+ case GSK_ERROR_BAD_V2_CIPHER:
+ case GSK_ERROR_BAD_V3_CIPHER:
+ case GSK_ERROR_NO_CIPHERS:
+ return CURLE_SSL_CIPHER;
+ case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
+ case GSK_ERROR_CERT_VALIDATION:
+ return CURLE_PEER_FAILED_VERIFICATION;
+ case GSK_OS400_ERROR_TIMED_OUT:
+ return CURLE_OPERATION_TIMEDOUT;
+ case GSK_WOULD_BLOCK:
+ return CURLE_AGAIN;
+ case GSK_OS400_ERROR_NOT_REGISTERED:
+ break;
+ case GSK_ERROR_IO:
+ switch (errno) {
+ case ENOMEM:
+ return CURLE_OUT_OF_MEMORY;
+ default:
+ failf(data, "%s I/O error: %s", procname, strerror(errno));
+ break;
+ }
+ break;
+ default:
+ failf(data, "%s: %s", procname, gsk_strerror(rc));
+ break;
+ }
+ return defcode;
+}
+
+
+static CURLcode set_enum(struct SessionHandle *data, gsk_handle h,
+ GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
+{
+ int rc = gsk_attribute_set_enum(h, id, value);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
+ break;
+ case GSK_ATTRIBUTE_INVALID_ID:
+ if(unsupported_ok)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ default:
+ failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_buffer(struct SessionHandle *data, gsk_handle h,
+ GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
+{
+ int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
+ break;
+ case GSK_ATTRIBUTE_INVALID_ID:
+ if(unsupported_ok)
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ default:
+ failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_numeric(struct SessionHandle *data,
+ gsk_handle h, GSK_NUM_ID id, int value)
+{
+ int rc = gsk_attribute_set_numeric_value(h, id, value);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
+ strerror(errno));
+ break;
+ default:
+ failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_callback(struct SessionHandle *data,
+ gsk_handle h, GSK_CALLBACK_ID id, void *info)
+{
+ int rc = gsk_attribute_set_callback(h, id, info);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
+ break;
+ default:
+ failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_ciphers(struct SessionHandle *data,
+ gsk_handle h, unsigned int *protoflags)
+{
+ const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
+ const char *clp;
+ const gskit_cipher *ctp;
+ int i;
+ int l;
+ bool unsupported;
+ CURLcode cc;
+ struct {
+ char *buf;
+ char *ptr;
+ } ciphers[CURL_GSKPROTO_LAST];
+
+ /* Compile cipher list into GSKit-compatible cipher lists. */
+
+ if(!cipherlist)
+ return CURLE_OK;
+ while(is_separator(*cipherlist)) /* Skip initial separators. */
+ cipherlist++;
+ if(!*cipherlist)
+ return CURLE_OK;
+
+ /* We allocate GSKit buffers of the same size as the input string: since
+ GSKit tokens are always shorter than their cipher names, allocated buffers
+ will always be large enough to accomodate the result. */
+ l = strlen(cipherlist) + 1;
+ memset((char *) ciphers, 0, sizeof ciphers);
+ for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
+ ciphers[i].buf = malloc(l);
+ if(!ciphers[i].buf) {
+ while(i--)
+ free(ciphers[i].buf);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ ciphers[i].ptr = ciphers[i].buf;
+ *ciphers[i].ptr = '\0';
+ }
+
+ /* Process each cipher in input string. */
+ unsupported = FALSE;
+ cc = CURLE_OK;
+ for(;;) {
+ for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
+ cipherlist++;
+ l = cipherlist - clp;
+ if(!l)
+ break;
+ /* Search the cipher in our table. */
+ for(ctp = ciphertable; ctp->name; ctp++)
+ if(strnequal(ctp->name, clp, l) && !ctp->name[l])
+ break;
+ if(!ctp->name) {
+ failf(data, "Unknown cipher %.*s", l, clp);
+ cc = CURLE_SSL_CIPHER;
+ }
+ else {
+ unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
+ CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
+ for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
+ if(ctp->versions & (1 << i)) {
+ strcpy(ciphers[i].ptr, ctp->gsktoken);
+ ciphers[i].ptr += strlen(ctp->gsktoken);
+ }
+ }
+ }
+
+ /* Advance to next cipher name or end of string. */
+ while(is_separator(*cipherlist))
+ cipherlist++;
+ }
+
+ /* Disable protocols with empty cipher lists. */
+ for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
+ if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
+ *protoflags &= ~(1 << i);
+ ciphers[i].buf[0] = '\0';
+ }
+ }
+
+ /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
+ if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
+ cc = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
+ if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
+ cc = CURLE_OK;
+ if(unsupported) {
+ failf(data, "TLSv1.1-only ciphers are not yet supported");
+ cc = CURLE_SSL_CIPHER;
+ }
+ }
+ }
+ if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
+ cc = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
+ if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
+ cc = CURLE_OK;
+ if(unsupported) {
+ failf(data, "TLSv1.2-only ciphers are not yet supported");
+ cc = CURLE_SSL_CIPHER;
+ }
+ }
+ }
+
+ /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
+ the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
+ if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
+ cc = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
+ if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
+ cc = CURLE_OK;
+ strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
+ ciphers[CURL_GSKPROTO_TLSV10].ptr);
+ }
+ }
+
+ /* Set-up other ciphers. */
+ if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
+ cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
+ if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
+ cc = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
+ ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
+
+ /* Clean-up. */
+ for(i = 0; i < CURL_GSKPROTO_LAST; i++)
+ free(ciphers[i].buf);
+
+ return cc;
+}
+
+
+int Curl_gskit_init(void)
+{
+ /* No initialisation needed. */
+
+ return 1;
+}
+
+
+void Curl_gskit_cleanup(void)
+{
+ /* Nothing to do. */
+}
+
+
+static CURLcode init_environment(struct SessionHandle *data,
+ gsk_handle *envir, const char *appid,
+ const char *file, const char *label,
+ const char *password)
+{
+ int rc;
+ CURLcode c;
+ gsk_handle h;
+
+ /* Creates the GSKit environment. */
+
+ rc = gsk_environment_open(&h);
+ switch (rc) {
+ case GSK_OK:
+ break;
+ case GSK_INSUFFICIENT_STORAGE:
+ return CURLE_OUT_OF_MEMORY;
+ default:
+ failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
+ if(c == CURLE_OK && appid)
+ c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
+ if(c == CURLE_OK && file)
+ c = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
+ if(c == CURLE_OK && label)
+ c = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
+ if(c == CURLE_OK && password)
+ c = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
+
+ if(c == CURLE_OK) {
+ /* Locate CAs, Client certificate and key according to our settings.
+ Note: this call may be blocking for some tenths of seconds. */
+ c = gskit_status(data, gsk_environment_init(h),
+ "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
+ if(c == CURLE_OK) {
+ *envir = h;
+ return c;
+ }
+ }
+ /* Error: rollback. */
+ gsk_environment_close(&h);
+ return c;
+}
+
+
+static void cancel_async_handshake(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ Qso_OverlappedIO_t cstat;
+
+ if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
+ QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
+}
+
+
+static void close_async_handshake(struct ssl_connect_data *connssl)
+{
+ QsoDestroyIOCompletionPort(connssl->iocport);
+ connssl->iocport = -1;
+}
+
+
+static void close_one(struct ssl_connect_data *conn,
+ struct SessionHandle *data)
+{
+ if(conn->handle) {
+ gskit_status(data, gsk_secure_soc_close(&conn->handle),
+ "gsk_secure_soc_close()", 0);
+ conn->handle = (gsk_handle) NULL;
+ }
+ if(conn->iocport >= 0)
+ close_async_handshake(conn);
+}
+
+
+static ssize_t gskit_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, CURLcode *curlcode)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode cc;
+ int written;
+
+ cc = gskit_status(data,
+ gsk_secure_soc_write(conn->ssl[sockindex].handle,
+ (char *) mem, (int) len, &written),
+ "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+ if(cc != CURLE_OK) {
+ *curlcode = cc;
+ written = -1;
+ }
+ return (ssize_t) written; /* number of bytes */
+}
+
+
+static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
+ size_t buffersize, CURLcode *curlcode)
+{
+ struct SessionHandle *data = conn->data;
+ int buffsize;
+ int nread;
+ CURLcode cc;
+
+ buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
+ cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+ buf, buffsize, &nread),
+ "gsk_secure_soc_read()", CURLE_RECV_ERROR);
+ if(cc != CURLE_OK) {
+ *curlcode = cc;
+ nread = -1;
+ }
+ return (ssize_t) nread;
+}
+
+
+static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ gsk_handle envir;
+ CURLcode cc;
+ int rc;
+ char *keyringfile;
+ char *keyringpwd;
+ char *keyringlabel;
+ char *sni;
+ unsigned int protoflags;
+ long timeout;
+ Qso_OverlappedIO_t commarea;
+
+ /* Create SSL environment, start (preferably asynchronous) handshake. */
+
+ connssl->handle = (gsk_handle) NULL;
+ connssl->iocport = -1;
+
+ /* GSKit supports two ways of specifying an SSL context: either by
+ * application identifier (that should have been defined at the system
+ * level) or by keyring file, password and certificate label.
+ * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
+ * application identifier of the certificate label.
+ * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
+ * It is not possible to have different keyrings for the CAs and the
+ * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
+ * the keyring file.
+ * If no key password is given and the keyring is the system keyring,
+ * application identifier mode is tried first, as recommended in IBM doc.
+ */
+
+ keyringfile = data->set.str[STRING_SSL_CAFILE];
+ keyringpwd = data->set.str[STRING_KEY_PASSWD];
+ keyringlabel = data->set.str[STRING_CERT];
+ envir = (gsk_handle) NULL;
+
+ if(keyringlabel && *keyringlabel && !keyringpwd &&
+ !strcmp(keyringfile, CURL_CA_BUNDLE)) {
+ /* Try application identifier mode. */
+ init_environment(data, &envir, keyringlabel, (const char *) NULL,
+ (const char *) NULL, (const char *) NULL);
+ }
+
+ if(!envir) {
+ /* Use keyring mode. */
+ cc = init_environment(data, &envir, (const char *) NULL,
+ keyringfile, keyringlabel, keyringpwd);
+ if(cc != CURLE_OK)
+ return cc;
+ }
+
+ /* Create secure session. */
+ cc = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
+ "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
+ gsk_environment_close(&envir);
+ if(cc != CURLE_OK)
+ return cc;
+
+ /* Determine which SSL/TLS version should be enabled. */
+ protoflags = CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
+ sni = conn->host.name;
+ switch (data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv2:
+ protoflags = CURL_GSKPROTO_SSLV2_MASK;
+ sni = (char *) NULL;
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ protoflags = CURL_GSKPROTO_SSLV2_MASK;
+ sni = (char *) NULL;
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ protoflags = CURL_GSKPROTO_TLSV10_MASK |
+ CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ protoflags = CURL_GSKPROTO_TLSV10_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ protoflags = CURL_GSKPROTO_TLSV11_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ protoflags = CURL_GSKPROTO_TLSV12_MASK;
+ break;
+ }
+
+ /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
+ if(sni) {
+ cc = set_buffer(data, connssl->handle,
+ GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
+ if(cc == CURLE_UNSUPPORTED_PROTOCOL)
+ cc = CURLE_OK;
+ }
+
+ /* Set session parameters. */
+ if(cc == CURLE_OK) {
+ /* Compute the handshake timeout. Since GSKit granularity is 1 second,
+ we round up the required value. */
+ timeout = Curl_timeleft(data, NULL, TRUE);
+ if(timeout < 0)
+ cc = CURLE_OPERATION_TIMEDOUT;
+ else
+ cc = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
+ (timeout + 999) / 1000);
+ }
+ if(cc == CURLE_OK)
+ cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
+ if(cc == CURLE_OK)
+ cc = set_ciphers(data, connssl->handle, &protoflags);
+ if(!protoflags) {
+ failf(data, "No SSL protocol/cipher combination enabled");
+ cc = CURLE_SSL_CIPHER;
+ }
+ if(cc == CURLE_OK)
+ cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
+ (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
+ GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
+ if(cc == CURLE_OK)
+ cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
+ (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
+ GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
+ if(cc == CURLE_OK)
+ cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
+ (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
+ GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
+ if(cc == CURLE_OK) {
+ cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
+ (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
+ GSK_TRUE: GSK_FALSE, TRUE);
+ if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
+ cc = CURLE_OK;
+ if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
+ failf(data, "TLS 1.1 not yet supported");
+ cc = CURLE_SSL_CIPHER;
+ }
+ }
+ }
+ if(cc == CURLE_OK) {
+ cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
+ (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
+ GSK_TRUE: GSK_FALSE, TRUE);
+ if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
+ cc = CURLE_OK;
+ if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
+ failf(data, "TLS 1.2 not yet supported");
+ cc = CURLE_SSL_CIPHER;
+ }
+ }
+ }
+ if(cc == CURLE_OK)
+ cc = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
+ data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
+ GSK_SERVER_AUTH_PASSTHRU, FALSE);
+
+ if(cc == CURLE_OK) {
+ /* Start handshake. Try asynchronous first. */
+ memset(&commarea, 0, sizeof commarea);
+ connssl->iocport = QsoCreateIOCompletionPort();
+ if(connssl->iocport != -1) {
+ cc = gskit_status(data, gsk_secure_soc_startInit(connssl->handle,
+ connssl->iocport, &commarea),
+ "gsk_secure_soc_startInit()", CURLE_SSL_CONNECT_ERROR);
+ if(cc == CURLE_OK) {
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+ }
+ else
+ close_async_handshake(connssl);
+ }
+ else if(errno != ENOBUFS)
+ cc = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0);
+ else {
+ /* No more completion port available. Use synchronous IO. */
+ cc = gskit_status(data, gsk_secure_soc_init(connssl->handle),
+ "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
+ if(cc == CURLE_OK) {
+ connssl->connecting_state = ssl_connect_3;
+ return CURLE_OK;
+ }
+ }
+ }
+
+ /* Error: rollback. */
+ close_one(connssl, data);
+ return cc;
+}
+
+
+static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
+ bool nonblocking)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ Qso_OverlappedIO_t cstat;
+ long timeout_ms;
+ struct timeval stmv;
+ CURLcode cc;
+
+ /* Poll or wait for end of SSL asynchronous handshake. */
+
+ for(;;) {
+ timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
+ if(timeout_ms < 0)
+ timeout_ms = 0;
+ stmv.tv_sec = timeout_ms / 1000;
+ stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
+ switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+ case 1: /* Operation complete. */
+ break;
+ case -1: /* An error occurred: handshake still in progress. */
+ if(errno == EINTR) {
+ if(nonblocking)
+ return CURLE_OK;
+ continue; /* Retry. */
+ }
+ if(errno != ETIME) {
+ failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
+ cancel_async_handshake(conn, sockindex);
+ close_async_handshake(connssl);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* FALL INTO... */
+ case 0: /* Handshake in progress, timeout occurred. */
+ if(nonblocking)
+ return CURLE_OK;
+ cancel_async_handshake(conn, sockindex);
+ close_async_handshake(connssl);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ break;
+ }
+ cc = gskit_status(data, cstat.returnValue, "SSL handshake",
+ CURLE_SSL_CONNECT_ERROR);
+ if(cc == CURLE_OK)
+ connssl->connecting_state = ssl_connect_3;
+ close_async_handshake(connssl);
+ return cc;
+}
+
+
+static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ const gsk_cert_data_elem *cdev;
+ int cdec;
+ const gsk_cert_data_elem *p;
+ const char *cert = (const char *) NULL;
+ const char *certend;
+ int i;
+ CURLcode cc;
+
+ /* SSL handshake done: gather certificate info and verify host. */
+
+ if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
+ GSK_PARTNER_CERT_INFO,
+ &cdev, &cdec),
+ "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
+ CURLE_OK) {
+ infof(data, "Server certificate:\n");
+ p = cdev;
+ for(i = 0; i++ < cdec; p++)
+ switch (p->cert_data_id) {
+ case CERT_BODY_DER:
+ cert = p->cert_data_p;
+ certend = cert + cdev->cert_data_l;
+ break;
+ case CERT_DN_PRINTABLE:
+ infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_ISSUER_DN_PRINTABLE:
+ infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_VALID_FROM:
+ infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_VALID_TO:
+ infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ }
+ }
+
+ /* Verify host. */
+ cc = Curl_verifyhost(conn, cert, certend);
+ if(cc != CURLE_OK)
+ return cc;
+
+ /* The only place GSKit can get the whole CA chain is a validation
+ callback where no user data pointer is available. Therefore it's not
+ possible to copy this chain into our structures for CAINFO.
+ However the server certificate may be available, thus we can return
+ info about it. */
+ if(data->set.ssl.certinfo) {
+ if(Curl_ssl_init_certinfo(data, 1))
+ return CURLE_OUT_OF_MEMORY;
+ if(cert) {
+ cc = Curl_extract_certinfo(conn, 0, cert, certend);
+ if(cc != CURLE_OK)
+ return cc;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+ return CURLE_OK;
+}
+
+
+static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
+ bool nonblocking, bool *done)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ long timeout_ms;
+ Qso_OverlappedIO_t cstat;
+ CURLcode cc = CURLE_OK;
+
+ *done = connssl->state == ssl_connection_complete;
+ if(*done)
+ return CURLE_OK;
+
+ /* Step 1: create session, start handshake. */
+ if(connssl->connecting_state == ssl_connect_1) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ cc = CURLE_OPERATION_TIMEDOUT;
+ }
+ else
+ cc = gskit_connect_step1(conn, sockindex);
+ }
+
+ /* Step 2: check if handshake is over. */
+ if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_2) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ cc = CURLE_OPERATION_TIMEDOUT;
+ }
+ else
+ cc = gskit_connect_step2(conn, sockindex, nonblocking);
+ }
+
+ /* Step 3: gather certificate info, verify host. */
+ if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_3)
+ cc = gskit_connect_step3(conn, sockindex);
+
+ if(cc != CURLE_OK)
+ close_one(connssl, data);
+ else if(connssl->connecting_state == ssl_connect_done) {
+ connssl->state = ssl_connection_complete;
+ connssl->connecting_state = ssl_connect_1;
+ conn->recv[sockindex] = gskit_recv;
+ conn->send[sockindex] = gskit_send;
+ *done = TRUE;
+ }
+
+ return cc;
+}
+
+
+CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ CURLcode cc;
+
+ cc = gskit_connect_common(conn, sockindex, TRUE, done);
+ if(*done || cc != CURLE_OK)
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ return cc;
+}
+
+
+CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode retcode;
+ bool done;
+
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ retcode = gskit_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ return retcode;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+
+void Curl_gskit_close(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->use)
+ close_one(connssl, data);
+}
+
+
+int Curl_gskit_close_all(struct SessionHandle *data)
+{
+ /* Unimplemented. */
+ (void) data;
+ return 0;
+}
+
+
+int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ ssize_t nread;
+ int what;
+ int rc;
+ char buf[120];
+
+ if(!connssl->handle)
+ return 0;
+
+ if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
+ return 0;
+
+ close_one(connssl, data);
+ rc = 0;
+ what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+
+ for(;;) {
+ if(what < 0) {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ rc = -1;
+ break;
+ }
+
+ if(!what) { /* timeout */
+ failf(data, "SSL shutdown timeout");
+ break;
+ }
+
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server. No way to gsk_secure_soc_read() now, so
+ use read(). */
+
+ nread = read(conn->sock[sockindex], buf, sizeof(buf));
+
+ if(nread < 0) {
+ failf(data, "read: %s", strerror(errno));
+ rc = -1;
+ }
+
+ if(nread <= 0)
+ break;
+
+ what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
+ }
+
+ return rc;
+}
+
+
+size_t Curl_gskit_version(char *buffer, size_t size)
+{
+ strncpy(buffer, "GSKit", size);
+ return strlen(buffer);
+}
+
+
+int Curl_gskit_check_cxn(struct connectdata *cxn)
+{
+ int err;
+ int errlen;
+
+ /* The only thing that can be tested here is at the socket level. */
+
+ if(!cxn->ssl[FIRSTSOCKET].handle)
+ return 0; /* connection has been closed */
+
+ err = 0;
+ errlen = sizeof err;
+
+ if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
+ (unsigned char *) &err, &errlen) ||
+ errlen != sizeof err || err)
+ return 0; /* connection has been closed */
+
+ return -1; /* connection status unknown */
+}
+
+#endif /* USE_GSKIT */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/gskit.h b/external/libcurl_android/jni/libcurl/lib/vtls/gskit.h
new file mode 100755
index 00000000..a4caa6f2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/gskit.h
@@ -0,0 +1,65 @@
+#ifndef HEADER_CURL_GSKIT_H
+#define HEADER_CURL_GSKIT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/*
+ * This header should only be needed to get included by vtls.c and gskit.c
+ */
+
+#include "urldata.h"
+
+#ifdef USE_GSKIT
+int Curl_gskit_init(void);
+void Curl_gskit_cleanup(void);
+CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex);
+CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn,
+ int sockindex, bool * done);
+void Curl_gskit_close(struct connectdata *conn, int sockindex);
+int Curl_gskit_close_all(struct SessionHandle * data);
+int Curl_gskit_shutdown(struct connectdata * conn, int sockindex);
+
+size_t Curl_gskit_version(char * buffer, size_t size);
+int Curl_gskit_check_cxn(struct connectdata * cxn);
+
+/* API setup for GSKit */
+#define curlssl_init Curl_gskit_init
+#define curlssl_cleanup Curl_gskit_cleanup
+#define curlssl_connect Curl_gskit_connect
+#define curlssl_connect_nonblocking Curl_gskit_connect_nonblocking
+
+/* No session handling for GSKit */
+#define curlssl_session_free(x) Curl_nop_stmt
+#define curlssl_close_all Curl_gskit_close_all
+#define curlssl_close Curl_gskit_close
+#define curlssl_shutdown(x,y) Curl_gskit_shutdown(x,y)
+#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN
+#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN
+#define curlssl_engines_list(x) NULL
+#define curlssl_version Curl_gskit_version
+#define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
+#define curlssl_data_pending(x,y) 0
+#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
+#endif /* USE_GSKIT */
+
+#endif /* HEADER_CURL_GSKIT_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/gtls.c b/external/libcurl_android/jni/libcurl/lib/vtls/gtls.c
new file mode 100755
index 00000000..d64f95dc
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/gtls.c
@@ -0,0 +1,1323 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ * Note: don't use the GnuTLS' *_t variable type names in this source code,
+ * since they were not present in 1.0.X.
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_GNUTLS
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#ifdef USE_GNUTLS_NETTLE
+#include <gnutls/crypto.h>
+#include <nettle/md5.h>
+#else
+#include <gcrypt.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "gtls.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "rawstr.h"
+#include "warnless.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ Some hackish cast macros based on:
+ http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html
+*/
+#ifndef GNUTLS_POINTER_TO_INT_CAST
+#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
+#endif
+#ifndef GNUTLS_INT_TO_POINTER_CAST
+#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
+#endif
+
+/* Enable GnuTLS debugging by defining GTLSDEBUG */
+/*#define GTLSDEBUG */
+
+#ifdef GTLSDEBUG
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "|<%d>| %s", level, str);
+}
+#endif
+static bool gtls_inited = FALSE;
+
+#if defined(GNUTLS_VERSION_NUMBER)
+# if (GNUTLS_VERSION_NUMBER >= 0x020c00)
+# undef gnutls_transport_set_lowat
+# define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
+# define USE_GNUTLS_PRIORITY_SET_DIRECT 1
+# endif
+# if (GNUTLS_VERSION_NUMBER >= 0x020c03)
+# define GNUTLS_MAPS_WINSOCK_ERRORS 1
+# endif
+
+# ifdef USE_NGHTTP2
+# undef HAS_ALPN
+# if (GNUTLS_VERSION_NUMBER >= 0x030200)
+# define HAS_ALPN
+# endif
+# endif
+#endif
+
+/*
+ * Custom push and pull callback functions used by GNU TLS to read and write
+ * to the socket. These functions are simple wrappers to send() and recv()
+ * (although here using the sread/swrite macros as defined by
+ * curl_setup_once.h).
+ * We use custom functions rather than the GNU TLS defaults because it allows
+ * us to get specific about the fourth "flags" argument, and to use arbitrary
+ * private data with gnutls_transport_set_ptr if we wish.
+ *
+ * When these custom push and pull callbacks fail, GNU TLS checks its own
+ * session-specific error variable, and when not set also its own global
+ * errno variable, in order to take appropriate action. GNU TLS does not
+ * require that the transport is actually a socket. This implies that for
+ * Windows builds these callbacks should ideally set the session-specific
+ * error variable using function gnutls_transport_set_errno or as a last
+ * resort global errno variable using gnutls_transport_set_global_errno,
+ * with a transport agnostic error value. This implies that some winsock
+ * error translation must take place in these callbacks.
+ *
+ * Paragraph above applies to GNU TLS versions older than 2.12.3, since
+ * this version GNU TLS does its own internal winsock error translation
+ * using system_errno() function.
+ */
+
+#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
+# define gtls_EINTR 4
+# define gtls_EIO 5
+# define gtls_EAGAIN 11
+static int gtls_mapped_sockerrno(void)
+{
+ switch(SOCKERRNO) {
+ case WSAEWOULDBLOCK:
+ return gtls_EAGAIN;
+ case WSAEINTR:
+ return gtls_EINTR;
+ default:
+ break;
+ }
+ return gtls_EIO;
+}
+#endif
+
+static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
+{
+ ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
+ if(ret < 0)
+ gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
+#endif
+ return ret;
+}
+
+static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
+{
+ ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
+ if(ret < 0)
+ gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
+#endif
+ return ret;
+}
+
+/* Curl_gtls_init()
+ *
+ * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
+ * are not thread-safe and thus this function itself is not thread-safe and
+ * must only be called from within curl_global_init() to keep the thread
+ * situation under control!
+ */
+int Curl_gtls_init(void)
+{
+ int ret = 1;
+ if(!gtls_inited) {
+ ret = gnutls_global_init()?0:1;
+#ifdef GTLSDEBUG
+ gnutls_global_set_log_function(tls_log_func);
+ gnutls_global_set_log_level(2);
+#endif
+ gtls_inited = TRUE;
+ }
+ return ret;
+}
+
+int Curl_gtls_cleanup(void)
+{
+ if(gtls_inited) {
+ gnutls_global_deinit();
+ gtls_inited = FALSE;
+ }
+ return 1;
+}
+
+static void showtime(struct SessionHandle *data,
+ const char *text,
+ time_t stamp)
+{
+ struct tm buffer;
+ const struct tm *tm = &buffer;
+ CURLcode result = Curl_gmtime(stamp, &buffer);
+ if(result)
+ return;
+
+ snprintf(data->state.buffer,
+ BUFSIZE,
+ "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n",
+ text,
+ Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+ tm->tm_mday,
+ Curl_month[tm->tm_mon],
+ tm->tm_year + 1900,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ infof(data, "%s\n", data->state.buffer);
+}
+
+static gnutls_datum_t load_file (const char *file)
+{
+ FILE *f;
+ gnutls_datum_t loaded_file = { NULL, 0 };
+ long filelen;
+ void *ptr;
+
+ if(!(f = fopen(file, "r")))
+ return loaded_file;
+ if(fseek(f, 0, SEEK_END) != 0
+ || (filelen = ftell(f)) < 0
+ || fseek(f, 0, SEEK_SET) != 0
+ || !(ptr = malloc((size_t)filelen)))
+ goto out;
+ if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
+ free(ptr);
+ goto out;
+ }
+
+ loaded_file.data = ptr;
+ loaded_file.size = (unsigned int)filelen;
+out:
+ fclose(f);
+ return loaded_file;
+}
+
+static void unload_file(gnutls_datum_t data) {
+ free(data.data);
+}
+
+
+/* this function does a SSL/TLS (re-)handshake */
+static CURLcode handshake(struct connectdata *conn,
+ int sockindex,
+ bool duringconnect,
+ bool nonblocking)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ gnutls_session_t session = conn->ssl[sockindex].session;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int rc;
+ int what;
+
+ for(;;) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, duringconnect);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd,
+ nonblocking?0:
+ timeout_ms?timeout_ms:1000);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking)
+ return CURLE_OK;
+ else if(timeout_ms) {
+ /* timeout */
+ failf(data, "SSL connection timeout at %ld", timeout_ms);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ rc = gnutls_handshake(session);
+
+ if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
+ connssl->connecting_state =
+ gnutls_record_get_direction(session)?
+ ssl_connect_2_writing:ssl_connect_2_reading;
+ continue;
+ if(nonblocking)
+ return CURLE_OK;
+ }
+ else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
+ const char *strerr = NULL;
+
+ if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
+ int alert = gnutls_alert_get(session);
+ strerr = gnutls_alert_get_name(alert);
+ }
+
+ if(strerr == NULL)
+ strerr = gnutls_strerror(rc);
+
+ failf(data, "gnutls_handshake() warning: %s", strerr);
+ }
+ else if(rc < 0) {
+ const char *strerr = NULL;
+
+ if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
+ int alert = gnutls_alert_get(session);
+ strerr = gnutls_alert_get_name(alert);
+ }
+
+ if(strerr == NULL)
+ strerr = gnutls_strerror(rc);
+
+ failf(data, "gnutls_handshake() failed: %s", strerr);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+ return CURLE_OK;
+ }
+}
+
+static gnutls_x509_crt_fmt_t do_file_type(const char *type)
+{
+ if(!type || !type[0])
+ return GNUTLS_X509_FMT_PEM;
+ if(Curl_raw_equal(type, "PEM"))
+ return GNUTLS_X509_FMT_PEM;
+ if(Curl_raw_equal(type, "DER"))
+ return GNUTLS_X509_FMT_DER;
+ return -1;
+}
+
+static CURLcode
+gtls_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ gnutls_session_t session;
+ int rc;
+ void *ssl_sessionid;
+ size_t ssl_idsize;
+ bool sni = TRUE; /* default is SNI enabled */
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
+ static const int cipher_priority[] = {
+ /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
+ but this code path is only ever used for ver. < 2.12.0.
+ GNUTLS_CIPHER_AES_128_GCM,
+ GNUTLS_CIPHER_AES_256_GCM,
+ */
+ GNUTLS_CIPHER_AES_128_CBC,
+ GNUTLS_CIPHER_AES_256_CBC,
+ GNUTLS_CIPHER_CAMELLIA_128_CBC,
+ GNUTLS_CIPHER_CAMELLIA_256_CBC,
+ GNUTLS_CIPHER_3DES_CBC,
+ };
+ static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
+ static int protocol_priority[] = { 0, 0, 0, 0 };
+#else
+#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
+/* If GnuTLS was compiled without support for SRP it will error out if SRP is
+ requested in the priority string, so treat it specially
+ */
+#define GNUTLS_SRP "+SRP"
+ const char* prioritylist;
+ const char *err = NULL;
+#endif
+#ifdef HAS_ALPN
+ int protocols_size = 2;
+ gnutls_datum_t protocols[2];
+#endif
+
+ if(conn->ssl[sockindex].state == ssl_connection_complete)
+ /* to make us tolerant against being called more than once for the
+ same connection */
+ return CURLE_OK;
+
+ if(!gtls_inited)
+ Curl_gtls_init();
+
+ /* GnuTLS only supports SSLv3 and TLSv1 */
+ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ failf(data, "GnuTLS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
+ sni = FALSE; /* SSLv3 has no SNI */
+
+ /* allocate a cred struct */
+ rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+
+ rc = gnutls_srp_allocate_client_credentials(
+ &conn->ssl[sockindex].srp_client_cred);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
+ gnutls_strerror(rc));
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
+ srp_client_cred,
+ data->set.ssl.username,
+ data->set.ssl.password);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_srp_set_client_cred() failed: %s",
+ gnutls_strerror(rc));
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ }
+#endif
+
+ if(data->set.ssl.CAfile) {
+ /* set the trusted CA cert bundle file */
+ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
+ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+
+ rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
+ data->set.ssl.CAfile,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)\n",
+ data->set.ssl.CAfile, gnutls_strerror(rc));
+ if(data->set.ssl.verifypeer)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else
+ infof(data, "found %d certificates in %s\n",
+ rc, data->set.ssl.CAfile);
+ }
+
+ if(data->set.ssl.CRLfile) {
+ /* set the CRL list file */
+ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
+ data->set.ssl.CRLfile,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ failf(data, "error reading crl file %s (%s)",
+ data->set.ssl.CRLfile, gnutls_strerror(rc));
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ else
+ infof(data, "found %d CRL in %s\n",
+ rc, data->set.ssl.CRLfile);
+ }
+
+ /* Initialize TLS session as a client */
+ rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "gnutls_init() failed: %d", rc);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* convenient assign */
+ session = conn->ssl[sockindex].session;
+
+ if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+#ifdef ENABLE_IPV6
+ (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+#endif
+ sni &&
+ (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
+ strlen(conn->host.name)) < 0))
+ infof(data, "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+
+ /* Use default priorities */
+ rc = gnutls_set_default_priority(session);
+ if(rc != GNUTLS_E_SUCCESS)
+ return CURLE_SSL_CONNECT_ERROR;
+
+#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
+ rc = gnutls_cipher_set_priority(session, cipher_priority);
+ if(rc != GNUTLS_E_SUCCESS)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* Sets the priority on the certificate types supported by gnutls. Priority
+ is higher for types specified before others. After specifying the types
+ you want, you must append a 0. */
+ rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
+ if(rc != GNUTLS_E_SUCCESS)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ if(data->set.ssl.cipher_list != NULL) {
+ failf(data, "can't pass a custom cipher list to older GnuTLS"
+ " versions");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ switch (data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv3:
+ protocol_priority[0] = GNUTLS_SSL3;
+ break;
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ protocol_priority[0] = GNUTLS_TLS1_0;
+ protocol_priority[1] = GNUTLS_TLS1_1;
+ protocol_priority[2] = GNUTLS_TLS1_2;
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ protocol_priority[0] = GNUTLS_TLS1_0;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ protocol_priority[0] = GNUTLS_TLS1_1;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ protocol_priority[0] = GNUTLS_TLS1_2;
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ default:
+ failf(data, "GnuTLS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ break;
+ }
+ rc = gnutls_protocol_set_priority(session, protocol_priority);
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "Did you pass a valid GnuTLS cipher list?");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+#else
+ /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
+ * removed if a run-time error indicates that SRP is not supported by this
+ * GnuTLS version */
+ switch (data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv3:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
+ sni = false;
+ break;
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:" GNUTLS_SRP;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.1:" GNUTLS_SRP;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.2:" GNUTLS_SRP;
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ default:
+ failf(data, "GnuTLS does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ break;
+ }
+ rc = gnutls_priority_set_direct(session, prioritylist, &err);
+ if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
+ if(!strcmp(err, GNUTLS_SRP)) {
+ /* This GnuTLS was probably compiled without support for SRP.
+ * Note that fact and try again without it. */
+ int validprioritylen = curlx_uztosi(err - prioritylist);
+ char *prioritycopy = strdup(prioritylist);
+ if(!prioritycopy)
+ return CURLE_OUT_OF_MEMORY;
+
+ infof(data, "This GnuTLS does not support SRP\n");
+ if(validprioritylen)
+ /* Remove the :+SRP */
+ prioritycopy[validprioritylen - 1] = 0;
+ rc = gnutls_priority_set_direct(session, prioritycopy, &err);
+ free(prioritycopy);
+ }
+ }
+ if(rc != GNUTLS_E_SUCCESS) {
+ failf(data, "Error %d setting GnuTLS cipher list starting with %s",
+ rc, err);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif
+
+#ifdef HAS_ALPN
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+ if(data->set.ssl_enable_alpn) {
+ protocols[0].data = NGHTTP2_PROTO_VERSION_ID;
+ protocols[0].size = NGHTTP2_PROTO_VERSION_ID_LEN;
+ protocols[1].data = ALPN_HTTP_1_1;
+ protocols[1].size = ALPN_HTTP_1_1_LENGTH;
+ gnutls_alpn_set_protocols(session, protocols, protocols_size, 0);
+ infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
+ ALPN_HTTP_1_1);
+ }
+ else {
+ infof(data, "SSL, can't negotiate HTTP/2.0 without ALPN\n");
+ }
+ }
+#endif
+
+ if(data->set.str[STRING_CERT]) {
+ if(gnutls_certificate_set_x509_key_file(
+ conn->ssl[sockindex].cred,
+ data->set.str[STRING_CERT],
+ data->set.str[STRING_KEY] ?
+ data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
+ do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
+ GNUTLS_E_SUCCESS) {
+ failf(data, "error reading X.509 key or certificate file");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+#ifdef USE_TLS_SRP
+ /* put the credentials to the current session */
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
+ conn->ssl[sockindex].srp_client_cred);
+ if(rc != GNUTLS_E_SUCCESS)
+ failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
+ }
+ else
+#endif
+ rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
+ conn->ssl[sockindex].cred);
+
+ /* set the connection handle (file descriptor for the socket) */
+ gnutls_transport_set_ptr(session,
+ GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
+
+ /* register callback functions to send and receive data. */
+ gnutls_transport_set_push_function(session, Curl_gtls_push);
+ gnutls_transport_set_pull_function(session, Curl_gtls_pull);
+
+ /* lowat must be set to zero when using custom push and pull functions. */
+ gnutls_transport_set_lowat(session, 0);
+
+ /* This might be a reconnect, so we check for a session ID in the cache
+ to speed up things */
+
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
+ /* we got a session id, use it! */
+ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
+
+ /* Informational message */
+ infof (data, "SSL re-using session ID\n");
+ }
+
+ return CURLE_OK;
+}
+
+static Curl_recv gtls_recv;
+static Curl_send gtls_send;
+
+static CURLcode
+gtls_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ unsigned int cert_list_size;
+ const gnutls_datum_t *chainp;
+ unsigned int verify_status;
+ gnutls_x509_crt_t x509_cert,x509_issuer;
+ gnutls_datum_t issuerp;
+ char certbuf[256] = ""; /* big enough? */
+ size_t size;
+ unsigned int algo;
+ unsigned int bits;
+ time_t certclock;
+ const char *ptr;
+ struct SessionHandle *data = conn->data;
+ gnutls_session_t session = conn->ssl[sockindex].session;
+ int rc;
+ int incache;
+ void *ssl_sessionid;
+#ifdef HAS_ALPN
+ gnutls_datum_t proto;
+#endif
+ CURLcode result = CURLE_OK;
+
+ /* This function will return the peer's raw certificate (chain) as sent by
+ the peer. These certificates are in raw format (DER encoded for
+ X.509). In case of a X.509 then a certificate list may be present. The
+ first certificate in the list is the peer's certificate, following the
+ issuer's certificate, then the issuer's issuer etc. */
+
+ chainp = gnutls_certificate_get_peers(session, &cert_list_size);
+ if(!chainp) {
+ if(data->set.ssl.verifypeer ||
+ data->set.ssl.verifyhost ||
+ data->set.ssl.issuercert) {
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
+ && data->set.ssl.username != NULL
+ && !data->set.ssl.verifypeer
+ && gnutls_cipher_get(session)) {
+ /* no peer cert, but auth is ok if we have SRP user and cipher and no
+ peer verify */
+ }
+ else {
+#endif
+ failf(data, "failed to get server cert");
+ return CURLE_PEER_FAILED_VERIFICATION;
+#ifdef USE_TLS_SRP
+ }
+#endif
+ }
+ infof(data, "\t common name: WARNING couldn't obtain\n");
+ }
+
+ if(data->set.ssl.verifypeer) {
+ /* This function will try to verify the peer's certificate and return its
+ status (trusted, invalid etc.). The value of status should be one or
+ more of the gnutls_certificate_status_t enumerated elements bitwise
+ or'd. To avoid denial of service attacks some default upper limits
+ regarding the certificate key size and chain size are set. To override
+ them use gnutls_certificate_set_verify_limits(). */
+
+ rc = gnutls_certificate_verify_peers2(session, &verify_status);
+ if(rc < 0) {
+ failf(data, "server cert verify failed: %d", rc);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* verify_status is a bitmask of gnutls_certificate_status bits */
+ if(verify_status & GNUTLS_CERT_INVALID) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server certificate verification failed. CAfile: %s "
+ "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
+ data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
+ return CURLE_SSL_CACERT;
+ }
+ else
+ infof(data, "\t server certificate verification FAILED\n");
+ }
+ else
+ infof(data, "\t server certificate verification OK\n");
+ }
+ else
+ infof(data, "\t server certificate verification SKIPPED\n");
+
+ /* initialize an X.509 certificate structure. */
+ gnutls_x509_crt_init(&x509_cert);
+
+ if(chainp)
+ /* convert the given DER or PEM encoded Certificate to the native
+ gnutls_x509_crt_t format */
+ gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
+
+ if(data->set.ssl.issuercert) {
+ gnutls_x509_crt_init(&x509_issuer);
+ issuerp = load_file(data->set.ssl.issuercert);
+ gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
+ rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer);
+ unload_file(issuerp);
+ if(rc <= 0) {
+ failf(data, "server certificate issuer check failed (IssuerCert: %s)",
+ data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+ infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
+ data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+ }
+
+ size=sizeof(certbuf);
+ rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
+ 0, /* the first and only one */
+ FALSE,
+ certbuf,
+ &size);
+ if(rc) {
+ infof(data, "error fetching CN from cert:%s\n",
+ gnutls_strerror(rc));
+ }
+
+ /* This function will check if the given certificate's subject matches the
+ given hostname. This is a basic implementation of the matching described
+ in RFC2818 (HTTPS), which takes into account wildcards, and the subject
+ alternative name PKIX extension. Returns non zero on success, and zero on
+ failure. */
+ rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
+#if GNUTLS_VERSION_NUMBER < 0x030306
+ /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
+ addresses. */
+ if(!rc) {
+#ifdef ENABLE_IPV6
+ #define use_addr in6_addr
+#else
+ #define use_addr in_addr
+#endif
+ unsigned char addrbuf[sizeof(struct use_addr)];
+ unsigned char certaddr[sizeof(struct use_addr)];
+ size_t addrlen = 0, certaddrlen;
+ int i;
+ int ret = 0;
+
+ if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
+ addrlen = 4;
+#ifdef ENABLE_IPV6
+ else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
+ addrlen = 16;
+#endif
+
+ if(addrlen) {
+ for(i=0; ; i++) {
+ certaddrlen = sizeof(certaddr);
+ ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
+ &certaddrlen, NULL);
+ /* If this happens, it wasn't an IP address. */
+ if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ continue;
+ if(ret < 0)
+ break;
+ if(ret != GNUTLS_SAN_IPADDRESS)
+ continue;
+ if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
+ rc = 1;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ if(!rc) {
+ if(data->set.ssl.verifyhost) {
+ failf(data, "SSL: certificate subject name (%s) does not match "
+ "target host name '%s'", certbuf, conn->host.dispname);
+ gnutls_x509_crt_deinit(x509_cert);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\t common name: %s (does not match '%s')\n",
+ certbuf, conn->host.dispname);
+ }
+ else
+ infof(data, "\t common name: %s (matched)\n", certbuf);
+
+ /* Check for time-based validity */
+ certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
+
+ if(certclock == (time_t)-1) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server cert expiration date verify failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else
+ infof(data, "\t server certificate expiration date verify FAILED\n");
+ }
+ else {
+ if(certclock < time(NULL)) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server certificate expiration date has passed.");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\t server certificate expiration date FAILED\n");
+ }
+ else
+ infof(data, "\t server certificate expiration date OK\n");
+ }
+
+ certclock = gnutls_x509_crt_get_activation_time(x509_cert);
+
+ if(certclock == (time_t)-1) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server cert activation date verify failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else
+ infof(data, "\t server certificate activation date verify FAILED\n");
+ }
+ else {
+ if(certclock > time(NULL)) {
+ if(data->set.ssl.verifypeer) {
+ failf(data, "server certificate not activated yet.");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\t server certificate activation date FAILED\n");
+ }
+ else
+ infof(data, "\t server certificate activation date OK\n");
+ }
+
+ /* Show:
+
+ - ciphers used
+ - subject
+ - start date
+ - expire date
+ - common name
+ - issuer
+
+ */
+
+ /* public key algorithm's parameters */
+ algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
+ infof(data, "\t certificate public key: %s\n",
+ gnutls_pk_algorithm_get_name(algo));
+
+ /* version of the X.509 certificate. */
+ infof(data, "\t certificate version: #%d\n",
+ gnutls_x509_crt_get_version(x509_cert));
+
+
+ size = sizeof(certbuf);
+ gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
+ infof(data, "\t subject: %s\n", certbuf);
+
+ certclock = gnutls_x509_crt_get_activation_time(x509_cert);
+ showtime(data, "start date", certclock);
+
+ certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
+ showtime(data, "expire date", certclock);
+
+ size = sizeof(certbuf);
+ gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
+ infof(data, "\t issuer: %s\n", certbuf);
+
+ gnutls_x509_crt_deinit(x509_cert);
+
+ /* compression algorithm (if any) */
+ ptr = gnutls_compression_get_name(gnutls_compression_get(session));
+ /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
+ infof(data, "\t compression: %s\n", ptr);
+
+ /* the name of the cipher used. ie 3DES. */
+ ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
+ infof(data, "\t cipher: %s\n", ptr);
+
+ /* the MAC algorithms name. ie SHA1 */
+ ptr = gnutls_mac_get_name(gnutls_mac_get(session));
+ infof(data, "\t MAC: %s\n", ptr);
+
+#ifdef HAS_ALPN
+ if(data->set.ssl_enable_alpn) {
+ rc = gnutls_alpn_get_selected_protocol(session, &proto);
+ if(rc == 0) {
+ infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
+ proto.data);
+
+ if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
+ memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
+ NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
+ conn->negnpn = NPN_HTTP2;
+ }
+ else if(proto.size == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
+ proto.data, ALPN_HTTP_1_1_LENGTH) == 0) {
+ conn->negnpn = NPN_HTTP1_1;
+ }
+ }
+ else {
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ }
+ }
+#endif
+
+ conn->ssl[sockindex].state = ssl_connection_complete;
+ conn->recv[sockindex] = gtls_recv;
+ conn->send[sockindex] = gtls_send;
+
+ {
+ /* we always unconditionally get the session id here, as even if we
+ already got it from the cache and asked to use it in the connection, it
+ might've been rejected and then a new one is in use now and we need to
+ detect that. */
+ void *connect_sessionid;
+ size_t connect_idsize = 0;
+
+ /* get the session ID data size */
+ gnutls_session_get_data(session, NULL, &connect_idsize);
+ connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
+
+ if(connect_sessionid) {
+ /* extract session ID to the allocated buffer */
+ gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
+
+ incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
+ if(incache) {
+ /* there was one before in the cache, so instead of risking that the
+ previous one was rejected, we just kill that and store the new */
+ Curl_ssl_delsessionid(conn, ssl_sessionid);
+ }
+
+ /* store this session id */
+ result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
+ if(result) {
+ free(connect_sessionid);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ return result;
+}
+
+
+/*
+ * This function is called after the TCP connect has completed. Setup the TLS
+ * layer and do all necessary magic.
+ */
+/* We use connssl->connecting_state to keep track of the connection status;
+ there are three states: 'ssl_connect_1' (not started yet or complete),
+ 'ssl_connect_2_reading' (waiting for data from server), and
+ 'ssl_connect_2_writing' (waiting to be able to write).
+ */
+static CURLcode
+gtls_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ int rc;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ /* Initiate the connection, if not already done */
+ if(ssl_connect_1==connssl->connecting_state) {
+ rc = gtls_connect_step1 (conn, sockindex);
+ if(rc)
+ return rc;
+ }
+
+ rc = handshake(conn, sockindex, TRUE, nonblocking);
+ if(rc)
+ /* handshake() sets its own error message with failf() */
+ return rc;
+
+ /* Finish connecting once the handshake is done */
+ if(ssl_connect_1==connssl->connecting_state) {
+ rc = gtls_connect_step3(conn, sockindex);
+ if(rc)
+ return rc;
+ }
+
+ *done = ssl_connect_1==connssl->connecting_state;
+
+ return CURLE_OK;
+}
+
+CURLcode
+Curl_gtls_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return gtls_connect_common(conn, sockindex, TRUE, done);
+}
+
+CURLcode
+Curl_gtls_connect(struct connectdata *conn,
+ int sockindex)
+
+{
+ CURLcode retcode;
+ bool done = FALSE;
+
+ retcode = gtls_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ return retcode;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+static ssize_t gtls_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
+
+ if(rc < 0 ) {
+ *curlcode = (rc == GNUTLS_E_AGAIN)
+ ? CURLE_AGAIN
+ : CURLE_SEND_ERROR;
+
+ rc = -1;
+ }
+
+ return rc;
+}
+
+void Curl_gtls_close_all(struct SessionHandle *data)
+{
+ /* FIX: make the OpenSSL code more generic and use parts of it here */
+ (void)data;
+}
+
+static void close_one(struct connectdata *conn,
+ int idx)
+{
+ if(conn->ssl[idx].session) {
+ gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
+ gnutls_deinit(conn->ssl[idx].session);
+ conn->ssl[idx].session = NULL;
+ }
+ if(conn->ssl[idx].cred) {
+ gnutls_certificate_free_credentials(conn->ssl[idx].cred);
+ conn->ssl[idx].cred = NULL;
+ }
+#ifdef USE_TLS_SRP
+ if(conn->ssl[idx].srp_client_cred) {
+ gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
+ conn->ssl[idx].srp_client_cred = NULL;
+ }
+#endif
+}
+
+void Curl_gtls_close(struct connectdata *conn, int sockindex)
+{
+ close_one(conn, sockindex);
+}
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
+{
+ ssize_t result;
+ int retval = 0;
+ struct SessionHandle *data = conn->data;
+ int done = 0;
+ char buf[120];
+
+ /* This has only been tested on the proftpd server, and the mod_tls code
+ sends a close notify alert without waiting for a close notify alert in
+ response. Thus we wait for a close notify alert from the server, but
+ we do not send one. Let's hope other servers do the same... */
+
+ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
+ gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
+
+ if(conn->ssl[sockindex].session) {
+ while(!done) {
+ int what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ if(what > 0) {
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server */
+ result = gnutls_record_recv(conn->ssl[sockindex].session,
+ buf, sizeof(buf));
+ switch(result) {
+ case 0:
+ /* This is the expected response. There was no data but only
+ the close notify alert */
+ done = 1;
+ break;
+ case GNUTLS_E_AGAIN:
+ case GNUTLS_E_INTERRUPTED:
+ infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
+ break;
+ default:
+ retval = -1;
+ done = 1;
+ break;
+ }
+ }
+ else if(0 == what) {
+ /* timeout */
+ failf(data, "SSL shutdown timeout");
+ done = 1;
+ break;
+ }
+ else {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ retval = -1;
+ done = 1;
+ }
+ }
+ gnutls_deinit(conn->ssl[sockindex].session);
+ }
+ gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
+
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
+ && data->set.ssl.username != NULL)
+ gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
+#endif
+
+ conn->ssl[sockindex].cred = NULL;
+ conn->ssl[sockindex].session = NULL;
+
+ return retval;
+}
+
+static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ CURLcode *curlcode)
+{
+ ssize_t ret;
+
+ ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
+ if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ }
+
+ if(ret == GNUTLS_E_REHANDSHAKE) {
+ /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
+ proper way" takes a whole lot of work. */
+ CURLcode rc = handshake(conn, num, FALSE, FALSE);
+ if(rc)
+ /* handshake() writes error message on its own */
+ *curlcode = rc;
+ else
+ *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
+ return -1;
+ }
+
+ if(ret < 0) {
+ failf(conn->data, "GnuTLS recv error (%d): %s",
+ (int)ret, gnutls_strerror((int)ret));
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ return ret;
+}
+
+void Curl_gtls_session_free(void *ptr)
+{
+ free(ptr);
+}
+
+size_t Curl_gtls_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
+}
+
+#ifndef USE_GNUTLS_NETTLE
+static int Curl_gtls_seed(struct SessionHandle *data)
+{
+ /* we have the "SSL is seeded" boolean static to prevent multiple
+ time-consuming seedings in vain */
+ static bool ssl_seeded = FALSE;
+
+ /* Quickly add a bit of entropy */
+ gcry_fast_random_poll();
+
+ if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
+ data->set.str[STRING_SSL_EGDSOCKET]) {
+
+ /* TODO: to a good job seeding the RNG
+ This may involve the gcry_control function and these options:
+ GCRYCTL_SET_RANDOM_SEED_FILE
+ GCRYCTL_SET_RNDEGD_SOCKET
+ */
+ ssl_seeded = TRUE;
+ }
+ return 0;
+}
+#endif
+
+/* data might be NULL! */
+int Curl_gtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+#if defined(USE_GNUTLS_NETTLE)
+ (void)data;
+ gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
+#elif defined(USE_GNUTLS)
+ if(data)
+ Curl_gtls_seed(data); /* Initiate the seed if not already done */
+ gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
+#endif
+ return 0;
+}
+
+void Curl_gtls_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
+{
+#if defined(USE_GNUTLS_NETTLE)
+ struct md5_ctx MD5pw;
+ md5_init(&MD5pw);
+ md5_update(&MD5pw, (unsigned int)tmplen, tmp);
+ md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
+#elif defined(USE_GNUTLS)
+ gcry_md_hd_t MD5pw;
+ gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
+ gcry_md_write(MD5pw, tmp, tmplen);
+ memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
+ gcry_md_close(MD5pw);
+#endif
+}
+
+#endif /* USE_GNUTLS */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/gtls.h b/external/libcurl_android/jni/libcurl/lib/vtls/gtls.h
new file mode 100755
index 00000000..cd6152ca
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/gtls.h
@@ -0,0 +1,79 @@
+#ifndef HEADER_CURL_GTLS_H
+#define HEADER_CURL_GTLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_GNUTLS
+
+#include "urldata.h"
+
+int Curl_gtls_init(void);
+int Curl_gtls_cleanup(void);
+CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
+CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+/* tell GnuTLS to close down all open information regarding connections (and
+ thus session ID caching etc) */
+void Curl_gtls_close_all(struct SessionHandle *data);
+
+ /* close a SSL connection */
+void Curl_gtls_close(struct connectdata *conn, int sockindex);
+
+void Curl_gtls_session_free(void *ptr);
+size_t Curl_gtls_version(char *buffer, size_t size);
+int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
+int Curl_gtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length);
+void Curl_gtls_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len);
+
+/* this backend provides these functions: */
+#define have_curlssl_md5sum 1
+
+/* API setup for GnuTLS */
+#define curlssl_init Curl_gtls_init
+#define curlssl_cleanup Curl_gtls_cleanup
+#define curlssl_connect Curl_gtls_connect
+#define curlssl_connect_nonblocking Curl_gtls_connect_nonblocking
+#define curlssl_session_free(x) Curl_gtls_session_free(x)
+#define curlssl_close_all Curl_gtls_close_all
+#define curlssl_close Curl_gtls_close
+#define curlssl_shutdown(x,y) Curl_gtls_shutdown(x,y)
+#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_gtls_version
+#define curlssl_check_cxn(x) (x=x, -1)
+#define curlssl_data_pending(x,y) (x=x, y=y, 0)
+#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
+#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
+#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
+
+#endif /* USE_GNUTLS */
+#endif /* HEADER_CURL_GTLS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/nss.c b/external/libcurl_android/jni/libcurl/lib/vtls/nss.c
new file mode 100755
index 00000000..83b3e323
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/nss.c
@@ -0,0 +1,1943 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all NSS-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_NSS
+
+#include "urldata.h"
+#include "sendf.h"
+#include "formdata.h" /* for the boundary function */
+#include "url.h" /* for the ssl config check function */
+#include "connect.h"
+#include "strequal.h"
+#include "select.h"
+#include "vtls.h"
+#include "llist.h"
+
+#define _MPRINTF_REPLACE /* use the internal *printf() functions */
+#include <curl/mprintf.h>
+
+#include "nssg.h"
+#include <nspr.h>
+#include <nss.h>
+#include <ssl.h>
+#include <sslerr.h>
+#include <secerr.h>
+#include <secmod.h>
+#include <sslproto.h>
+#include <prtypes.h>
+#include <pk11pub.h>
+#include <prio.h>
+#include <secitem.h>
+#include <secport.h>
+#include <certdb.h>
+#include <base64.h>
+#include <cert.h>
+#include <prerror.h>
+
+#include "curl_memory.h"
+#include "rawstr.h"
+#include "warnless.h"
+#include "x509asn1.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#define SSL_DIR "/etc/pki/nssdb"
+
+/* enough to fit the string "PEM Token #[0|1]" */
+#define SLOTSIZE 13
+
+PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
+
+PRLock * nss_initlock = NULL;
+PRLock * nss_crllock = NULL;
+struct curl_llist *nss_crl_list = NULL;
+NSSInitContext * nss_context = NULL;
+
+volatile int initialized = 0;
+
+typedef struct {
+ const char *name;
+ int num;
+} cipher_s;
+
+#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \
+ CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \
+ ptr->type = (_type); \
+ ptr->pValue = (_val); \
+ ptr->ulValueLen = (_len); \
+} WHILE_FALSE
+
+#define CERT_NewTempCertificate __CERT_NewTempCertificate
+
+#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
+static const cipher_s cipherlist[] = {
+ /* SSL2 cipher suites */
+ {"rc4", SSL_EN_RC4_128_WITH_MD5},
+ {"rc4-md5", SSL_EN_RC4_128_WITH_MD5},
+ {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5},
+ {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5},
+ {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
+ {"des", SSL_EN_DES_64_CBC_WITH_MD5},
+ {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
+ /* SSL3/TLS cipher suites */
+ {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5},
+ {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA},
+ {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA},
+ {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
+ {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
+ {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
+ {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
+ {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
+ {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA},
+ {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
+ {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
+ {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA},
+ /* TLS 1.0: Exportable 56-bit Cipher Suites. */
+ {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
+ {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
+ /* AES ciphers. */
+ {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
+ {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
+ {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
+ {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
+ {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA},
+ {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA},
+ /* ECC ciphers. */
+ {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA},
+ {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
+ {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA},
+ {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA},
+ {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA},
+ {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA},
+ {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
+ {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA},
+ {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
+ {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
+ {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA},
+ {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA},
+ {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
+ {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
+ {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
+ {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
+ {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
+ {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA},
+ {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA},
+ {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
+ {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
+ {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
+#ifdef TLS_RSA_WITH_NULL_SHA256
+ /* new HMAC-SHA256 cipher suites specified in RFC */
+ {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256},
+ {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256},
+ {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256},
+ {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
+ {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
+ {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
+ {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
+#endif
+#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256
+ /* AES GCM cipher suites in RFC 5288 and RFC 5289 */
+ {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256},
+ {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+ {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},
+ {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+ {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256},
+ {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
+#endif
+};
+
+static const char* pem_library = "libnsspem.so";
+SECMODModule* mod = NULL;
+
+/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
+static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
+static PRIOMethods nspr_io_methods;
+
+static const char* nss_error_to_name(PRErrorCode code)
+{
+ const char *name = PR_ErrorToName(code);
+ if(name)
+ return name;
+
+ return "unknown error";
+}
+
+static void nss_print_error_message(struct SessionHandle *data, PRUint32 err)
+{
+ failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
+}
+
+static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
+ char *cipher_list)
+{
+ unsigned int i;
+ PRBool cipher_state[NUM_OF_CIPHERS];
+ PRBool found;
+ char *cipher;
+
+ /* First disable all ciphers. This uses a different max value in case
+ * NSS adds more ciphers later we don't want them available by
+ * accident
+ */
+ for(i=0; i<SSL_NumImplementedCiphers; i++) {
+ SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], PR_FALSE);
+ }
+
+ /* Set every entry in our list to false */
+ for(i=0; i<NUM_OF_CIPHERS; i++) {
+ cipher_state[i] = PR_FALSE;
+ }
+
+ cipher = cipher_list;
+
+ while(cipher_list && (cipher_list[0])) {
+ while((*cipher) && (ISSPACE(*cipher)))
+ ++cipher;
+
+ if((cipher_list = strchr(cipher, ','))) {
+ *cipher_list++ = '\0';
+ }
+
+ found = PR_FALSE;
+
+ for(i=0; i<NUM_OF_CIPHERS; i++) {
+ if(Curl_raw_equal(cipher, cipherlist[i].name)) {
+ cipher_state[i] = PR_TRUE;
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if(found == PR_FALSE) {
+ failf(data, "Unknown cipher in list: %s", cipher);
+ return SECFailure;
+ }
+
+ if(cipher_list) {
+ cipher = cipher_list;
+ }
+ }
+
+ /* Finally actually enable the selected ciphers */
+ for(i=0; i<NUM_OF_CIPHERS; i++) {
+ if(!cipher_state[i])
+ continue;
+
+ if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) != SECSuccess) {
+ failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name);
+ return SECFailure;
+ }
+ }
+
+ return SECSuccess;
+}
+
+/*
+ * Get the number of ciphers that are enabled. We use this to determine
+ * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
+ */
+static int num_enabled_ciphers(void)
+{
+ PRInt32 policy = 0;
+ int count = 0;
+ unsigned int i;
+
+ for(i=0; i<NUM_OF_CIPHERS; i++) {
+ SSL_CipherPolicyGet(cipherlist[i].num, &policy);
+ if(policy)
+ count++;
+ }
+ return count;
+}
+
+/*
+ * Determine whether the nickname passed in is a filename that needs to
+ * be loaded as a PEM or a regular NSS nickname.
+ *
+ * returns 1 for a file
+ * returns 0 for not a file (NSS nickname)
+ */
+static int is_file(const char *filename)
+{
+ struct_stat st;
+
+ if(filename == NULL)
+ return 0;
+
+ if(stat(filename, &st) == 0)
+ if(S_ISREG(st.st_mode))
+ return 1;
+
+ return 0;
+}
+
+/* Check if the given string is filename or nickname of a certificate. If the
+ * given string is recognized as filename, return NULL. If the given string is
+ * recognized as nickname, return a duplicated string. The returned string
+ * should be later deallocated using free(). If the OOM failure occurs, we
+ * return NULL, too.
+ */
+static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind)
+{
+ const char *str = data->set.str[cert_kind];
+ const char *n;
+
+ if(!is_file(str))
+ /* no such file exists, use the string as nickname */
+ return strdup(str);
+
+ /* search the last slash; we require at least one slash in a file name */
+ n = strrchr(str, '/');
+ if(!n) {
+ infof(data, "warning: certificate file name \"%s\" handled as nickname; "
+ "please use \"./%s\" to force file name\n", str, str);
+ return strdup(str);
+ }
+
+ /* we'll use the PEM reader to read the certificate from file */
+ return NULL;
+}
+
+/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
+ * the call succeeds, append the object handle to the list of objects so that
+ * the object can be destroyed in Curl_nss_close(). */
+static CURLcode nss_create_object(struct ssl_connect_data *ssl,
+ CK_OBJECT_CLASS obj_class,
+ const char *filename, bool cacert)
+{
+ PK11SlotInfo *slot;
+ PK11GenericObject *obj;
+ CK_BBOOL cktrue = CK_TRUE;
+ CK_BBOOL ckfalse = CK_FALSE;
+ CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
+ int attr_cnt = 0;
+ CURLcode err = (cacert)
+ ? CURLE_SSL_CACERT_BADFILE
+ : CURLE_SSL_CERTPROBLEM;
+
+ const int slot_id = (cacert) ? 0 : 1;
+ char *slot_name = aprintf("PEM Token #%d", slot_id);
+ if(!slot_name)
+ return CURLE_OUT_OF_MEMORY;
+
+ slot = PK11_FindSlotByName(slot_name);
+ free(slot_name);
+ if(!slot)
+ return err;
+
+ PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
+ PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
+ PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
+ strlen(filename) + 1);
+
+ if(CKO_CERTIFICATE == obj_class) {
+ CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
+ PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
+ }
+
+ obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
+ PK11_FreeSlot(slot);
+ if(!obj)
+ return err;
+
+ if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
+ PK11_DestroyGenericObject(obj);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!cacert && CKO_CERTIFICATE == obj_class)
+ /* store reference to a client certificate */
+ ssl->obj_clicert = obj;
+
+ return CURLE_OK;
+}
+
+/* Destroy the NSS object whose handle is given by ptr. This function is
+ * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
+ * NSS objects in Curl_nss_close() */
+static void nss_destroy_object(void *user, void *ptr)
+{
+ PK11GenericObject *obj = (PK11GenericObject *)ptr;
+ (void) user;
+ PK11_DestroyGenericObject(obj);
+}
+
+/* same as nss_destroy_object() but for CRL items */
+static void nss_destroy_crl_item(void *user, void *ptr)
+{
+ SECItem *crl_der = (SECItem *)ptr;
+ (void) user;
+ SECITEM_FreeItem(crl_der, PR_TRUE);
+}
+
+static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
+ const char *filename, PRBool cacert)
+{
+ CURLcode err = (cacert)
+ ? CURLE_SSL_CACERT_BADFILE
+ : CURLE_SSL_CERTPROBLEM;
+
+ /* libnsspem.so leaks memory if the requested file does not exist. For more
+ * details, go to <https://bugzilla.redhat.com/734760>. */
+ if(is_file(filename))
+ err = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
+
+ if(CURLE_OK == err && !cacert) {
+ /* we have successfully loaded a client certificate */
+ CERTCertificate *cert;
+ char *nickname = NULL;
+ char *n = strrchr(filename, '/');
+ if(n)
+ n++;
+
+ /* The following undocumented magic helps to avoid a SIGSEGV on call
+ * of PK11_ReadRawAttribute() from SelectClientCert() when using an
+ * immature version of libnsspem.so. For more details, go to
+ * <https://bugzilla.redhat.com/733685>. */
+ nickname = aprintf("PEM Token #1:%s", n);
+ if(nickname) {
+ cert = PK11_FindCertFromNickname(nickname, NULL);
+ if(cert)
+ CERT_DestroyCertificate(cert);
+
+ free(nickname);
+ }
+ }
+
+ return err;
+}
+
+/* add given CRL to cache if it is not already there */
+static CURLcode nss_cache_crl(SECItem *crl_der)
+{
+ CERTCertDBHandle *db = CERT_GetDefaultCertDB();
+ CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0);
+ if(crl) {
+ /* CRL already cached */
+ SEC_DestroyCrl(crl);
+ SECITEM_FreeItem(crl_der, PR_TRUE);
+ return CURLE_SSL_CRL_BADFILE;
+ }
+
+ /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */
+ PR_Lock(nss_crllock);
+
+ /* store the CRL item so that we can free it in Curl_nss_cleanup() */
+ if(!Curl_llist_insert_next(nss_crl_list, nss_crl_list->tail, crl_der)) {
+ SECITEM_FreeItem(crl_der, PR_TRUE);
+ PR_Unlock(nss_crllock);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
+ /* unable to cache CRL */
+ PR_Unlock(nss_crllock);
+ return CURLE_SSL_CRL_BADFILE;
+ }
+
+ /* we need to clear session cache, so that the CRL could take effect */
+ SSL_ClearSessionCache();
+ PR_Unlock(nss_crllock);
+ return CURLE_OK;
+}
+
+static CURLcode nss_load_crl(const char* crlfilename)
+{
+ PRFileDesc *infile;
+ PRFileInfo info;
+ SECItem filedata = { 0, NULL, 0 };
+ SECItem *crl_der = NULL;
+ char *body;
+
+ infile = PR_Open(crlfilename, PR_RDONLY, 0);
+ if(!infile)
+ return CURLE_SSL_CRL_BADFILE;
+
+ if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
+ goto fail;
+
+ if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
+ goto fail;
+
+ if(info.size != PR_Read(infile, filedata.data, info.size))
+ goto fail;
+
+ crl_der = SECITEM_AllocItem(NULL, NULL, 0U);
+ if(!crl_der)
+ goto fail;
+
+ /* place a trailing zero right after the visible data */
+ body = (char*)filedata.data;
+ body[--filedata.len] = '\0';
+
+ body = strstr(body, "-----BEGIN");
+ if(body) {
+ /* assume ASCII */
+ char *trailer;
+ char *begin = PORT_Strchr(body, '\n');
+ if(!begin)
+ begin = PORT_Strchr(body, '\r');
+ if(!begin)
+ goto fail;
+
+ trailer = strstr(++begin, "-----END");
+ if(!trailer)
+ goto fail;
+
+ /* retrieve DER from ASCII */
+ *trailer = '\0';
+ if(ATOB_ConvertAsciiToItem(crl_der, begin))
+ goto fail;
+
+ SECITEM_FreeItem(&filedata, PR_FALSE);
+ }
+ else
+ /* assume DER */
+ *crl_der = filedata;
+
+ PR_Close(infile);
+ return nss_cache_crl(crl_der);
+
+fail:
+ PR_Close(infile);
+ SECITEM_FreeItem(crl_der, PR_TRUE);
+ SECITEM_FreeItem(&filedata, PR_FALSE);
+ return CURLE_SSL_CRL_BADFILE;
+}
+
+static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
+ char *key_file)
+{
+ PK11SlotInfo *slot;
+ SECStatus status;
+ CURLcode rv;
+ struct ssl_connect_data *ssl = conn->ssl;
+ (void)sockindex; /* unused */
+
+ rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
+ if(CURLE_OK != rv) {
+ PR_SetError(SEC_ERROR_BAD_KEY, 0);
+ return rv;
+ }
+
+ slot = PK11_FindSlotByName("PEM Token #1");
+ if(!slot)
+ return CURLE_SSL_CERTPROBLEM;
+
+ /* This will force the token to be seen as re-inserted */
+ SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
+ PK11_IsPresent(slot);
+
+ status = PK11_Authenticate(slot, PR_TRUE,
+ conn->data->set.str[STRING_KEY_PASSWD]);
+ PK11_FreeSlot(slot);
+ return (SECSuccess == status)
+ ? CURLE_OK
+ : CURLE_SSL_CERTPROBLEM;
+}
+
+static int display_error(struct connectdata *conn, PRInt32 err,
+ const char *filename)
+{
+ switch(err) {
+ case SEC_ERROR_BAD_PASSWORD:
+ failf(conn->data, "Unable to load client key: Incorrect password");
+ return 1;
+ case SEC_ERROR_UNKNOWN_CERT:
+ failf(conn->data, "Unable to load certificate %s", filename);
+ return 1;
+ default:
+ break;
+ }
+ return 0; /* The caller will print a generic error */
+}
+
+static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
+ char *cert_file, char *key_file)
+{
+ struct SessionHandle *data = conn->data;
+ CURLcode rv;
+
+ if(cert_file) {
+ rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
+ if(CURLE_OK != rv) {
+ const PRErrorCode err = PR_GetError();
+ if(!display_error(conn, err, cert_file)) {
+ const char *err_name = nss_error_to_name(err);
+ failf(data, "unable to load client cert: %d (%s)", err, err_name);
+ }
+
+ return rv;
+ }
+ }
+
+ if(key_file || (is_file(cert_file))) {
+ if(key_file)
+ rv = nss_load_key(conn, sockindex, key_file);
+ else
+ /* In case the cert file also has the key */
+ rv = nss_load_key(conn, sockindex, cert_file);
+ if(CURLE_OK != rv) {
+ const PRErrorCode err = PR_GetError();
+ if(!display_error(conn, err, key_file)) {
+ const char *err_name = nss_error_to_name(err);
+ failf(data, "unable to load client key: %d (%s)", err, err_name);
+ }
+
+ return rv;
+ }
+ }
+
+ return CURLE_OK;
+}
+
+static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
+{
+ (void)slot; /* unused */
+ if(retry || NULL == arg)
+ return NULL;
+ else
+ return (char *)PORT_Strdup((char *)arg);
+}
+
+/* bypass the default SSL_AuthCertificate() hook in case we do not want to
+ * verify peer */
+static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
+ PRBool isServer)
+{
+ struct connectdata *conn = (struct connectdata *)arg;
+ if(!conn->data->set.ssl.verifypeer) {
+ infof(conn->data, "skipping SSL peer certificate verification\n");
+ return SECSuccess;
+ }
+
+ return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
+}
+
+/**
+ * Inform the application that the handshake is complete.
+ */
+static void HandshakeCallback(PRFileDesc *sock, void *arg)
+{
+#ifdef USE_NGHTTP2
+ struct connectdata *conn = (struct connectdata*) arg;
+ unsigned int buflenmax = 50;
+ unsigned char buf[50];
+ unsigned int buflen;
+ SSLNextProtoState state;
+
+ if(!conn->data->set.ssl_enable_npn && !conn->data->set.ssl_enable_alpn) {
+ return;
+ }
+
+ if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
+
+ switch(state) {
+ case SSL_NEXT_PROTO_NO_SUPPORT:
+ case SSL_NEXT_PROTO_NO_OVERLAP:
+ infof(conn->data, "TLS, neither ALPN nor NPN succeeded\n");
+ return;
+#ifdef SSL_ENABLE_ALPN
+ case SSL_NEXT_PROTO_SELECTED:
+ infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf);
+ break;
+#endif
+ case SSL_NEXT_PROTO_NEGOTIATED:
+ infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf);
+ break;
+ }
+
+ if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN &&
+ memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)
+ == 0) {
+ conn->negnpn = NPN_HTTP2;
+ }
+ else if(buflen == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, buf,
+ ALPN_HTTP_1_1_LENGTH)) {
+ conn->negnpn = NPN_HTTP1_1;
+ }
+ }
+#else
+ (void)sock;
+ (void)arg;
+#endif
+}
+
+static void display_cert_info(struct SessionHandle *data,
+ CERTCertificate *cert)
+{
+ char *subject, *issuer, *common_name;
+ PRExplodedTime printableTime;
+ char timeString[256];
+ PRTime notBefore, notAfter;
+
+ subject = CERT_NameToAscii(&cert->subject);
+ issuer = CERT_NameToAscii(&cert->issuer);
+ common_name = CERT_GetCommonName(&cert->subject);
+ infof(data, "\tsubject: %s\n", subject);
+
+ CERT_GetCertTimes(cert, &notBefore, &notAfter);
+ PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
+ PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
+ infof(data, "\tstart date: %s\n", timeString);
+ PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
+ PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
+ infof(data, "\texpire date: %s\n", timeString);
+ infof(data, "\tcommon name: %s\n", common_name);
+ infof(data, "\tissuer: %s\n", issuer);
+
+ PR_Free(subject);
+ PR_Free(issuer);
+ PR_Free(common_name);
+}
+
+static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
+{
+ SSLChannelInfo channel;
+ SSLCipherSuiteInfo suite;
+ CERTCertificate *cert;
+ CERTCertificate *cert2;
+ CERTCertificate *cert3;
+ PRTime now;
+ int i;
+
+ if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
+ SECSuccess && channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite) == SECSuccess) {
+ infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
+ }
+ }
+
+ cert = SSL_PeerCertificate(sock);
+
+ if(cert) {
+ infof(conn->data, "Server certificate:\n");
+
+ if(!conn->data->set.ssl.certinfo) {
+ display_cert_info(conn->data, cert);
+ CERT_DestroyCertificate(cert);
+ }
+ else {
+ /* Count certificates in chain. */
+ now = PR_Now();
+ i = 1;
+ if(!cert->isRoot) {
+ cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
+ while(cert2) {
+ i++;
+ if(cert2->isRoot) {
+ CERT_DestroyCertificate(cert2);
+ break;
+ }
+ cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
+ CERT_DestroyCertificate(cert2);
+ cert2 = cert3;
+ }
+ }
+ Curl_ssl_init_certinfo(conn->data, i);
+ for(i = 0; cert; cert = cert2) {
+ Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data,
+ (char *)cert->derCert.data + cert->derCert.len);
+ if(cert->isRoot) {
+ CERT_DestroyCertificate(cert);
+ break;
+ }
+ cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ }
+
+ return;
+}
+
+static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
+{
+ struct connectdata *conn = (struct connectdata *)arg;
+ struct SessionHandle *data = conn->data;
+ PRErrorCode err = PR_GetError();
+ CERTCertificate *cert;
+
+ /* remember the cert verification result */
+ data->set.ssl.certverifyresult = err;
+
+ if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
+ /* we are asked not to verify the host name */
+ return SECSuccess;
+
+ /* print only info about the cert, the error is printed off the callback */
+ cert = SSL_PeerCertificate(sock);
+ if(cert) {
+ infof(data, "Server certificate:\n");
+ display_cert_info(data, cert);
+ CERT_DestroyCertificate(cert);
+ }
+
+ return SECFailure;
+}
+
+/**
+ *
+ * Check that the Peer certificate's issuer certificate matches the one found
+ * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the
+ * issuer check, so we provide comments that mimic the OpenSSL
+ * X509_check_issued function (in x509v3/v3_purp.c)
+ */
+static SECStatus check_issuer_cert(PRFileDesc *sock,
+ char *issuer_nickname)
+{
+ CERTCertificate *cert,*cert_issuer,*issuer;
+ SECStatus res=SECSuccess;
+ void *proto_win = NULL;
+
+ /*
+ PRArenaPool *tmpArena = NULL;
+ CERTAuthKeyID *authorityKeyID = NULL;
+ SECITEM *caname = NULL;
+ */
+
+ cert = SSL_PeerCertificate(sock);
+ cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner);
+
+ proto_win = SSL_RevealPinArg(sock);
+ issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
+
+ if((!cert_issuer) || (!issuer))
+ res = SECFailure;
+ else if(SECITEM_CompareItem(&cert_issuer->derCert,
+ &issuer->derCert)!=SECEqual)
+ res = SECFailure;
+
+ CERT_DestroyCertificate(cert);
+ CERT_DestroyCertificate(issuer);
+ CERT_DestroyCertificate(cert_issuer);
+ return res;
+}
+
+/**
+ *
+ * Callback to pick the SSL client certificate.
+ */
+static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
+ struct SessionHandle *data = connssl->data;
+ const char *nickname = connssl->client_nickname;
+
+ if(connssl->obj_clicert) {
+ /* use the cert/key provided by PEM reader */
+ static const char pem_slotname[] = "PEM Token #1";
+ SECItem cert_der = { 0, NULL, 0 };
+ void *proto_win = SSL_RevealPinArg(sock);
+ struct CERTCertificateStr *cert;
+ struct SECKEYPrivateKeyStr *key;
+
+ PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
+ if(NULL == slot) {
+ failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
+ return SECFailure;
+ }
+
+ if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
+ &cert_der) != SECSuccess) {
+ failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
+ PK11_FreeSlot(slot);
+ return SECFailure;
+ }
+
+ cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
+ SECITEM_FreeItem(&cert_der, PR_FALSE);
+ if(NULL == cert) {
+ failf(data, "NSS: client certificate from file not found");
+ PK11_FreeSlot(slot);
+ return SECFailure;
+ }
+
+ key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
+ PK11_FreeSlot(slot);
+ if(NULL == key) {
+ failf(data, "NSS: private key from file not found");
+ CERT_DestroyCertificate(cert);
+ return SECFailure;
+ }
+
+ infof(data, "NSS: client certificate from file\n");
+ display_cert_info(data, cert);
+
+ *pRetCert = cert;
+ *pRetKey = key;
+ return SECSuccess;
+ }
+
+ /* use the default NSS hook */
+ if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
+ pRetCert, pRetKey)
+ || NULL == *pRetCert) {
+
+ if(NULL == nickname)
+ failf(data, "NSS: client certificate not found (nickname not "
+ "specified)");
+ else
+ failf(data, "NSS: client certificate not found: %s", nickname);
+
+ return SECFailure;
+ }
+
+ /* get certificate nickname if any */
+ nickname = (*pRetCert)->nickname;
+ if(NULL == nickname)
+ nickname = "[unknown]";
+
+ if(NULL == *pRetKey) {
+ failf(data, "NSS: private key not found for certificate: %s", nickname);
+ return SECFailure;
+ }
+
+ infof(data, "NSS: using client certificate: %s\n", nickname);
+ display_cert_info(data, *pRetCert);
+ return SECSuccess;
+}
+
+/* This function is supposed to decide, which error codes should be used
+ * to conclude server is TLS intolerant.
+ *
+ * taken from xulrunner - nsNSSIOLayer.cpp
+ */
+static PRBool
+isTLSIntoleranceError(PRInt32 err)
+{
+ switch (err) {
+ case SSL_ERROR_BAD_MAC_ALERT:
+ case SSL_ERROR_BAD_MAC_READ:
+ case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
+ case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
+ case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE:
+ case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
+ case SSL_ERROR_NO_CYPHER_OVERLAP:
+ case SSL_ERROR_BAD_SERVER:
+ case SSL_ERROR_BAD_BLOCK_PADDING:
+ case SSL_ERROR_UNSUPPORTED_VERSION:
+ case SSL_ERROR_PROTOCOL_VERSION_ALERT:
+ case SSL_ERROR_RX_MALFORMED_FINISHED:
+ case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE:
+ case SSL_ERROR_DECODE_ERROR_ALERT:
+ case SSL_ERROR_RX_UNKNOWN_ALERT:
+ return PR_TRUE;
+ default:
+ return PR_FALSE;
+ }
+}
+
+/* update blocking direction in case of PR_WOULD_BLOCK_ERROR */
+static void nss_update_connecting_state(ssl_connect_state state, void *secret)
+{
+ struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret;
+ if(PR_GetError() != PR_WOULD_BLOCK_ERROR)
+ /* an unrelated error is passing by */
+ return;
+
+ switch(connssl->connecting_state) {
+ case ssl_connect_2:
+ case ssl_connect_2_reading:
+ case ssl_connect_2_writing:
+ break;
+ default:
+ /* we are not called from an SSL handshake */
+ return;
+ }
+
+ /* update the state accordingly */
+ connssl->connecting_state = state;
+}
+
+/* recv() wrapper we use to detect blocking direction during SSL handshake */
+static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ const PRRecvFN recv_fn = fd->lower->methods->recv;
+ const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout);
+ if(rv < 0)
+ /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
+ nss_update_connecting_state(ssl_connect_2_reading, fd->secret);
+ return rv;
+}
+
+/* send() wrapper we use to detect blocking direction during SSL handshake */
+static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ const PRSendFN send_fn = fd->lower->methods->send;
+ const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout);
+ if(rv < 0)
+ /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
+ nss_update_connecting_state(ssl_connect_2_writing, fd->secret);
+ return rv;
+}
+
+/* close() wrapper to avoid assertion failure due to fd->secret != NULL */
+static PRStatus nspr_io_close(PRFileDesc *fd)
+{
+ const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close;
+ fd->secret = NULL;
+ return close_fn(fd);
+}
+
+static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
+{
+ NSSInitParameters initparams;
+
+ if(nss_context != NULL)
+ return CURLE_OK;
+
+ memset((void *) &initparams, '\0', sizeof(initparams));
+ initparams.length = sizeof(initparams);
+
+ if(cert_dir) {
+ char *certpath = aprintf("sql:%s", cert_dir);
+ if(!certpath)
+ return CURLE_OUT_OF_MEMORY;
+
+ infof(data, "Initializing NSS with certpath: %s\n", certpath);
+ nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
+ NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
+ free(certpath);
+
+ if(nss_context != NULL)
+ return CURLE_OK;
+
+ infof(data, "Unable to initialize NSS database\n");
+ }
+
+ infof(data, "Initializing NSS with certpath: none\n");
+ nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
+ | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
+ | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
+ if(nss_context != NULL)
+ return CURLE_OK;
+
+ infof(data, "Unable to initialize NSS\n");
+ return CURLE_SSL_CACERT_BADFILE;
+}
+
+static CURLcode nss_init(struct SessionHandle *data)
+{
+ char *cert_dir;
+ struct_stat st;
+ CURLcode rv;
+
+ if(initialized)
+ return CURLE_OK;
+
+ /* list of all CRL items we need to destroy in Curl_nss_cleanup() */
+ nss_crl_list = Curl_llist_alloc(nss_destroy_crl_item);
+ if(!nss_crl_list)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* First we check if $SSL_DIR points to a valid dir */
+ cert_dir = getenv("SSL_DIR");
+ if(cert_dir) {
+ if((stat(cert_dir, &st) != 0) ||
+ (!S_ISDIR(st.st_mode))) {
+ cert_dir = NULL;
+ }
+ }
+
+ /* Now we check if the default location is a valid dir */
+ if(!cert_dir) {
+ if((stat(SSL_DIR, &st) == 0) &&
+ (S_ISDIR(st.st_mode))) {
+ cert_dir = (char *)SSL_DIR;
+ }
+ }
+
+ if(nspr_io_identity == PR_INVALID_IO_LAYER) {
+ /* allocate an identity for our own NSPR I/O layer */
+ nspr_io_identity = PR_GetUniqueIdentity("libcurl");
+ if(nspr_io_identity == PR_INVALID_IO_LAYER)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* the default methods just call down to the lower I/O layer */
+ memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods);
+
+ /* override certain methods in the table by our wrappers */
+ nspr_io_methods.recv = nspr_io_recv;
+ nspr_io_methods.send = nspr_io_send;
+ nspr_io_methods.close = nspr_io_close;
+ }
+
+ rv = nss_init_core(data, cert_dir);
+ if(rv)
+ return rv;
+
+ if(num_enabled_ciphers() == 0)
+ NSS_SetDomesticPolicy();
+
+ initialized = 1;
+ return CURLE_OK;
+}
+
+/**
+ * Global SSL init
+ *
+ * @retval 0 error initializing SSL
+ * @retval 1 SSL initialized successfully
+ */
+int Curl_nss_init(void)
+{
+ /* curl_global_init() is not thread-safe so this test is ok */
+ if(nss_initlock == NULL) {
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
+ nss_initlock = PR_NewLock();
+ nss_crllock = PR_NewLock();
+ }
+
+ /* We will actually initialize NSS later */
+
+ return 1;
+}
+
+CURLcode Curl_nss_force_init(struct SessionHandle *data)
+{
+ CURLcode rv;
+ if(!nss_initlock) {
+ failf(data,
+ "unable to initialize NSS, curl_global_init() should have been "
+ "called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
+ return CURLE_FAILED_INIT;
+ }
+
+ PR_Lock(nss_initlock);
+ rv = nss_init(data);
+ PR_Unlock(nss_initlock);
+ return rv;
+}
+
+/* Global cleanup */
+void Curl_nss_cleanup(void)
+{
+ /* This function isn't required to be threadsafe and this is only done
+ * as a safety feature.
+ */
+ PR_Lock(nss_initlock);
+ if(initialized) {
+ /* Free references to client certificates held in the SSL session cache.
+ * Omitting this hampers destruction of the security module owning
+ * the certificates. */
+ SSL_ClearSessionCache();
+
+ if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
+ SECMOD_DestroyModule(mod);
+ mod = NULL;
+ }
+ NSS_ShutdownContext(nss_context);
+ nss_context = NULL;
+ }
+
+ /* destroy all CRL items */
+ Curl_llist_destroy(nss_crl_list, NULL);
+ nss_crl_list = NULL;
+
+ PR_Unlock(nss_initlock);
+
+ PR_DestroyLock(nss_initlock);
+ PR_DestroyLock(nss_crllock);
+ nss_initlock = NULL;
+
+ initialized = 0;
+}
+
+/*
+ * This function uses SSL_peek to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+int
+Curl_nss_check_cxn(struct connectdata *conn)
+{
+ int rc;
+ char buf;
+
+ rc =
+ PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
+ PR_SecondsToInterval(1));
+ if(rc > 0)
+ return 1; /* connection still in place */
+
+ if(rc == 0)
+ return 0; /* connection has been closed */
+
+ return -1; /* connection status unknown */
+}
+
+/*
+ * This function is called when an SSL connection is closed.
+ */
+void Curl_nss_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->handle) {
+ /* NSS closes the socket we previously handed to it, so we must mark it
+ as closed to avoid double close */
+ fake_sclose(conn->sock[sockindex]);
+ conn->sock[sockindex] = CURL_SOCKET_BAD;
+
+ if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
+ /* A server might require different authentication based on the
+ * particular path being requested by the client. To support this
+ * scenario, we must ensure that a connection will never reuse the
+ * authentication data from a previous connection. */
+ SSL_InvalidateSession(connssl->handle);
+
+ if(connssl->client_nickname != NULL) {
+ free(connssl->client_nickname);
+ connssl->client_nickname = NULL;
+ }
+ /* destroy all NSS objects in order to avoid failure of NSS shutdown */
+ Curl_llist_destroy(connssl->obj_list, NULL);
+ connssl->obj_list = NULL;
+ connssl->obj_clicert = NULL;
+
+ PR_Close(connssl->handle);
+ connssl->handle = NULL;
+ }
+}
+
+/*
+ * This function is called when the 'data' struct is going away. Close
+ * down everything and free all resources!
+ */
+int Curl_nss_close_all(struct SessionHandle *data)
+{
+ (void)data;
+ return 0;
+}
+
+/* return true if NSS can provide error code (and possibly msg) for the
+ error */
+static bool is_nss_error(CURLcode err)
+{
+ switch(err) {
+ case CURLE_PEER_FAILED_VERIFICATION:
+ case CURLE_SSL_CACERT:
+ case CURLE_SSL_CERTPROBLEM:
+ case CURLE_SSL_CONNECT_ERROR:
+ case CURLE_SSL_ISSUER_ERROR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* return true if the given error code is related to a client certificate */
+static bool is_cc_error(PRInt32 err)
+{
+ switch(err) {
+ case SSL_ERROR_BAD_CERT_ALERT:
+ case SSL_ERROR_EXPIRED_CERT_ALERT:
+ case SSL_ERROR_REVOKED_CERT_ALERT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static Curl_recv nss_recv;
+static Curl_send nss_send;
+
+static CURLcode nss_load_ca_certificates(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ const char *cafile = data->set.ssl.CAfile;
+ const char *capath = data->set.ssl.CApath;
+
+ if(cafile) {
+ CURLcode rv = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
+ if(CURLE_OK != rv)
+ return rv;
+ }
+
+ if(capath) {
+ struct_stat st;
+ if(stat(capath, &st) == -1)
+ return CURLE_SSL_CACERT_BADFILE;
+
+ if(S_ISDIR(st.st_mode)) {
+ PRDirEntry *entry;
+ PRDir *dir = PR_OpenDir(capath);
+ if(!dir)
+ return CURLE_SSL_CACERT_BADFILE;
+
+ while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) {
+ char *fullpath = aprintf("%s/%s", capath, entry->name);
+ if(!fullpath) {
+ PR_CloseDir(dir);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
+ /* This is purposefully tolerant of errors so non-PEM files can
+ * be in the same directory */
+ infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath);
+
+ free(fullpath);
+ }
+
+ PR_CloseDir(dir);
+ }
+ else
+ infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
+ }
+
+ infof(data, " CAfile: %s\n CApath: %s\n",
+ cafile ? cafile : "none",
+ capath ? capath : "none");
+
+ return CURLE_OK;
+}
+
+static CURLcode nss_init_sslver(SSLVersionRange *sslver,
+ struct SessionHandle *data)
+{
+ switch (data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ sslver->min = SSL_LIBRARY_VERSION_3_0;
+ if(data->state.ssl_connect_retry) {
+ infof(data, "TLS disabled due to previous handshake failure\n");
+ sslver->max = SSL_LIBRARY_VERSION_3_0;
+ return CURLE_OK;
+ }
+ /* intentional fall-through to default to highest TLS version if possible */
+
+ case CURL_SSLVERSION_TLSv1:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_2
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+#elif defined SSL_LIBRARY_VERSION_TLS_1_1
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+#else
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+#endif
+ return CURLE_OK;
+
+ case CURL_SSLVERSION_SSLv2:
+ sslver->min = SSL_LIBRARY_VERSION_2;
+ sslver->max = SSL_LIBRARY_VERSION_2;
+ return CURLE_OK;
+
+ case CURL_SSLVERSION_SSLv3:
+ sslver->min = SSL_LIBRARY_VERSION_3_0;
+ sslver->max = SSL_LIBRARY_VERSION_3_0;
+ return CURLE_OK;
+
+ case CURL_SSLVERSION_TLSv1_0:
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+ return CURLE_OK;
+
+ case CURL_SSLVERSION_TLSv1_1:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_1
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_1;
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+ return CURLE_OK;
+#endif
+ break;
+
+ case CURL_SSLVERSION_TLSv1_2:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_2
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_2;
+ sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+ return CURLE_OK;
+#endif
+ break;
+ }
+
+ failf(data, "TLS minor version cannot be set");
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
+ struct SessionHandle *data,
+ CURLcode curlerr)
+{
+ SSLVersionRange sslver;
+ PRErrorCode err = 0;
+
+ /* reset the flag to avoid an infinite loop */
+ data->state.ssl_connect_retry = FALSE;
+
+ if(is_nss_error(curlerr)) {
+ /* read NSPR error code */
+ err = PR_GetError();
+ if(is_cc_error(err))
+ curlerr = CURLE_SSL_CERTPROBLEM;
+
+ /* print the error number and error string */
+ infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
+
+ /* print a human-readable message describing the error if available */
+ nss_print_error_message(data, err);
+ }
+
+ /* cleanup on connection failure */
+ Curl_llist_destroy(connssl->obj_list, NULL);
+ connssl->obj_list = NULL;
+
+ if(connssl->handle
+ && (SSL_VersionRangeGet(connssl->handle, &sslver) == SECSuccess)
+ && (sslver.min == SSL_LIBRARY_VERSION_3_0)
+ && (sslver.max != SSL_LIBRARY_VERSION_3_0)
+ && isTLSIntoleranceError(err)) {
+ /* schedule reconnect through Curl_retry_request() */
+ data->state.ssl_connect_retry = TRUE;
+ infof(data, "Error in TLS handshake, trying SSLv3...\n");
+ return CURLE_OK;
+ }
+
+ return curlerr;
+}
+
+/* Switch the SSL socket into non-blocking mode. */
+static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl,
+ struct SessionHandle *data)
+{
+ static PRSocketOptionData sock_opt;
+ sock_opt.option = PR_SockOpt_Nonblocking;
+ sock_opt.value.non_blocking = PR_TRUE;
+
+ if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
+ return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
+
+ return CURLE_OK;
+}
+
+static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
+{
+ PRFileDesc *model = NULL;
+ PRFileDesc *nspr_io = NULL;
+ PRFileDesc *nspr_io_stub = NULL;
+ PRBool ssl_no_cache;
+ PRBool ssl_cbc_random_iv;
+ struct SessionHandle *data = conn->data;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode curlerr;
+
+ SSLVersionRange sslver = {
+ SSL_LIBRARY_VERSION_TLS_1_0, /* min */
+ SSL_LIBRARY_VERSION_TLS_1_0 /* max */
+ };
+
+#ifdef USE_NGHTTP2
+#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
+ unsigned int alpn_protos_len = NGHTTP2_PROTO_VERSION_ID_LEN +
+ ALPN_HTTP_1_1_LENGTH + 2;
+ unsigned char alpn_protos[NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH
+ + 2];
+ int cur = 0;
+#endif
+#endif
+
+
+ if(connssl->state == ssl_connection_complete)
+ return CURLE_OK;
+
+ connssl->data = data;
+
+ /* list of all NSS objects we need to destroy in Curl_nss_close() */
+ connssl->obj_list = Curl_llist_alloc(nss_destroy_object);
+ if(!connssl->obj_list)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* FIXME. NSS doesn't support multiple databases open at the same time. */
+ PR_Lock(nss_initlock);
+ curlerr = nss_init(conn->data);
+ if(CURLE_OK != curlerr) {
+ PR_Unlock(nss_initlock);
+ goto error;
+ }
+
+ curlerr = CURLE_SSL_CONNECT_ERROR;
+
+ if(!mod) {
+ char *configstring = aprintf("library=%s name=PEM", pem_library);
+ if(!configstring) {
+ PR_Unlock(nss_initlock);
+ goto error;
+ }
+ mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
+ free(configstring);
+
+ if(!mod || !mod->loaded) {
+ if(mod) {
+ SECMOD_DestroyModule(mod);
+ mod = NULL;
+ }
+ infof(data, "WARNING: failed to load NSS PEM library %s. Using "
+ "OpenSSL PEM certificates will not work.\n", pem_library);
+ }
+ }
+
+ PK11_SetPasswordFunc(nss_get_password);
+ PR_Unlock(nss_initlock);
+
+ model = PR_NewTCPSocket();
+ if(!model)
+ goto error;
+ model = SSL_ImportFD(NULL, model);
+
+ if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
+ goto error;
+ if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
+ goto error;
+ if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
+ goto error;
+
+ /* do not use SSL cache if disabled or we are not going to verify peer */
+ ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
+ PR_FALSE : PR_TRUE;
+ if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
+ goto error;
+
+ /* enable/disable the requested SSL version(s) */
+ if(nss_init_sslver(&sslver, data) != CURLE_OK)
+ goto error;
+ if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
+ goto error;
+
+ ssl_cbc_random_iv = !data->set.ssl_enable_beast;
+#ifdef SSL_CBC_RANDOM_IV
+ /* unless the user explicitly asks to allow the protocol vulnerability, we
+ use the work-around */
+ if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
+ infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n",
+ ssl_cbc_random_iv);
+#else
+ if(ssl_cbc_random_iv)
+ infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
+#endif
+
+ /* reset the flag to avoid an infinite loop */
+ data->state.ssl_connect_retry = FALSE;
+
+ if(data->set.ssl.cipher_list) {
+ if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
+ curlerr = CURLE_SSL_CIPHER;
+ goto error;
+ }
+ }
+
+ if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
+ infof(data, "warning: ignoring value of ssl.verifyhost\n");
+
+ /* bypass the default SSL_AuthCertificate() hook in case we do not want to
+ * verify peer */
+ if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
+ goto error;
+
+ data->set.ssl.certverifyresult=0; /* not checked yet */
+ if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
+ goto error;
+
+ if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
+ goto error;
+
+ if(data->set.ssl.verifypeer) {
+ const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
+ if(CURLE_OK != rv) {
+ curlerr = rv;
+ goto error;
+ }
+ }
+
+ if(data->set.ssl.CRLfile) {
+ const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile);
+ if(CURLE_OK != rv) {
+ curlerr = rv;
+ goto error;
+ }
+ infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile);
+ }
+
+ if(data->set.str[STRING_CERT]) {
+ char *nickname = dup_nickname(data, STRING_CERT);
+ if(nickname) {
+ /* we are not going to use libnsspem.so to read the client cert */
+ connssl->obj_clicert = NULL;
+ }
+ else {
+ CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
+ data->set.str[STRING_KEY]);
+ if(CURLE_OK != rv) {
+ /* failf() is already done in cert_stuff() */
+ curlerr = rv;
+ goto error;
+ }
+ }
+
+ /* store the nickname for SelectClientCert() called during handshake */
+ connssl->client_nickname = nickname;
+ }
+ else
+ connssl->client_nickname = NULL;
+
+ if(SSL_GetClientAuthDataHook(model, SelectClientCert,
+ (void *)connssl) != SECSuccess) {
+ curlerr = CURLE_SSL_CERTPROBLEM;
+ goto error;
+ }
+
+ /* wrap OS file descriptor by NSPR's file descriptor abstraction */
+ nspr_io = PR_ImportTCPSocket(sockfd);
+ if(!nspr_io)
+ goto error;
+
+ /* create our own NSPR I/O layer */
+ nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
+ if(!nspr_io_stub) {
+ PR_Close(nspr_io);
+ goto error;
+ }
+
+ /* make the per-connection data accessible from NSPR I/O callbacks */
+ nspr_io_stub->secret = (void *)connssl;
+
+ /* push our new layer to the NSPR I/O stack */
+ if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
+ PR_Close(nspr_io);
+ PR_Close(nspr_io_stub);
+ goto error;
+ }
+
+ /* import our model socket onto the current I/O stack */
+ connssl->handle = SSL_ImportFD(model, nspr_io);
+ if(!connssl->handle) {
+ PR_Close(nspr_io);
+ goto error;
+ }
+
+ PR_Close(model); /* We don't need this any more */
+ model = NULL;
+
+ /* This is the password associated with the cert that we're using */
+ if(data->set.str[STRING_KEY_PASSWD]) {
+ SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
+ }
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+#ifdef SSL_ENABLE_NPN
+ if(data->set.ssl_enable_npn) {
+ if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, PR_TRUE) != SECSuccess)
+ goto error;
+ }
+#endif
+
+#ifdef SSL_ENABLE_ALPN
+ if(data->set.ssl_enable_alpn) {
+ if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, PR_TRUE)
+ != SECSuccess)
+ goto error;
+ }
+#endif
+
+#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
+ if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) {
+ alpn_protos[cur] = NGHTTP2_PROTO_VERSION_ID_LEN;
+ cur++;
+ memcpy(&alpn_protos[cur], NGHTTP2_PROTO_VERSION_ID,
+ NGHTTP2_PROTO_VERSION_ID_LEN);
+ cur += NGHTTP2_PROTO_VERSION_ID_LEN;
+ alpn_protos[cur] = ALPN_HTTP_1_1_LENGTH;
+ cur++;
+ memcpy(&alpn_protos[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
+
+ if(SSL_SetNextProtoNego(connssl->handle, alpn_protos, alpn_protos_len)
+ != SECSuccess)
+ goto error;
+ }
+ else {
+ infof(data, "SSL, can't negotiate HTTP/2.0 with neither NPN nor ALPN\n");
+ }
+#endif
+ }
+#endif
+
+
+ /* Force handshake on next I/O */
+ SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
+
+ SSL_SetURL(connssl->handle, conn->host.name);
+
+ return CURLE_OK;
+
+error:
+ if(model)
+ PR_Close(model);
+
+ return nss_fail_connect(connssl, data, curlerr);
+}
+
+static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ CURLcode curlerr = CURLE_SSL_CONNECT_ERROR;
+ PRUint32 timeout;
+
+ /* check timeout situation */
+ const long time_left = Curl_timeleft(data, NULL, TRUE);
+ if(time_left < 0L) {
+ failf(data, "timed out before SSL handshake");
+ curlerr = CURLE_OPERATION_TIMEDOUT;
+ goto error;
+ }
+
+ /* Force the handshake now */
+ timeout = PR_MillisecondsToInterval((PRUint32) time_left);
+ if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
+ if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
+ /* blocking direction is updated by nss_update_connecting_state() */
+ return CURLE_AGAIN;
+ else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
+ curlerr = CURLE_PEER_FAILED_VERIFICATION;
+ else if(conn->data->set.ssl.certverifyresult!=0)
+ curlerr = CURLE_SSL_CACERT;
+ goto error;
+ }
+
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = nss_recv;
+ conn->send[sockindex] = nss_send;
+
+ display_conn_info(conn, connssl->handle);
+
+ if(data->set.str[STRING_SSL_ISSUERCERT]) {
+ SECStatus ret = SECFailure;
+ char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
+ if(nickname) {
+ /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
+ ret = check_issuer_cert(connssl->handle, nickname);
+ free(nickname);
+ }
+
+ if(SECFailure == ret) {
+ infof(data,"SSL certificate issuer check failed\n");
+ curlerr = CURLE_SSL_ISSUER_ERROR;
+ goto error;
+ }
+ else {
+ infof(data, "SSL certificate issuer check ok\n");
+ }
+ }
+
+ return CURLE_OK;
+
+error:
+ return nss_fail_connect(connssl, data, curlerr);
+}
+
+static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
+ bool *done)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ const bool blocking = (done == NULL);
+ CURLcode rv;
+
+ if(connssl->connecting_state == ssl_connect_1) {
+ rv = nss_setup_connect(conn, sockindex);
+ if(rv)
+ /* we do not expect CURLE_AGAIN from nss_setup_connect() */
+ return rv;
+
+ if(!blocking) {
+ /* in non-blocking mode, set NSS non-blocking mode before handshake */
+ rv = nss_set_nonblock(connssl, data);
+ if(rv)
+ return rv;
+ }
+
+ connssl->connecting_state = ssl_connect_2;
+ }
+
+ rv = nss_do_connect(conn, sockindex);
+ switch(rv) {
+ case CURLE_OK:
+ break;
+ case CURLE_AGAIN:
+ if(!blocking)
+ /* CURLE_AGAIN in non-blocking mode is not an error */
+ return CURLE_OK;
+ /* fall through */
+ default:
+ return rv;
+ }
+
+ if(blocking) {
+ /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
+ rv = nss_set_nonblock(connssl, data);
+ if(rv)
+ return rv;
+ }
+ else
+ /* signal completed SSL handshake */
+ *done = TRUE;
+
+ connssl->connecting_state = ssl_connect_done;
+ return CURLE_OK;
+}
+
+CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+{
+ return nss_connect_common(conn, sockindex, /* blocking */ NULL);
+}
+
+CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
+{
+ return nss_connect_common(conn, sockindex, done);
+}
+
+static ssize_t nss_send(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ const void *mem, /* send this data */
+ size_t len, /* amount to write */
+ CURLcode *curlcode)
+{
+ ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0,
+ PR_INTERVAL_NO_WAIT);
+ if(rc < 0) {
+ PRInt32 err = PR_GetError();
+ if(err == PR_WOULD_BLOCK_ERROR)
+ *curlcode = CURLE_AGAIN;
+ else {
+ /* print the error number and error string */
+ const char *err_name = nss_error_to_name(err);
+ infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);
+
+ /* print a human-readable message describing the error if available */
+ nss_print_error_message(conn->data, err);
+
+ *curlcode = (is_cc_error(err))
+ ? CURLE_SSL_CERTPROBLEM
+ : CURLE_SEND_ERROR;
+ }
+ return -1;
+ }
+ return rc; /* number of bytes */
+}
+
+static ssize_t nss_recv(struct connectdata * conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ CURLcode *curlcode)
+{
+ ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0,
+ PR_INTERVAL_NO_WAIT);
+ if(nread < 0) {
+ /* failed SSL read */
+ PRInt32 err = PR_GetError();
+
+ if(err == PR_WOULD_BLOCK_ERROR)
+ *curlcode = CURLE_AGAIN;
+ else {
+ /* print the error number and error string */
+ const char *err_name = nss_error_to_name(err);
+ infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name);
+
+ /* print a human-readable message describing the error if available */
+ nss_print_error_message(conn->data, err);
+
+ *curlcode = (is_cc_error(err))
+ ? CURLE_SSL_CERTPROBLEM
+ : CURLE_RECV_ERROR;
+ }
+ return -1;
+ }
+ return nread;
+}
+
+size_t Curl_nss_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
+}
+
+int Curl_nss_seed(struct SessionHandle *data)
+{
+ /* make sure that NSS is initialized */
+ return !!Curl_nss_force_init(data);
+}
+
+/* data might be NULL */
+int Curl_nss_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+ if(data)
+ Curl_nss_seed(data); /* Initiate the seed if not already done */
+ if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) {
+ /* no way to signal a failure from here, we have to abort */
+ failf(data, "PK11_GenerateRandom() failed, calling abort()...");
+ abort();
+ }
+ return 0;
+}
+
+void Curl_nss_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
+{
+ PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
+ unsigned int MD5out;
+ PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
+ PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
+ PK11_DestroyContext(MD5pw, PR_TRUE);
+}
+
+#endif /* USE_NSS */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/nssg.h b/external/libcurl_android/jni/libcurl/lib/vtls/nssg.h
new file mode 100755
index 00000000..311f873d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/nssg.h
@@ -0,0 +1,89 @@
+#ifndef HEADER_CURL_NSSG_H
+#define HEADER_CURL_NSSG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_NSS
+/*
+ * This header should only be needed to get included by vtls.c and nss.c
+ */
+
+#include "urldata.h"
+
+CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex);
+CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+/* close a SSL connection */
+void Curl_nss_close(struct connectdata *conn, int sockindex);
+
+/* tell NSS to close down all open information regarding connections (and
+ thus session ID caching etc) */
+int Curl_nss_close_all(struct SessionHandle *data);
+
+int Curl_nss_init(void);
+void Curl_nss_cleanup(void);
+
+size_t Curl_nss_version(char *buffer, size_t size);
+int Curl_nss_check_cxn(struct connectdata *cxn);
+int Curl_nss_seed(struct SessionHandle *data);
+
+/* initialize NSS library if not already */
+CURLcode Curl_nss_force_init(struct SessionHandle *data);
+
+int Curl_nss_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length);
+
+void Curl_nss_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len);
+
+/* this backend provides these functions: */
+#define have_curlssl_md5sum 1
+
+/* API setup for NSS */
+#define curlssl_init Curl_nss_init
+#define curlssl_cleanup Curl_nss_cleanup
+#define curlssl_connect Curl_nss_connect
+#define curlssl_connect_nonblocking Curl_nss_connect_nonblocking
+
+/* NSS has its own session ID cache */
+#define curlssl_session_free(x) Curl_nop_stmt
+#define curlssl_close_all Curl_nss_close_all
+#define curlssl_close Curl_nss_close
+/* NSS has no shutdown function provided and thus always fail */
+#define curlssl_shutdown(x,y) (x=x, y=y, 1)
+#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_nss_version
+#define curlssl_check_cxn(x) Curl_nss_check_cxn(x)
+#define curlssl_data_pending(x,y) (x=x, y=y, 0)
+#define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
+#define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
+#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
+
+#endif /* USE_NSS */
+#endif /* HEADER_CURL_NSSG_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/openssl.c b/external/libcurl_android/jni/libcurl/lib/vtls/openssl.c
new file mode 100755
index 00000000..da928544
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/openssl.c
@@ -0,0 +1,2918 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ */
+
+/*
+ * The original SSLeay-using code for curl was written by Linas Vepstas and
+ * Sampo Kellomaki 1998.
+ */
+
+#include "curl_setup.h"
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "formdata.h" /* for the boundary function */
+#include "url.h" /* for the ssl config check function */
+#include "inet_pton.h"
+#include "openssl.h"
+#include "connect.h"
+#include "slist.h"
+#include "strequal.h"
+#include "select.h"
+#include "vtls.h"
+#include "rawstr.h"
+#include "hostcheck.h"
+
+#define _MPRINTF_REPLACE /* use the internal *printf() functions */
+#include <curl/mprintf.h>
+
+#ifdef USE_SSLEAY
+
+#ifdef USE_OPENSSL
+#include <openssl/rand.h>
+#include <openssl/x509v3.h>
+#include <openssl/dsa.h>
+#include <openssl/dh.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+#include <openssl/conf.h>
+#else
+#include <rand.h>
+#include <x509v3.h>
+#include <md5.h>
+#endif
+
+#include "warnless.h"
+#include "curl_memory.h"
+#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef OPENSSL_VERSION_NUMBER
+#error "OPENSSL_VERSION_NUMBER not defined"
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x0090581fL
+#define HAVE_SSL_GET1_SESSION 1
+#else
+#undef HAVE_SSL_GET1_SESSION
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00904100L
+#define HAVE_USERDATA_IN_PWD_CALLBACK 1
+#else
+#undef HAVE_USERDATA_IN_PWD_CALLBACK
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907001L
+/* ENGINE_load_private_key() takes four arguments */
+#define HAVE_ENGINE_LOAD_FOUR_ARGS
+#include <openssl/ui.h>
+#else
+/* ENGINE_load_private_key() takes three arguments */
+#undef HAVE_ENGINE_LOAD_FOUR_ARGS
+#endif
+
+#if (OPENSSL_VERSION_NUMBER >= 0x00903001L) && defined(HAVE_OPENSSL_PKCS12_H)
+/* OpenSSL has PKCS 12 support */
+#define HAVE_PKCS12_SUPPORT
+#else
+/* OpenSSL/SSLEay does not have PKCS12 support */
+#undef HAVE_PKCS12_SUPPORT
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00906001L
+#define HAVE_ERR_ERROR_STRING_N 1
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00909000L
+#define SSL_METHOD_QUAL const
+#else
+#define SSL_METHOD_QUAL
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+/* 0.9.6 didn't have X509_STORE_set_flags() */
+#define HAVE_X509_STORE_SET_FLAGS 1
+#else
+#define X509_STORE_set_flags(x,y) Curl_nop_stmt
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#define HAVE_ERR_REMOVE_THREAD_STATE 1
+#endif
+
+#ifndef HAVE_SSLV2_CLIENT_METHOD
+#undef OPENSSL_NO_SSL2 /* undef first to avoid compiler warnings */
+#define OPENSSL_NO_SSL2
+#endif
+
+/*
+ * Number of bytes to read from the random number seed file. This must be
+ * a finite value (because some entropy "files" like /dev/urandom have
+ * an infinite length), but must be large enough to provide enough
+ * entopy to properly seed OpenSSL's PRNG.
+ */
+#define RAND_LOAD_LENGTH 1024
+
+#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
+static char global_passwd[64];
+#endif
+
+static int passwd_callback(char *buf, int num, int encrypting
+#ifdef HAVE_USERDATA_IN_PWD_CALLBACK
+ /* This was introduced in 0.9.4, we can set this
+ using SSL_CTX_set_default_passwd_cb_userdata()
+ */
+ , void *global_passwd
+#endif
+ )
+{
+ DEBUGASSERT(0 == encrypting);
+
+ if(!encrypting) {
+ int klen = curlx_uztosi(strlen((char *)global_passwd));
+ if(num > klen) {
+ memcpy(buf, global_passwd, klen+1);
+ return klen;
+ }
+ }
+ return 0;
+}
+
+/*
+ * rand_enough() is a function that returns TRUE if we have seeded the random
+ * engine properly. We use some preprocessor magic to provide a seed_enough()
+ * macro to use, just to prevent a compiler warning on this function if we
+ * pass in an argument that is never used.
+ */
+
+#ifdef HAVE_RAND_STATUS
+#define seed_enough(x) rand_enough()
+static bool rand_enough(void)
+{
+ return (0 != RAND_status()) ? TRUE : FALSE;
+}
+#else
+#define seed_enough(x) rand_enough(x)
+static bool rand_enough(int nread)
+{
+ /* this is a very silly decision to make */
+ return (nread > 500) ? TRUE : FALSE;
+}
+#endif
+
+static int ossl_seed(struct SessionHandle *data)
+{
+ char *buf = data->state.buffer; /* point to the big buffer */
+ int nread=0;
+
+ /* Q: should we add support for a random file name as a libcurl option?
+ A: Yes, it is here */
+
+#ifndef RANDOM_FILE
+ /* if RANDOM_FILE isn't defined, we only perform this if an option tells
+ us to! */
+ if(data->set.ssl.random_file)
+#define RANDOM_FILE "" /* doesn't matter won't be used */
+#endif
+ {
+ /* let the option override the define */
+ nread += RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]?
+ data->set.str[STRING_SSL_RANDOM_FILE]:
+ RANDOM_FILE),
+ RAND_LOAD_LENGTH);
+ if(seed_enough(nread))
+ return nread;
+ }
+
+#if defined(HAVE_RAND_EGD)
+ /* only available in OpenSSL 0.9.5 and later */
+ /* EGD_SOCKET is set at configure time or not at all */
+#ifndef EGD_SOCKET
+ /* If we don't have the define set, we only do this if the egd-option
+ is set */
+ if(data->set.str[STRING_SSL_EGDSOCKET])
+#define EGD_SOCKET "" /* doesn't matter won't be used */
+#endif
+ {
+ /* If there's an option and a define, the option overrides the
+ define */
+ int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]?
+ data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
+ if(-1 != ret) {
+ nread += ret;
+ if(seed_enough(nread))
+ return nread;
+ }
+ }
+#endif
+
+ /* If we get here, it means we need to seed the PRNG using a "silly"
+ approach! */
+ do {
+ unsigned char randb[64];
+ int len = sizeof(randb);
+ RAND_bytes(randb, len);
+ RAND_add(randb, len, (len >> 1));
+ } while(!RAND_status());
+
+ /* generates a default path for the random seed file */
+ buf[0]=0; /* blank it first */
+ RAND_file_name(buf, BUFSIZE);
+ if(buf[0]) {
+ /* we got a file name to try */
+ nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
+ if(seed_enough(nread))
+ return nread;
+ }
+
+ infof(data, "libcurl is now using a weak random seed!\n");
+ return nread;
+}
+
+static int Curl_ossl_seed(struct SessionHandle *data)
+{
+ /* we have the "SSL is seeded" boolean static to prevent multiple
+ time-consuming seedings in vain */
+ static bool ssl_seeded = FALSE;
+
+ if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
+ data->set.str[STRING_SSL_EGDSOCKET]) {
+ ossl_seed(data);
+ ssl_seeded = TRUE;
+ }
+ return 0;
+}
+
+
+#ifndef SSL_FILETYPE_ENGINE
+#define SSL_FILETYPE_ENGINE 42
+#endif
+#ifndef SSL_FILETYPE_PKCS12
+#define SSL_FILETYPE_PKCS12 43
+#endif
+static int do_file_type(const char *type)
+{
+ if(!type || !type[0])
+ return SSL_FILETYPE_PEM;
+ if(Curl_raw_equal(type, "PEM"))
+ return SSL_FILETYPE_PEM;
+ if(Curl_raw_equal(type, "DER"))
+ return SSL_FILETYPE_ASN1;
+ if(Curl_raw_equal(type, "ENG"))
+ return SSL_FILETYPE_ENGINE;
+ if(Curl_raw_equal(type, "P12"))
+ return SSL_FILETYPE_PKCS12;
+ return -1;
+}
+
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_LOAD_FOUR_ARGS)
+/*
+ * Supply default password to the engine user interface conversation.
+ * The password is passed by OpenSSL engine from ENGINE_load_private_key()
+ * last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
+ */
+static int ssl_ui_reader(UI *ui, UI_STRING *uis)
+{
+ const char *password;
+ switch(UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ password = (const char*)UI_get0_user_data(ui);
+ if(NULL != password &&
+ UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
+ UI_set_result(ui, uis, password);
+ return 1;
+ }
+ default:
+ break;
+ }
+ return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
+}
+
+/*
+ * Suppress interactive request for a default password if available.
+ */
+static int ssl_ui_writer(UI *ui, UI_STRING *uis)
+{
+ switch(UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ if(NULL != UI_get0_user_data(ui) &&
+ UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
+ return 1;
+ }
+ default:
+ break;
+ }
+ return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
+}
+#endif
+
+static
+int cert_stuff(struct connectdata *conn,
+ SSL_CTX* ctx,
+ char *cert_file,
+ const char *cert_type,
+ char *key_file,
+ const char *key_type)
+{
+ struct SessionHandle *data = conn->data;
+
+ int file_type = do_file_type(cert_type);
+
+ if(cert_file != NULL || file_type == SSL_FILETYPE_ENGINE) {
+ SSL *ssl;
+ X509 *x509;
+ int cert_done = 0;
+
+ if(data->set.str[STRING_KEY_PASSWD]) {
+#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
+ /*
+ * If password has been given, we store that in the global
+ * area (*shudder*) for a while:
+ */
+ size_t len = strlen(data->set.str[STRING_KEY_PASSWD]);
+ if(len < sizeof(global_passwd))
+ memcpy(global_passwd, data->set.str[STRING_KEY_PASSWD], len+1);
+ else
+ global_passwd[0] = '\0';
+#else
+ /*
+ * We set the password in the callback userdata
+ */
+ SSL_CTX_set_default_passwd_cb_userdata(ctx,
+ data->set.str[STRING_KEY_PASSWD]);
+#endif
+ /* Set passwd callback: */
+ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
+ }
+
+
+#define SSL_CLIENT_CERT_ERR \
+ "unable to use client certificate (no key found or wrong pass phrase?)"
+
+ switch(file_type) {
+ case SSL_FILETYPE_PEM:
+ /* SSL_CTX_use_certificate_chain_file() only works on PEM files */
+ if(SSL_CTX_use_certificate_chain_file(ctx,
+ cert_file) != 1) {
+ failf(data, SSL_CLIENT_CERT_ERR);
+ return 0;
+ }
+ break;
+
+ case SSL_FILETYPE_ASN1:
+ /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
+ we use the case above for PEM so this can only be performed with
+ ASN1 files. */
+ if(SSL_CTX_use_certificate_file(ctx,
+ cert_file,
+ file_type) != 1) {
+ failf(data, SSL_CLIENT_CERT_ERR);
+ return 0;
+ }
+ break;
+ case SSL_FILETYPE_ENGINE:
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
+ {
+ if(data->state.engine) {
+ const char *cmd_name = "LOAD_CERT_CTRL";
+ struct {
+ const char *cert_id;
+ X509 *cert;
+ } params;
+
+ params.cert_id = cert_file;
+ params.cert = NULL;
+
+ /* Does the engine supports LOAD_CERT_CTRL ? */
+ if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
+ 0, (void *)cmd_name, NULL)) {
+ failf(data, "ssl engine does not support loading certificates");
+ return 0;
+ }
+
+ /* Load the certificate from the engine */
+ if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name,
+ 0, &params, NULL, 1)) {
+ failf(data, "ssl engine cannot load client cert with id"
+ " '%s' [%s]", cert_file,
+ ERR_error_string(ERR_get_error(), NULL));
+ return 0;
+ }
+
+ if(!params.cert) {
+ failf(data, "ssl engine didn't initialized the certificate "
+ "properly.");
+ return 0;
+ }
+
+ if(SSL_CTX_use_certificate(ctx, params.cert) != 1) {
+ failf(data, "unable to set client certificate");
+ X509_free(params.cert);
+ return 0;
+ }
+ X509_free(params.cert); /* we don't need the handle any more... */
+ }
+ else {
+ failf(data, "crypto engine not set, can't load certificate");
+ return 0;
+ }
+ }
+ break;
+#else
+ failf(data, "file type ENG for certificate not implemented");
+ return 0;
+#endif
+
+ case SSL_FILETYPE_PKCS12:
+ {
+#ifdef HAVE_PKCS12_SUPPORT
+ FILE *f;
+ PKCS12 *p12;
+ EVP_PKEY *pri;
+ STACK_OF(X509) *ca = NULL;
+ int i;
+
+ f = fopen(cert_file,"rb");
+ if(!f) {
+ failf(data, "could not open PKCS12 file '%s'", cert_file);
+ return 0;
+ }
+ p12 = d2i_PKCS12_fp(f, NULL);
+ fclose(f);
+
+ if(!p12) {
+ failf(data, "error reading PKCS12 file '%s'", cert_file );
+ return 0;
+ }
+
+ PKCS12_PBE_add();
+
+ if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
+ &ca)) {
+ failf(data,
+ "could not parse PKCS12 file, check password, OpenSSL error %s",
+ ERR_error_string(ERR_get_error(), NULL) );
+ PKCS12_free(p12);
+ return 0;
+ }
+
+ PKCS12_free(p12);
+
+ if(SSL_CTX_use_certificate(ctx, x509) != 1) {
+ failf(data, SSL_CLIENT_CERT_ERR);
+ goto fail;
+ }
+
+ if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
+ failf(data, "unable to use private key from PKCS12 file '%s'",
+ cert_file);
+ goto fail;
+ }
+
+ if(!SSL_CTX_check_private_key (ctx)) {
+ failf(data, "private key from PKCS12 file '%s' "
+ "does not match certificate in same file", cert_file);
+ goto fail;
+ }
+ /* Set Certificate Verification chain */
+ if(ca && sk_X509_num(ca)) {
+ for(i = 0; i < sk_X509_num(ca); i++) {
+ /*
+ * Note that sk_X509_pop() is used below to make sure the cert is
+ * removed from the stack properly before getting passed to
+ * SSL_CTX_add_extra_chain_cert(). Previously we used
+ * sk_X509_value() instead, but then we'd clean it in the subsequent
+ * sk_X509_pop_free() call.
+ */
+ X509 *x = sk_X509_pop(ca);
+ if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
+ failf(data, "cannot add certificate to certificate chain");
+ goto fail;
+ }
+ /* SSL_CTX_add_client_CA() seems to work with either sk_* function,
+ * presumably because it duplicates what we pass to it.
+ */
+ if(!SSL_CTX_add_client_CA(ctx, x)) {
+ failf(data, "cannot add certificate to client CA list");
+ goto fail;
+ }
+ }
+ }
+
+ cert_done = 1;
+ fail:
+ EVP_PKEY_free(pri);
+ X509_free(x509);
+ sk_X509_pop_free(ca, X509_free);
+
+ if(!cert_done)
+ return 0; /* failure! */
+ break;
+#else
+ failf(data, "file type P12 for certificate not supported");
+ return 0;
+#endif
+ }
+ default:
+ failf(data, "not supported file type '%s' for certificate", cert_type);
+ return 0;
+ }
+
+ file_type = do_file_type(key_type);
+
+ switch(file_type) {
+ case SSL_FILETYPE_PEM:
+ if(cert_done)
+ break;
+ if(key_file == NULL)
+ /* cert & key can only be in PEM case in the same file */
+ key_file=cert_file;
+ case SSL_FILETYPE_ASN1:
+ if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
+ failf(data, "unable to set private key file: '%s' type %s",
+ key_file, key_type?key_type:"PEM");
+ return 0;
+ }
+ break;
+ case SSL_FILETYPE_ENGINE:
+#ifdef HAVE_OPENSSL_ENGINE_H
+ { /* XXXX still needs some work */
+ EVP_PKEY *priv_key = NULL;
+ if(data->state.engine) {
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+ UI_METHOD *ui_method =
+ UI_create_method((char *)"cURL user interface");
+ if(NULL == ui_method) {
+ failf(data, "unable do create OpenSSL user-interface method");
+ return 0;
+ }
+ UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
+ UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
+ UI_method_set_reader(ui_method, ssl_ui_reader);
+ UI_method_set_writer(ui_method, ssl_ui_writer);
+#endif
+ /* the typecast below was added to please mingw32 */
+ priv_key = (EVP_PKEY *)
+ ENGINE_load_private_key(data->state.engine,key_file,
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+ ui_method,
+#endif
+ data->set.str[STRING_KEY_PASSWD]);
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+ UI_destroy_method(ui_method);
+#endif
+ if(!priv_key) {
+ failf(data, "failed to load private key from crypto engine");
+ return 0;
+ }
+ if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
+ failf(data, "unable to set private key");
+ EVP_PKEY_free(priv_key);
+ return 0;
+ }
+ EVP_PKEY_free(priv_key); /* we don't need the handle any more... */
+ }
+ else {
+ failf(data, "crypto engine not set, can't load private key");
+ return 0;
+ }
+ }
+ break;
+#else
+ failf(data, "file type ENG for private key not supported");
+ return 0;
+#endif
+ case SSL_FILETYPE_PKCS12:
+ if(!cert_done) {
+ failf(data, "file type P12 for private key not supported");
+ return 0;
+ }
+ break;
+ default:
+ failf(data, "not supported file type for private key");
+ return 0;
+ }
+
+ ssl=SSL_new(ctx);
+ if(NULL == ssl) {
+ failf(data,"unable to create an SSL structure");
+ return 0;
+ }
+
+ x509=SSL_get_certificate(ssl);
+
+ /* This version was provided by Evan Jordan and is supposed to not
+ leak memory as the previous version: */
+ if(x509 != NULL) {
+ EVP_PKEY *pktmp = X509_get_pubkey(x509);
+ EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl));
+ EVP_PKEY_free(pktmp);
+ }
+
+ SSL_free(ssl);
+
+ /* If we are using DSA, we can copy the parameters from
+ * the private key */
+
+
+ /* Now we know that a key and cert have been set against
+ * the SSL context */
+ if(!SSL_CTX_check_private_key(ctx)) {
+ failf(data, "Private key does not match the certificate public key");
+ return 0;
+ }
+#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
+ /* erase it now */
+ memset(global_passwd, 0, sizeof(global_passwd));
+#endif
+ }
+ return 1;
+}
+
+/* returns non-zero on failure */
+static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
+{
+#if 0
+ return X509_NAME_oneline(a, buf, size);
+#else
+ BIO *bio_out = BIO_new(BIO_s_mem());
+ BUF_MEM *biomem;
+ int rc;
+
+ if(!bio_out)
+ return 1; /* alloc failed! */
+
+ rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC);
+ BIO_get_mem_ptr(bio_out, &biomem);
+
+ if((size_t)biomem->length < size)
+ size = biomem->length;
+ else
+ size--; /* don't overwrite the buffer end */
+
+ memcpy(buf, biomem->data, size);
+ buf[size]=0;
+
+ BIO_free(bio_out);
+
+ return !rc;
+#endif
+}
+
+static
+int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+ X509 *err_cert;
+ char buf[256];
+
+ err_cert=X509_STORE_CTX_get_current_cert(ctx);
+ (void)x509_name_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
+ return ok;
+}
+
+/* Return error string for last OpenSSL error
+ */
+static char *SSL_strerror(unsigned long error, char *buf, size_t size)
+{
+#ifdef HAVE_ERR_ERROR_STRING_N
+ /* OpenSSL 0.9.6 and later has a function named
+ ERRO_error_string_n() that takes the size of the buffer as a
+ third argument */
+ ERR_error_string_n(error, buf, size);
+#else
+ (void) size;
+ ERR_error_string(error, buf);
+#endif
+ return buf;
+}
+
+#endif /* USE_SSLEAY */
+
+#ifdef USE_SSLEAY
+/**
+ * Global SSL init
+ *
+ * @retval 0 error initializing SSL
+ * @retval 1 SSL initialized successfully
+ */
+int Curl_ossl_init(void)
+{
+#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
+ ENGINE_load_builtin_engines();
+#endif
+
+ /* Lets get nice error messages */
+ SSL_load_error_strings();
+
+ /* Init the global ciphers and digests */
+ if(!SSLeay_add_ssl_algorithms())
+ return 0;
+
+ OpenSSL_add_all_algorithms();
+
+
+ /* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately
+ that function makes an exit() call on wrongly formatted config files
+ which makes it hard to use in some situations. OPENSSL_config() itself
+ calls CONF_modules_load_file() and we use that instead and we ignore
+ its return code! */
+
+ (void)CONF_modules_load_file(NULL, NULL,
+ CONF_MFLAGS_DEFAULT_SECTION|
+ CONF_MFLAGS_IGNORE_MISSING_FILE);
+
+ return 1;
+}
+
+#endif /* USE_SSLEAY */
+
+#ifdef USE_SSLEAY
+
+/* Global cleanup */
+void Curl_ossl_cleanup(void)
+{
+ /* Free ciphers and digests lists */
+ EVP_cleanup();
+
+#ifdef HAVE_ENGINE_CLEANUP
+ /* Free engine list */
+ ENGINE_cleanup();
+#endif
+
+#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
+ /* Free OpenSSL ex_data table */
+ CRYPTO_cleanup_all_ex_data();
+#endif
+
+ /* Free OpenSSL error strings */
+ ERR_free_strings();
+
+ /* Free thread local error state, destroying hash upon zero refcount */
+#ifdef HAVE_ERR_REMOVE_THREAD_STATE
+ ERR_remove_thread_state(NULL);
+#else
+ ERR_remove_state(0);
+#endif
+}
+
+/*
+ * This function uses SSL_peek to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+int Curl_ossl_check_cxn(struct connectdata *conn)
+{
+ int rc;
+ char buf;
+
+ rc = SSL_peek(conn->ssl[FIRSTSOCKET].handle, (void*)&buf, 1);
+ if(rc > 0)
+ return 1; /* connection still in place */
+
+ if(rc == 0)
+ return 0; /* connection has been closed */
+
+ return -1; /* connection status unknown */
+}
+
+/* Selects an OpenSSL crypto engine
+ */
+CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine)
+{
+#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
+ ENGINE *e;
+
+#if OPENSSL_VERSION_NUMBER >= 0x00909000L
+ e = ENGINE_by_id(engine);
+#else
+ /* avoid memory leak */
+ for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
+ const char *e_id = ENGINE_get_id(e);
+ if(!strcmp(engine, e_id))
+ break;
+ }
+#endif
+
+ if(!e) {
+ failf(data, "SSL Engine '%s' not found", engine);
+ return CURLE_SSL_ENGINE_NOTFOUND;
+ }
+
+ if(data->state.engine) {
+ ENGINE_finish(data->state.engine);
+ ENGINE_free(data->state.engine);
+ data->state.engine = NULL;
+ }
+ if(!ENGINE_init(e)) {
+ char buf[256];
+
+ ENGINE_free(e);
+ failf(data, "Failed to initialise SSL Engine '%s':\n%s",
+ engine, SSL_strerror(ERR_get_error(), buf, sizeof(buf)));
+ return CURLE_SSL_ENGINE_INITFAILED;
+ }
+ data->state.engine = e;
+ return CURLE_OK;
+#else
+ (void)engine;
+ failf(data, "SSL Engine not supported");
+ return CURLE_SSL_ENGINE_NOTFOUND;
+#endif
+}
+
+/* Sets engine as default for all SSL operations
+ */
+CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data)
+{
+#ifdef HAVE_OPENSSL_ENGINE_H
+ if(data->state.engine) {
+ if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
+ infof(data,"set default crypto engine '%s'\n",
+ ENGINE_get_id(data->state.engine));
+ }
+ else {
+ failf(data, "set default crypto engine '%s' failed",
+ ENGINE_get_id(data->state.engine));
+ return CURLE_SSL_ENGINE_SETFAILED;
+ }
+ }
+#else
+ (void) data;
+#endif
+ return CURLE_OK;
+}
+
+/* Return list of OpenSSL crypto engine names.
+ */
+struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
+{
+ struct curl_slist *list = NULL;
+#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
+ struct curl_slist *beg;
+ ENGINE *e;
+
+ for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
+ beg = curl_slist_append(list, ENGINE_get_id(e));
+ if(!beg) {
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ list = beg;
+ }
+#endif
+ (void) data;
+ return list;
+}
+
+
+/*
+ * This function is called when an SSL connection is closed.
+ */
+void Curl_ossl_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->handle) {
+ (void)SSL_shutdown(connssl->handle);
+ SSL_set_connect_state(connssl->handle);
+
+ SSL_free (connssl->handle);
+ connssl->handle = NULL;
+ }
+ if(connssl->ctx) {
+ SSL_CTX_free (connssl->ctx);
+ connssl->ctx = NULL;
+ }
+}
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
+{
+ int retval = 0;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
+ to be at least 120 bytes long. */
+ unsigned long sslerror;
+ ssize_t nread;
+ int buffsize;
+ int err;
+ int done = 0;
+
+ /* This has only been tested on the proftpd server, and the mod_tls code
+ sends a close notify alert without waiting for a close notify alert in
+ response. Thus we wait for a close notify alert from the server, but
+ we do not send one. Let's hope other servers do the same... */
+
+ if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
+ (void)SSL_shutdown(connssl->handle);
+
+ if(connssl->handle) {
+ buffsize = (int)sizeof(buf);
+ while(!done) {
+ int what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+ if(what > 0) {
+ ERR_clear_error();
+
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server */
+ nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf,
+ buffsize);
+ err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread);
+
+ switch(err) {
+ case SSL_ERROR_NONE: /* this is not an error */
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ /* This is the expected response. There was no data but only
+ the close notify alert */
+ done = 1;
+ break;
+ case SSL_ERROR_WANT_READ:
+ /* there's data pending, re-invoke SSL_read() */
+ infof(data, "SSL_ERROR_WANT_READ\n");
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ /* SSL wants a write. Really odd. Let's bail out. */
+ infof(data, "SSL_ERROR_WANT_WRITE\n");
+ done = 1;
+ break;
+ default:
+ /* openssl/ssl.h says "look at error stack/return value/errno" */
+ sslerror = ERR_get_error();
+ failf(conn->data, "SSL read: %s, errno %d",
+ ERR_error_string(sslerror, buf),
+ SOCKERRNO);
+ done = 1;
+ break;
+ }
+ }
+ else if(0 == what) {
+ /* timeout */
+ failf(data, "SSL shutdown timeout");
+ done = 1;
+ }
+ else {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ retval = -1;
+ done = 1;
+ }
+ } /* while()-loop for the select() */
+
+ if(data->set.verbose) {
+#ifdef HAVE_SSL_GET_SHUTDOWN
+ switch(SSL_get_shutdown(connssl->handle)) {
+ case SSL_SENT_SHUTDOWN:
+ infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
+ break;
+ case SSL_RECEIVED_SHUTDOWN:
+ infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n");
+ break;
+ case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN:
+ infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|"
+ "SSL_RECEIVED__SHUTDOWN\n");
+ break;
+ }
+#endif
+ }
+
+ SSL_free (connssl->handle);
+ connssl->handle = NULL;
+ }
+ return retval;
+}
+
+void Curl_ossl_session_free(void *ptr)
+{
+ /* free the ID */
+ SSL_SESSION_free(ptr);
+}
+
+/*
+ * This function is called when the 'data' struct is going away. Close
+ * down everything and free all resources!
+ */
+int Curl_ossl_close_all(struct SessionHandle *data)
+{
+#ifdef HAVE_OPENSSL_ENGINE_H
+ if(data->state.engine) {
+ ENGINE_finish(data->state.engine);
+ ENGINE_free(data->state.engine);
+ data->state.engine = NULL;
+ }
+#else
+ (void)data;
+#endif
+ return 0;
+}
+
+static int asn1_output(const ASN1_UTCTIME *tm,
+ char *buf,
+ size_t sizeofbuf)
+{
+ const char *asn1_string;
+ int gmt=FALSE;
+ int i;
+ int year=0,month=0,day=0,hour=0,minute=0,second=0;
+
+ i=tm->length;
+ asn1_string=(const char *)tm->data;
+
+ if(i < 10)
+ return 1;
+ if(asn1_string[i-1] == 'Z')
+ gmt=TRUE;
+ for(i=0; i<10; i++)
+ if((asn1_string[i] > '9') || (asn1_string[i] < '0'))
+ return 2;
+
+ year= (asn1_string[0]-'0')*10+(asn1_string[1]-'0');
+ if(year < 50)
+ year+=100;
+
+ month= (asn1_string[2]-'0')*10+(asn1_string[3]-'0');
+ if((month > 12) || (month < 1))
+ return 3;
+
+ day= (asn1_string[4]-'0')*10+(asn1_string[5]-'0');
+ hour= (asn1_string[6]-'0')*10+(asn1_string[7]-'0');
+ minute= (asn1_string[8]-'0')*10+(asn1_string[9]-'0');
+
+ if((asn1_string[10] >= '0') && (asn1_string[10] <= '9') &&
+ (asn1_string[11] >= '0') && (asn1_string[11] <= '9'))
+ second= (asn1_string[10]-'0')*10+(asn1_string[11]-'0');
+
+ snprintf(buf, sizeofbuf,
+ "%04d-%02d-%02d %02d:%02d:%02d %s",
+ year+1900, month, day, hour, minute, second, (gmt?"GMT":""));
+
+ return 0;
+}
+
+/* ====================================================== */
+
+
+/* Quote from RFC2818 section 3.1 "Server Identity"
+
+ If a subjectAltName extension of type dNSName is present, that MUST
+ be used as the identity. Otherwise, the (most specific) Common Name
+ field in the Subject field of the certificate MUST be used. Although
+ the use of the Common Name is existing practice, it is deprecated and
+ Certification Authorities are encouraged to use the dNSName instead.
+
+ Matching is performed using the matching rules specified by
+ [RFC2459]. If more than one identity of a given type is present in
+ the certificate (e.g., more than one dNSName name, a match in any one
+ of the set is considered acceptable.) Names may contain the wildcard
+ character * which is considered to match any single domain name
+ component or component fragment. E.g., *.a.com matches foo.a.com but
+ not bar.foo.a.com. f*.com matches foo.com but not bar.com.
+
+ In some cases, the URI is specified as an IP address rather than a
+ hostname. In this case, the iPAddress subjectAltName must be present
+ in the certificate and must exactly match the IP in the URI.
+
+*/
+static CURLcode verifyhost(struct connectdata *conn,
+ X509 *server_cert)
+{
+ int matched = -1; /* -1 is no alternative match yet, 1 means match and 0
+ means mismatch */
+ int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
+ size_t addrlen = 0;
+ struct SessionHandle *data = conn->data;
+ STACK_OF(GENERAL_NAME) *altnames;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ CURLcode res = CURLE_OK;
+
+#ifdef ENABLE_IPV6
+ if(conn->bits.ipv6_ip &&
+ Curl_inet_pton(AF_INET6, conn->host.name, &addr)) {
+ target = GEN_IPADD;
+ addrlen = sizeof(struct in6_addr);
+ }
+ else
+#endif
+ if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) {
+ target = GEN_IPADD;
+ addrlen = sizeof(struct in_addr);
+ }
+
+ /* get a "list" of alternative names */
+ altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
+
+ if(altnames) {
+ int numalts;
+ int i;
+
+ /* get amount of alternatives, RFC2459 claims there MUST be at least
+ one, but we don't depend on it... */
+ numalts = sk_GENERAL_NAME_num(altnames);
+
+ /* loop through all alternatives while none has matched */
+ for(i=0; (i<numalts) && (matched != 1); i++) {
+ /* get a handle to alternative name number i */
+ const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
+
+ /* only check alternatives of the same type the target is */
+ if(check->type == target) {
+ /* get data and length */
+ const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
+ size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
+
+ switch(target) {
+ case GEN_DNS: /* name/pattern comparison */
+ /* The OpenSSL man page explicitly says: "In general it cannot be
+ assumed that the data returned by ASN1_STRING_data() is null
+ terminated or does not contain embedded nulls." But also that
+ "The actual format of the data will depend on the actual string
+ type itself: for example for and IA5String the data will be ASCII"
+
+ Gisle researched the OpenSSL sources:
+ "I checked the 0.9.6 and 0.9.8 sources before my patch and
+ it always 0-terminates an IA5String."
+ */
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ Curl_cert_hostcheck(altptr, conn->host.name))
+ matched = 1;
+ else
+ matched = 0;
+ break;
+
+ case GEN_IPADD: /* IP address comparison */
+ /* compare alternative IP address if the data chunk is the same size
+ our server IP address is */
+ if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
+ matched = 1;
+ else
+ matched = 0;
+ break;
+ }
+ }
+ }
+ GENERAL_NAMES_free(altnames);
+ }
+
+ if(matched == 1)
+ /* an alternative name matched the server hostname */
+ infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
+ else if(matched == 0) {
+ /* an alternative name field existed, but didn't match and then
+ we MUST fail */
+ infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
+ failf(data, "SSL: no alternative certificate subject name matches "
+ "target host name '%s'", conn->host.dispname);
+ res = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else {
+ /* we have to look to the last occurrence of a commonName in the
+ distinguished one to get the most significant one. */
+ int j,i=-1 ;
+
+/* The following is done because of a bug in 0.9.6b */
+
+ unsigned char *nulstr = (unsigned char *)"";
+ unsigned char *peer_CN = nulstr;
+
+ X509_NAME *name = X509_get_subject_name(server_cert) ;
+ if(name)
+ while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i))>=0)
+ i=j;
+
+ /* we have the name entry and we will now convert this to a string
+ that we can use for comparison. Doing this we support BMPstring,
+ UTF8 etc. */
+
+ if(i>=0) {
+ ASN1_STRING *tmp = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
+
+ /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
+ is already UTF-8 encoded. We check for this case and copy the raw
+ string manually to avoid the problem. This code can be made
+ conditional in the future when OpenSSL has been fixed. Work-around
+ brought by Alexis S. L. Carvalho. */
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
+ }
+ }
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && (curlx_uztosi(strlen((char *)peer_CN)) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ res = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ }
+
+ if(peer_CN == nulstr)
+ peer_CN = NULL;
+ else {
+ /* convert peer_CN from UTF8 */
+ CURLcode rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN));
+ /* Curl_convert_from_utf8 calls failf if unsuccessful */
+ if(rc) {
+ OPENSSL_free(peer_CN);
+ return rc;
+ }
+ }
+
+ if(res)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
+ failf(data,
+ "SSL: unable to obtain common name from peer certificate");
+ res = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
+ failf(data, "SSL: certificate subject name '%s' does not match "
+ "target host name '%s'", peer_CN, conn->host.dispname);
+ res = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else {
+ infof(data, "\t common name: %s (matched)\n", peer_CN);
+ }
+ if(peer_CN)
+ OPENSSL_free(peer_CN);
+ }
+ return res;
+}
+#endif /* USE_SSLEAY */
+
+/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions
+ and thus this cannot be done there. */
+#ifdef SSL_CTRL_SET_MSG_CALLBACK
+
+static const char *ssl_msg_type(int ssl_ver, int msg)
+{
+ if(ssl_ver == SSL2_VERSION_MAJOR) {
+ switch (msg) {
+ case SSL2_MT_ERROR:
+ return "Error";
+ case SSL2_MT_CLIENT_HELLO:
+ return "Client hello";
+ case SSL2_MT_CLIENT_MASTER_KEY:
+ return "Client key";
+ case SSL2_MT_CLIENT_FINISHED:
+ return "Client finished";
+ case SSL2_MT_SERVER_HELLO:
+ return "Server hello";
+ case SSL2_MT_SERVER_VERIFY:
+ return "Server verify";
+ case SSL2_MT_SERVER_FINISHED:
+ return "Server finished";
+ case SSL2_MT_REQUEST_CERTIFICATE:
+ return "Request CERT";
+ case SSL2_MT_CLIENT_CERTIFICATE:
+ return "Client CERT";
+ }
+ }
+ else if(ssl_ver == SSL3_VERSION_MAJOR) {
+ switch (msg) {
+ case SSL3_MT_HELLO_REQUEST:
+ return "Hello request";
+ case SSL3_MT_CLIENT_HELLO:
+ return "Client hello";
+ case SSL3_MT_SERVER_HELLO:
+ return "Server hello";
+ case SSL3_MT_CERTIFICATE:
+ return "CERT";
+ case SSL3_MT_SERVER_KEY_EXCHANGE:
+ return "Server key exchange";
+ case SSL3_MT_CLIENT_KEY_EXCHANGE:
+ return "Client key exchange";
+ case SSL3_MT_CERTIFICATE_REQUEST:
+ return "Request CERT";
+ case SSL3_MT_SERVER_DONE:
+ return "Server finished";
+ case SSL3_MT_CERTIFICATE_VERIFY:
+ return "CERT verify";
+ case SSL3_MT_FINISHED:
+ return "Finished";
+ }
+ }
+ return "Unknown";
+}
+
+static const char *tls_rt_type(int type)
+{
+ return (
+ type == SSL3_RT_CHANGE_CIPHER_SPEC ? "TLS change cipher, " :
+ type == SSL3_RT_ALERT ? "TLS alert, " :
+ type == SSL3_RT_HANDSHAKE ? "TLS handshake, " :
+ type == SSL3_RT_APPLICATION_DATA ? "TLS app data, " :
+ "TLS Unknown, ");
+}
+
+
+/*
+ * Our callback from the SSL/TLS layers.
+ */
+static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
+ const void *buf, size_t len, const SSL *ssl,
+ struct connectdata *conn)
+{
+ struct SessionHandle *data;
+ const char *msg_name, *tls_rt_name;
+ char ssl_buf[1024];
+ int ver, msg_type, txt_len;
+
+ if(!conn || !conn->data || !conn->data->set.fdebug ||
+ (direction != 0 && direction != 1))
+ return;
+
+ data = conn->data;
+ ssl_ver >>= 8;
+ ver = (ssl_ver == SSL2_VERSION_MAJOR ? '2' :
+ ssl_ver == SSL3_VERSION_MAJOR ? '3' : '?');
+
+ /* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL
+ * always pass-up content-type as 0. But the interesting message-type
+ * is at 'buf[0]'.
+ */
+ if(ssl_ver == SSL3_VERSION_MAJOR && content_type != 0)
+ tls_rt_name = tls_rt_type(content_type);
+ else
+ tls_rt_name = "";
+
+ msg_type = *(char*)buf;
+ msg_name = ssl_msg_type(ssl_ver, msg_type);
+
+ txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "SSLv%c, %s%s (%d):\n",
+ ver, tls_rt_name, msg_name, msg_type);
+ Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+
+ Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
+ CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL);
+ (void) ssl;
+}
+#endif
+
+#ifdef USE_SSLEAY
+/* ====================================================== */
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+# define use_sni(x) sni = (x)
+#else
+# define use_sni(x) Curl_nop_stmt
+#endif
+
+#ifdef USE_NGHTTP2
+
+#undef HAS_ALPN
+#if defined(HAVE_SSL_CTX_SET_ALPN_PROTOS) && \
+ defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
+# define HAS_ALPN 1
+#endif
+
+#if !defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || \
+ defined(OPENSSL_NO_NEXTPROTONEG)
+# if !defined(HAS_ALPN)
+# error http2 builds require OpenSSL with NPN or ALPN support
+# endif
+#endif
+
+
+/*
+ * in is a list of lenght prefixed strings. this function has to select
+ * the protocol we want to use from the list and write its string into out.
+ */
+static int
+select_next_proto_cb(SSL *ssl,
+ unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen,
+ void *arg)
+{
+ struct connectdata *conn = (struct connectdata*) arg;
+ int retval = nghttp2_select_next_protocol(out, outlen, in, inlen);
+ (void)ssl;
+
+ if(retval == 1) {
+ infof(conn->data, "NPN, negotiated HTTP2 (%s)\n",
+ NGHTTP2_PROTO_VERSION_ID);
+ conn->negnpn = NPN_HTTP2;
+ }
+ else if(retval == 0) {
+ infof(conn->data, "NPN, negotiated HTTP1.1\n");
+ conn->negnpn = NPN_HTTP1_1;
+ }
+ else {
+ infof(conn->data, "NPN, no overlap, use HTTP1.1\n",
+ NGHTTP2_PROTO_VERSION_ID);
+ *out = (unsigned char*)"http/1.1";
+ *outlen = sizeof("http/1.1") - 1;
+ conn->negnpn = NPN_HTTP1_1;
+ }
+
+ return SSL_TLSEXT_ERR_OK;
+}
+#endif
+
+static const char *
+get_ssl_version_txt(SSL_SESSION *session)
+{
+ if(NULL == session)
+ return "";
+
+ switch(session->ssl_version) {
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ case TLS1_2_VERSION:
+ return "TLSv1.2";
+ case TLS1_1_VERSION:
+ return "TLSv1.1";
+#endif
+ case TLS1_VERSION:
+ return "TLSv1.0";
+ case SSL3_VERSION:
+ return "SSLv3";
+ case SSL2_VERSION:
+ return "SSLv2";
+ }
+ return "unknown";
+}
+
+
+static CURLcode
+ossl_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode = CURLE_OK;
+ char *ciphers;
+ struct SessionHandle *data = conn->data;
+ SSL_METHOD_QUAL SSL_METHOD *req_method=NULL;
+ void *ssl_sessionid=NULL;
+ X509_LOOKUP *lookup=NULL;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ long ctx_options;
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ bool sni;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+#endif
+#ifdef HAS_ALPN
+ unsigned char protocols[128];
+#endif
+
+ DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
+
+ /* Make funny stuff to get random input */
+ Curl_ossl_seed(data);
+
+ data->set.ssl.certverifyresult = !X509_V_OK;
+
+ /* check to see if we've been told to use an explicit SSL/TLS version */
+
+ switch(data->set.ssl.version) {
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1_1:
+ case CURL_SSLVERSION_TLSv1_2:
+ /* it will be handled later with the context options */
+ req_method = SSLv23_client_method();
+ use_sni(TRUE);
+ break;
+ case CURL_SSLVERSION_SSLv2:
+#ifdef OPENSSL_NO_SSL2
+ failf(data, "OpenSSL was built without SSLv2 support");
+ return CURLE_NOT_BUILT_IN;
+#else
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+ return CURLE_SSL_CONNECT_ERROR;
+#endif
+ req_method = SSLv2_client_method();
+ use_sni(FALSE);
+ break;
+#endif
+ case CURL_SSLVERSION_SSLv3:
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+ return CURLE_SSL_CONNECT_ERROR;
+#endif
+ req_method = SSLv3_client_method();
+ use_sni(FALSE);
+ break;
+ }
+
+ if(connssl->ctx)
+ SSL_CTX_free(connssl->ctx);
+ connssl->ctx = SSL_CTX_new(req_method);
+
+ if(!connssl->ctx) {
+ failf(data, "SSL: couldn't create a context: %s",
+ ERR_error_string(ERR_peek_error(), NULL));
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifdef SSL_MODE_RELEASE_BUFFERS
+ SSL_CTX_set_mode(connssl->ctx, SSL_MODE_RELEASE_BUFFERS);
+#endif
+
+#ifdef SSL_CTRL_SET_MSG_CALLBACK
+ if(data->set.fdebug && data->set.verbose) {
+ /* the SSL trace callback is only used for verbose logging so we only
+ inform about failures of setting it */
+ if(!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK,
+ (void (*)(void))ssl_tls_trace)) {
+ infof(data, "SSL: couldn't set callback!\n");
+ }
+ else if(!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0,
+ conn)) {
+ infof(data, "SSL: couldn't set callback argument!\n");
+ }
+ }
+#endif
+
+ /* OpenSSL contains code to work-around lots of bugs and flaws in various
+ SSL-implementations. SSL_CTX_set_options() is used to enabled those
+ work-arounds. The man page for this option states that SSL_OP_ALL enables
+ all the work-arounds and that "It is usually safe to use SSL_OP_ALL to
+ enable the bug workaround options if compatibility with somewhat broken
+ implementations is desired."
+
+ The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to
+ disable "rfc4507bis session ticket support". rfc4507bis was later turned
+ into the proper RFC5077 it seems: http://tools.ietf.org/html/rfc5077
+
+ The enabled extension concerns the session management. I wonder how often
+ libcurl stops a connection and then resumes a TLS session. also, sending
+ the session data is some overhead. .I suggest that you just use your
+ proposed patch (which explicitly disables TICKET).
+
+ If someone writes an application with libcurl and openssl who wants to
+ enable the feature, one can do this in the SSL callback.
+
+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper
+ interoperability with web server Netscape Enterprise Server 2.0.1 which
+ was released back in 1996.
+
+ Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has
+ become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate
+ CVE-2010-4180 when using previous OpenSSL versions we no longer enable
+ this option regardless of OpenSSL version and SSL_OP_ALL definition.
+
+ OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability
+ (http://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to
+ SSL_OP_ALL that _disables_ that work-around despite the fact that
+ SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to
+ keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit
+ must not be set.
+ */
+
+ ctx_options = SSL_OP_ALL;
+
+#ifdef SSL_OP_NO_TICKET
+ ctx_options |= SSL_OP_NO_TICKET;
+#endif
+
+#ifdef SSL_OP_NO_COMPRESSION
+ ctx_options |= SSL_OP_NO_COMPRESSION;
+#endif
+
+#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
+ /* mitigate CVE-2010-4180 */
+ ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
+#endif
+
+#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
+ /* unless the user explicitly ask to allow the protocol vulnerability we
+ use the work-around */
+ if(!conn->data->set.ssl_enable_beast)
+ ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+#endif
+
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ ctx_options |= SSL_OP_NO_SSLv2;
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ infof(data, "Set version TLSv1.x for SRP authorisation\n");
+ ctx_options |= SSL_OP_NO_SSLv3;
+ }
+#endif
+ break;
+
+ case CURL_SSLVERSION_SSLv3:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_TLSv1;
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+ break;
+
+ case CURL_SSLVERSION_TLSv1:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+ break;
+
+ case CURL_SSLVERSION_TLSv1_0:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+ break;
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ case CURL_SSLVERSION_TLSv1_1:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+ ctx_options |= SSL_OP_NO_TLSv1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+ break;
+
+ case CURL_SSLVERSION_TLSv1_2:
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+ ctx_options |= SSL_OP_NO_TLSv1;
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ break;
+#endif
+
+#ifndef OPENSSL_NO_SSL2
+ case CURL_SSLVERSION_SSLv2:
+ ctx_options |= SSL_OP_NO_SSLv3;
+ ctx_options |= SSL_OP_NO_TLSv1;
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+ break;
+#endif
+
+ default:
+ failf(data, "Unsupported SSL protocol version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ SSL_CTX_set_options(connssl->ctx, ctx_options);
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+ if(data->set.ssl_enable_npn) {
+ SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb,
+ conn);
+ }
+
+#ifdef HAS_ALPN
+ if(data->set.ssl_enable_alpn) {
+ protocols[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
+ memcpy(&protocols[1], NGHTTP2_PROTO_VERSION_ID,
+ NGHTTP2_PROTO_VERSION_ID_LEN);
+
+ protocols[NGHTTP2_PROTO_VERSION_ID_LEN+1] = ALPN_HTTP_1_1_LENGTH;
+ memcpy(&protocols[NGHTTP2_PROTO_VERSION_ID_LEN+2], ALPN_HTTP_1_1,
+ ALPN_HTTP_1_1_LENGTH);
+
+ /* expects length prefixed preference ordered list of protocols in wire
+ * format
+ */
+ SSL_CTX_set_alpn_protos(connssl->ctx, protocols,
+ NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH + 2);
+
+ infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
+ ALPN_HTTP_1_1);
+ }
+#endif
+ }
+#endif
+
+ if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
+ if(!cert_stuff(conn,
+ connssl->ctx,
+ data->set.str[STRING_CERT],
+ data->set.str[STRING_CERT_TYPE],
+ data->set.str[STRING_KEY],
+ data->set.str[STRING_KEY_TYPE])) {
+ /* failf() is already done in cert_stuff() */
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ ciphers = data->set.str[STRING_SSL_CIPHER_LIST];
+ if(!ciphers)
+ ciphers = (char *)DEFAULT_CIPHER_SELECTION;
+ if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
+ failf(data, "failed setting cipher list: %s", ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+
+#ifdef USE_TLS_SRP
+ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+ infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+
+ if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) {
+ failf(data, "Unable to set SRP user name");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ if(!SSL_CTX_set_srp_password(connssl->ctx,data->set.ssl.password)) {
+ failf(data, "failed setting SRP password");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ if(!data->set.str[STRING_SSL_CIPHER_LIST]) {
+ infof(data, "Setting cipher list SRP\n");
+
+ if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
+ failf(data, "failed setting SRP cipher list");
+ return CURLE_SSL_CIPHER;
+ }
+ }
+ }
+#endif
+ if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
+ /* tell SSL where to find CA certificates that are used to verify
+ the servers certificate. */
+ if(!SSL_CTX_load_verify_locations(connssl->ctx,
+ data->set.str[STRING_SSL_CAFILE],
+ data->set.str[STRING_SSL_CAPATH])) {
+ if(data->set.ssl.verifypeer) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data,"error setting certificate verify locations:\n"
+ " CAfile: %s\n CApath: %s",
+ data->set.str[STRING_SSL_CAFILE]?
+ data->set.str[STRING_SSL_CAFILE]: "none",
+ data->set.str[STRING_SSL_CAPATH]?
+ data->set.str[STRING_SSL_CAPATH] : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Just continue with a warning if no strict certificate verification
+ is required. */
+ infof(data, "error setting certificate verify locations,"
+ " continuing anyway:\n");
+ }
+ }
+ else {
+ /* Everything is fine. */
+ infof(data, "successfully set certificate verify locations:\n");
+ }
+ infof(data,
+ " CAfile: %s\n"
+ " CApath: %s\n",
+ data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
+ "none",
+ data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
+ "none");
+ }
+
+ if(data->set.str[STRING_SSL_CRLFILE]) {
+ /* tell SSL where to find CRL file that is used to check certificate
+ * revocation */
+ lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
+ X509_LOOKUP_file());
+ if(!lookup ||
+ (!X509_load_crl_file(lookup,data->set.str[STRING_SSL_CRLFILE],
+ X509_FILETYPE_PEM)) ) {
+ failf(data,"error loading CRL file: %s",
+ data->set.str[STRING_SSL_CRLFILE]);
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ else {
+ /* Everything is fine. */
+ infof(data, "successfully load CRL file:\n");
+ X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+ }
+ infof(data,
+ " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ?
+ data->set.str[STRING_SSL_CRLFILE]: "none");
+ }
+
+ /* SSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+ * anyway. In the latter case the result of the verification is checked with
+ * SSL_get_verify_result() below. */
+ SSL_CTX_set_verify(connssl->ctx,
+ data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
+ cert_verify_callback);
+
+ /* give application a chance to interfere with SSL set up. */
+ if(data->set.ssl.fsslctx) {
+ retcode = (*data->set.ssl.fsslctx)(data, connssl->ctx,
+ data->set.ssl.fsslctxp);
+ if(retcode) {
+ failf(data,"error signaled by ssl ctx callback");
+ return retcode;
+ }
+ }
+
+ /* Lets make an SSL structure */
+ if(connssl->handle)
+ SSL_free(connssl->handle);
+ connssl->handle = SSL_new(connssl->ctx);
+ if(!connssl->handle) {
+ failf(data, "SSL: couldn't create a context (handle)!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ SSL_set_connect_state(connssl->handle);
+
+ connssl->server_cert = 0x0;
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+#ifdef ENABLE_IPV6
+ (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+#endif
+ sni &&
+ !SSL_set_tlsext_host_name(connssl->handle, conn->host.name))
+ infof(data, "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+#endif
+
+ /* Check if there's a cached ID we can/should use here! */
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+ /* we got a session id, use it! */
+ if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
+ failf(data, "SSL: SSL_set_session failed: %s",
+ ERR_error_string(ERR_get_error(),NULL));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof (data, "SSL re-using session ID\n");
+ }
+
+ /* pass the raw socket into the SSL layers */
+ if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+ failf(data, "SSL: SSL_set_fd failed: %s",
+ ERR_error_string(ERR_get_error(),NULL));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+}
+
+static CURLcode
+ossl_connect_step2(struct connectdata *conn, int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ int err;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
+ || ssl_connect_2_reading == connssl->connecting_state
+ || ssl_connect_2_writing == connssl->connecting_state);
+
+ ERR_clear_error();
+
+ err = SSL_connect(connssl->handle);
+
+ /* 1 is fine
+ 0 is "not successful but was shut down controlled"
+ <0 is "handshake was not successful, because a fatal error occurred" */
+ if(1 != err) {
+ int detail = SSL_get_error(connssl->handle, err);
+
+ if(SSL_ERROR_WANT_READ == detail) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+ else if(SSL_ERROR_WANT_WRITE == detail) {
+ connssl->connecting_state = ssl_connect_2_writing;
+ return CURLE_OK;
+ }
+ else {
+ /* untreated error */
+ unsigned long errdetail;
+ char error_buffer[256]; /* OpenSSL documents that this must be at least
+ 256 bytes long. */
+ CURLcode rc;
+ const char *cert_problem = NULL;
+ long lerr;
+
+ connssl->connecting_state = ssl_connect_2; /* the connection failed,
+ we're not waiting for
+ anything else. */
+
+ errdetail = ERR_get_error(); /* Gets the earliest error code from the
+ thread's error queue and removes the
+ entry. */
+
+ switch(errdetail) {
+ case 0x1407E086:
+ /* 1407E086:
+ SSL routines:
+ SSL2_SET_CERTIFICATE:
+ certificate verify failed */
+ /* fall-through */
+ case 0x14090086:
+ /* 14090086:
+ SSL routines:
+ SSL3_GET_SERVER_CERTIFICATE:
+ certificate verify failed */
+ rc = CURLE_SSL_CACERT;
+
+ lerr = SSL_get_verify_result(connssl->handle);
+ if(lerr != X509_V_OK) {
+ snprintf(error_buffer, sizeof(error_buffer),
+ "SSL certificate problem: %s",
+ X509_verify_cert_error_string(lerr));
+ }
+ else
+ cert_problem = "SSL certificate problem, verify that the CA cert is"
+ " OK.";
+
+ break;
+ default:
+ rc = CURLE_SSL_CONNECT_ERROR;
+ SSL_strerror(errdetail, error_buffer, sizeof(error_buffer));
+ break;
+ }
+
+ /* detail is already set to the SSL error above */
+
+ /* If we e.g. use SSLv2 request-method and the server doesn't like us
+ * (RST connection etc.), OpenSSL gives no explanation whatsoever and
+ * the SO_ERROR is also lost.
+ */
+ if(CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
+ failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
+ conn->host.name, conn->remote_port);
+ return rc;
+ }
+ /* Could be a CERT problem */
+
+ failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer);
+ return rc;
+ }
+ }
+ else {
+ /* we have been connected fine, we're not waiting for anything else. */
+ connssl->connecting_state = ssl_connect_3;
+
+ /* Informational message */
+ infof (data, "SSL connection using %s / %s\n",
+ get_ssl_version_txt(SSL_get_session(connssl->handle)),
+ SSL_get_cipher(connssl->handle));
+
+#ifdef HAS_ALPN
+ /* Sets data and len to negotiated protocol, len is 0 if no protocol was
+ * negotiated
+ */
+ if(data->set.ssl_enable_alpn) {
+ const unsigned char* neg_protocol;
+ unsigned int len;
+ SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
+ if(len != 0) {
+ infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
+
+ if(len == NGHTTP2_PROTO_VERSION_ID_LEN &&
+ memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len) == 0) {
+ conn->negnpn = NPN_HTTP2;
+ }
+ else if(len == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
+ neg_protocol, ALPN_HTTP_1_1_LENGTH) == 0) {
+ conn->negnpn = NPN_HTTP1_1;
+ }
+ }
+ else {
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ }
+ }
+#endif
+
+ return CURLE_OK;
+ }
+}
+
+static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
+{
+ int i, ilen;
+
+ if((ilen = (int)len) < 0)
+ return 1; /* buffer too big */
+
+ i = i2t_ASN1_OBJECT(buf, ilen, a);
+
+ if(i >= ilen)
+ return 1; /* buffer too small */
+
+ return 0;
+}
+
+static void pubkey_show(struct SessionHandle *data,
+ int num,
+ const char *type,
+ const char *name,
+ unsigned char *raw,
+ int len)
+{
+ size_t left;
+ int i;
+ char namebuf[32];
+ char *buffer;
+
+ left = len*3 + 1;
+ buffer = malloc(left);
+ if(buffer) {
+ char *ptr=buffer;
+ snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
+ for(i=0; i< len; i++) {
+ snprintf(ptr, left, "%02x:", raw[i]);
+ ptr += 3;
+ left -= 3;
+ }
+ infof(data, " %s: %s\n", namebuf, buffer);
+ Curl_ssl_push_certinfo(data, num, namebuf, buffer);
+ free(buffer);
+ }
+}
+
+#define print_pubkey_BN(_type, _name, _num) \
+do { \
+ if(pubkey->pkey._type->_name != NULL) { \
+ int len = BN_num_bytes(pubkey->pkey._type->_name); \
+ if(len < CERTBUFFERSIZE) { \
+ BN_bn2bin(pubkey->pkey._type->_name, (unsigned char*)bufp); \
+ bufp[len] = 0; \
+ pubkey_show(data, _num, #_type, #_name, (unsigned char*)bufp, len); \
+ } \
+ } \
+} WHILE_FALSE
+
+static int X509V3_ext(struct SessionHandle *data,
+ int certnum,
+ STACK_OF(X509_EXTENSION) *exts)
+{
+ int i;
+ size_t j;
+
+ if(sk_X509_EXTENSION_num(exts) <= 0)
+ /* no extensions, bail out */
+ return 1;
+
+ for(i=0; i<sk_X509_EXTENSION_num(exts); i++) {
+ ASN1_OBJECT *obj;
+ X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+ BUF_MEM *biomem;
+ char buf[512];
+ char *ptr=buf;
+ char namebuf[128];
+ BIO *bio_out = BIO_new(BIO_s_mem());
+
+ if(!bio_out)
+ return 1;
+
+ obj = X509_EXTENSION_get_object(ext);
+
+ asn1_object_dump(obj, namebuf, sizeof(namebuf));
+
+ infof(data, "%s: %s\n", namebuf,
+ X509_EXTENSION_get_critical(ext)?"(critical)":"");
+
+ if(!X509V3_EXT_print(bio_out, ext, 0, 0))
+ M_ASN1_OCTET_STRING_print(bio_out, ext->value);
+
+ BIO_get_mem_ptr(bio_out, &biomem);
+
+ /* biomem->length bytes at biomem->data, this little loop here is only
+ done for the infof() call, we send the "raw" data to the certinfo
+ function */
+ for(j=0; j<(size_t)biomem->length; j++) {
+ const char *sep="";
+ if(biomem->data[j] == '\n') {
+ sep=", ";
+ j++; /* skip the newline */
+ };
+ while((j<(size_t)biomem->length) && (biomem->data[j] == ' '))
+ j++;
+ if(j<(size_t)biomem->length)
+ ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
+ biomem->data[j]);
+ }
+ infof(data, " %s\n", buf);
+
+ Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
+
+ BIO_free(bio_out);
+
+ }
+ return 0; /* all is fine */
+}
+
+
+static void X509_signature(struct SessionHandle *data,
+ int numcert,
+ ASN1_STRING *sig)
+{
+ char buf[1024];
+ char *ptr = buf;
+ int i;
+ for(i=0; i<sig->length; i++)
+ ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%02x:", sig->data[i]);
+
+ infof(data, " Signature: %s\n", buf);
+ Curl_ssl_push_certinfo(data, numcert, "Signature", buf);
+}
+
+static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
+{
+ BIO *bio_out = BIO_new(BIO_s_mem());
+ BUF_MEM *biomem;
+
+ /* this outputs the cert in this 64 column wide style with newlines and
+ -----BEGIN CERTIFICATE----- texts and more */
+ PEM_write_bio_X509(bio_out, x);
+
+ BIO_get_mem_ptr(bio_out, &biomem);
+
+ Curl_ssl_push_certinfo_len(data, numcert,
+ "Cert", biomem->data, biomem->length);
+
+ BIO_free(bio_out);
+
+}
+
+/*
+ * This size was previously 512 which has been reported "too small" without
+ * any specifics, so it was enlarged to allow more data to get shown uncut.
+ * The "perfect" size is yet to figure out.
+ */
+#define CERTBUFFERSIZE 8192
+
+static CURLcode get_cert_chain(struct connectdata *conn,
+ struct ssl_connect_data *connssl)
+
+{
+ STACK_OF(X509) *sk;
+ int i;
+ char *bufp;
+ struct SessionHandle *data = conn->data;
+ int numcerts;
+
+ bufp = malloc(CERTBUFFERSIZE);
+ if(!bufp)
+ return CURLE_OUT_OF_MEMORY;
+
+ sk = SSL_get_peer_cert_chain(connssl->handle);
+ if(!sk) {
+ free(bufp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ numcerts = sk_X509_num(sk);
+ if(Curl_ssl_init_certinfo(data, numcerts)) {
+ free(bufp);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ infof(data, "--- Certificate chain\n");
+ for(i=0; i<numcerts; i++) {
+ long value;
+ ASN1_INTEGER *num;
+ ASN1_TIME *certdate;
+
+ /* get the certs in "importance order" */
+#if 0
+ X509 *x = sk_X509_value(sk, numcerts - i - 1);
+#else
+ X509 *x = sk_X509_value(sk, i);
+#endif
+
+ X509_CINF *cinf;
+ EVP_PKEY *pubkey=NULL;
+ int j;
+ char *ptr;
+
+ (void)x509_name_oneline(X509_get_subject_name(x), bufp, CERTBUFFERSIZE);
+ infof(data, "%2d Subject: %s\n", i, bufp);
+ Curl_ssl_push_certinfo(data, i, "Subject", bufp);
+
+ (void)x509_name_oneline(X509_get_issuer_name(x), bufp, CERTBUFFERSIZE);
+ infof(data, " Issuer: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Issuer", bufp);
+
+ value = X509_get_version(x);
+ infof(data, " Version: %lu (0x%lx)\n", value+1, value);
+ snprintf(bufp, CERTBUFFERSIZE, "%lx", value);
+ Curl_ssl_push_certinfo(data, i, "Version", bufp); /* hex */
+
+ num=X509_get_serialNumber(x);
+ if(num->length <= 4) {
+ value = ASN1_INTEGER_get(num);
+ infof(data," Serial Number: %ld (0x%lx)\n", value, value);
+ snprintf(bufp, CERTBUFFERSIZE, "%lx", value);
+ }
+ else {
+ int left = CERTBUFFERSIZE;
+
+ ptr = bufp;
+ *ptr++ = 0;
+ if(num->type == V_ASN1_NEG_INTEGER)
+ *ptr++='-';
+
+ for(j=0; (j<num->length) && (left>=4); j++) {
+ /* TODO: length restrictions */
+ snprintf(ptr, 3, "%02x%c",num->data[j],
+ ((j+1 == num->length)?'\n':':'));
+ ptr += 3;
+ left-=4;
+ }
+ if(num->length)
+ infof(data," Serial Number: %s\n", bufp);
+ else
+ bufp[0]=0;
+ }
+ if(bufp[0])
+ Curl_ssl_push_certinfo(data, i, "Serial Number", bufp); /* hex */
+
+ cinf = x->cert_info;
+
+ j = asn1_object_dump(cinf->signature->algorithm, bufp, CERTBUFFERSIZE);
+ if(!j) {
+ infof(data, " Signature Algorithm: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Signature Algorithm", bufp);
+ }
+
+ certdate = X509_get_notBefore(x);
+ asn1_output(certdate, bufp, CERTBUFFERSIZE);
+ infof(data, " Start date: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Start date", bufp);
+
+ certdate = X509_get_notAfter(x);
+ asn1_output(certdate, bufp, CERTBUFFERSIZE);
+ infof(data, " Expire date: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Expire date", bufp);
+
+ j = asn1_object_dump(cinf->key->algor->algorithm, bufp, CERTBUFFERSIZE);
+ if(!j) {
+ infof(data, " Public Key Algorithm: %s\n", bufp);
+ Curl_ssl_push_certinfo(data, i, "Public Key Algorithm", bufp);
+ }
+
+ pubkey = X509_get_pubkey(x);
+ if(!pubkey)
+ infof(data, " Unable to load public key\n");
+ else {
+ switch(pubkey->type) {
+ case EVP_PKEY_RSA:
+ infof(data, " RSA Public Key (%d bits)\n",
+ BN_num_bits(pubkey->pkey.rsa->n));
+ snprintf(bufp, CERTBUFFERSIZE, "%d", BN_num_bits(pubkey->pkey.rsa->n));
+ Curl_ssl_push_certinfo(data, i, "RSA Public Key", bufp);
+
+ print_pubkey_BN(rsa, n, i);
+ print_pubkey_BN(rsa, e, i);
+ print_pubkey_BN(rsa, d, i);
+ print_pubkey_BN(rsa, p, i);
+ print_pubkey_BN(rsa, q, i);
+ print_pubkey_BN(rsa, dmp1, i);
+ print_pubkey_BN(rsa, dmq1, i);
+ print_pubkey_BN(rsa, iqmp, i);
+ break;
+ case EVP_PKEY_DSA:
+ print_pubkey_BN(dsa, p, i);
+ print_pubkey_BN(dsa, q, i);
+ print_pubkey_BN(dsa, g, i);
+ print_pubkey_BN(dsa, priv_key, i);
+ print_pubkey_BN(dsa, pub_key, i);
+ break;
+ case EVP_PKEY_DH:
+ print_pubkey_BN(dh, p, i);
+ print_pubkey_BN(dh, g, i);
+ print_pubkey_BN(dh, priv_key, i);
+ print_pubkey_BN(dh, pub_key, i);
+ break;
+#if 0
+ case EVP_PKEY_EC: /* symbol not present in OpenSSL 0.9.6 */
+ /* left TODO */
+ break;
+#endif
+ }
+ EVP_PKEY_free(pubkey);
+ }
+
+ X509V3_ext(data, i, cinf->extensions);
+
+ X509_signature(data, i, x->signature);
+
+ dumpcert(data, x, i);
+ }
+
+ free(bufp);
+
+ return CURLE_OK;
+}
+
+/*
+ * Get the server cert, verify it and show it etc, only call failf() if the
+ * 'strict' argument is TRUE as otherwise all this is for informational
+ * purposes only!
+ *
+ * We check certificates to authenticate the server; otherwise we risk
+ * man-in-the-middle attack.
+ */
+static CURLcode servercert(struct connectdata *conn,
+ struct ssl_connect_data *connssl,
+ bool strict)
+{
+ CURLcode retcode = CURLE_OK;
+ int rc;
+ long lerr;
+ ASN1_TIME *certdate;
+ struct SessionHandle *data = conn->data;
+ X509 *issuer;
+ FILE *fp;
+ char *buffer = data->state.buffer;
+
+ if(data->set.ssl.certinfo)
+ /* we've been asked to gather certificate info! */
+ (void)get_cert_chain(conn, connssl);
+
+ connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
+ if(!connssl->server_cert) {
+ if(strict)
+ failf(data, "SSL: couldn't get peer certificate!");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ infof (data, "Server certificate:\n");
+
+ rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
+ buffer, BUFSIZE);
+ infof(data, "\t subject: %s\n", rc?"[NONE]":buffer);
+
+ certdate = X509_get_notBefore(connssl->server_cert);
+ asn1_output(certdate, buffer, BUFSIZE);
+ infof(data, "\t start date: %s\n", buffer);
+
+ certdate = X509_get_notAfter(connssl->server_cert);
+ asn1_output(certdate, buffer, BUFSIZE);
+ infof(data, "\t expire date: %s\n", buffer);
+
+ if(data->set.ssl.verifyhost) {
+ retcode = verifyhost(conn, connssl->server_cert);
+ if(retcode) {
+ X509_free(connssl->server_cert);
+ connssl->server_cert = NULL;
+ return retcode;
+ }
+ }
+
+ rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert),
+ buffer, BUFSIZE);
+ if(rc) {
+ if(strict)
+ failf(data, "SSL: couldn't get X509-issuer name!");
+ retcode = CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ infof(data, "\t issuer: %s\n", buffer);
+
+ /* We could do all sorts of certificate verification stuff here before
+ deallocating the certificate. */
+
+ /* e.g. match issuer name with provided issuer certificate */
+ if(data->set.str[STRING_SSL_ISSUERCERT]) {
+ fp=fopen(data->set.str[STRING_SSL_ISSUERCERT],"r");
+ if(!fp) {
+ if(strict)
+ failf(data, "SSL: Unable to open issuer cert (%s)",
+ data->set.str[STRING_SSL_ISSUERCERT]);
+ X509_free(connssl->server_cert);
+ connssl->server_cert = NULL;
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+ issuer = PEM_read_X509(fp,NULL,ZERO_NULL,NULL);
+ if(!issuer) {
+ if(strict)
+ failf(data, "SSL: Unable to read issuer cert (%s)",
+ data->set.str[STRING_SSL_ISSUERCERT]);
+ X509_free(connssl->server_cert);
+ X509_free(issuer);
+ fclose(fp);
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+ fclose(fp);
+ if(X509_check_issued(issuer,connssl->server_cert) != X509_V_OK) {
+ if(strict)
+ failf(data, "SSL: Certificate issuer check failed (%s)",
+ data->set.str[STRING_SSL_ISSUERCERT]);
+ X509_free(connssl->server_cert);
+ X509_free(issuer);
+ connssl->server_cert = NULL;
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+ infof(data, "\t SSL certificate issuer check ok (%s)\n",
+ data->set.str[STRING_SSL_ISSUERCERT]);
+ X509_free(issuer);
+ }
+
+ lerr = data->set.ssl.certverifyresult=
+ SSL_get_verify_result(connssl->handle);
+ if(data->set.ssl.certverifyresult != X509_V_OK) {
+ if(data->set.ssl.verifypeer) {
+ /* We probably never reach this, because SSL_connect() will fail
+ and we return earlier if verifypeer is set? */
+ if(strict)
+ failf(data, "SSL certificate verify result: %s (%ld)",
+ X509_verify_cert_error_string(lerr), lerr);
+ retcode = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ else
+ infof(data, "\t SSL certificate verify result: %s (%ld),"
+ " continuing anyway.\n",
+ X509_verify_cert_error_string(lerr), lerr);
+ }
+ else
+ infof(data, "\t SSL certificate verify ok.\n");
+ }
+
+ X509_free(connssl->server_cert);
+ connssl->server_cert = NULL;
+ connssl->connecting_state = ssl_connect_done;
+
+ return retcode;
+}
+
+
+static CURLcode
+ossl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode = CURLE_OK;
+ void *old_ssl_sessionid=NULL;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ int incache;
+ SSL_SESSION *our_ssl_sessionid;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+#ifdef HAVE_SSL_GET1_SESSION
+ our_ssl_sessionid = SSL_get1_session(connssl->handle);
+
+ /* SSL_get1_session() will increment the reference
+ count and the session will stay in memory until explicitly freed with
+ SSL_SESSION_free(3), regardless of its state.
+ This function was introduced in openssl 0.9.5a. */
+#else
+ our_ssl_sessionid = SSL_get_session(connssl->handle);
+
+ /* if SSL_get1_session() is unavailable, use SSL_get_session().
+ This is an inferior option because the session can be flushed
+ at any time by openssl. It is included only so curl compiles
+ under versions of openssl < 0.9.5a.
+
+ WARNING: How curl behaves if it's session is flushed is
+ untested.
+ */
+#endif
+
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+ if(!incache) {
+ retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
+ 0 /* unknown size */);
+ if(retcode) {
+ failf(data, "failed to store ssl session");
+ return retcode;
+ }
+ }
+#ifdef HAVE_SSL_GET1_SESSION
+ else {
+ /* Session was incache, so refcount already incremented earlier.
+ * Avoid further increments with each SSL_get1_session() call.
+ * This does not free the session as refcount remains > 0
+ */
+ SSL_SESSION_free(our_ssl_sessionid);
+ }
+#endif
+
+ /*
+ * We check certificates to authenticate the server; otherwise we risk
+ * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
+ * verify the peer ignore faults and failures from the server cert
+ * operations.
+ */
+
+ if(!data->set.ssl.verifypeer && !data->set.ssl.verifyhost)
+ (void)servercert(conn, connssl, FALSE);
+ else
+ retcode = servercert(conn, connssl, TRUE);
+
+ if(CURLE_OK == retcode)
+ connssl->connecting_state = ssl_connect_done;
+ return retcode;
+}
+
+static Curl_recv ossl_recv;
+static Curl_send ossl_send;
+
+static CURLcode
+ossl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode retcode;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1==connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ retcode = ossl_connect_step1(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if this
+ * connection is done nonblocking and this loop would execute again. This
+ * permits the owner of a multi handle to abort a connection attempt
+ * before step2 has completed while ensuring that a client using select()
+ * or epoll() will always have a valid fdset to wait on.
+ */
+ retcode = ossl_connect_step2(conn, sockindex);
+ if(retcode || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return retcode;
+
+ } /* repeat step2 until all transactions are done. */
+
+
+ if(ssl_connect_3==connssl->connecting_state) {
+ retcode = ossl_connect_step3(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ if(ssl_connect_done==connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = ossl_recv;
+ conn->send[sockindex] = ossl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+CURLcode
+Curl_ossl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return ossl_connect_common(conn, sockindex, TRUE, done);
+}
+
+CURLcode
+Curl_ossl_connect(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode;
+ bool done = FALSE;
+
+ retcode = ossl_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ return retcode;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+bool Curl_ossl_data_pending(const struct connectdata *conn,
+ int connindex)
+{
+ if(conn->ssl[connindex].handle)
+ /* SSL is in use */
+ return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+ else
+ return FALSE;
+}
+
+static ssize_t ossl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ /* SSL_write() is said to return 'int' while write() and send() returns
+ 'size_t' */
+ int err;
+ char error_buffer[120]; /* OpenSSL documents that this must be at least 120
+ bytes long. */
+ unsigned long sslerror;
+ int memlen;
+ int rc;
+
+ ERR_clear_error();
+
+ memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
+ rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+
+ if(rc <= 0) {
+ err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+
+ switch(err) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* The operation did not complete; the same TLS/SSL I/O function
+ should be called again later. This is basically an EWOULDBLOCK
+ equivalent. */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ case SSL_ERROR_SYSCALL:
+ failf(conn->data, "SSL_write() returned SYSCALL, errno = %d",
+ SOCKERRNO);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ case SSL_ERROR_SSL:
+ /* A failure in the SSL library occurred, usually a protocol error.
+ The OpenSSL error queue contains more information on the error. */
+ sslerror = ERR_get_error();
+ failf(conn->data, "SSL_write() error: %s",
+ ERR_error_string(sslerror, error_buffer));
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+ /* a true error */
+ failf(conn->data, "SSL_write() return error %d", err);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+ *curlcode = CURLE_OK;
+ return (ssize_t)rc; /* number of bytes */
+}
+
+static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ CURLcode *curlcode)
+{
+ char error_buffer[120]; /* OpenSSL documents that this must be at
+ least 120 bytes long. */
+ unsigned long sslerror;
+ ssize_t nread;
+ int buffsize;
+
+ ERR_clear_error();
+
+ buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
+ if(nread <= 0) {
+ /* failed SSL_read */
+ int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
+
+ switch(err) {
+ case SSL_ERROR_NONE: /* this is not an error */
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_read() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
+ value/errno" */
+ /* http://www.openssl.org/docs/crypto/ERR_get_error.html */
+ sslerror = ERR_get_error();
+ if((nread < 0) || sslerror) {
+ /* If the return code was negative or there actually is an error in the
+ queue */
+ failf(conn->data, "SSL read: %s, errno %d",
+ ERR_error_string(sslerror, error_buffer),
+ SOCKERRNO);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+ }
+ }
+ return nread;
+}
+
+size_t Curl_ossl_version(char *buffer, size_t size)
+{
+#ifdef YASSL_VERSION
+ /* yassl provides an OpenSSL API compatibility layer so it looks identical
+ to OpenSSL in all other aspects */
+ return snprintf(buffer, size, "yassl/%s", YASSL_VERSION);
+#else /* YASSL_VERSION */
+
+#if(SSLEAY_VERSION_NUMBER >= 0x905000)
+ {
+ char sub[3];
+ unsigned long ssleay_value;
+ sub[2]='\0';
+ sub[1]='\0';
+ ssleay_value=SSLeay();
+ if(ssleay_value < 0x906000) {
+ ssleay_value=SSLEAY_VERSION_NUMBER;
+ sub[0]='\0';
+ }
+ else {
+ if(ssleay_value&0xff0) {
+ int minor_ver = (ssleay_value >> 4) & 0xff;
+ if(minor_ver > 26) {
+ /* handle extended version introduced for 0.9.8za */
+ sub[1] = (char) ((minor_ver - 1) % 26 + 'a' + 1);
+ sub[0] = 'z';
+ }
+ else {
+ sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1);
+ }
+ }
+ else
+ sub[0]='\0';
+ }
+
+ return snprintf(buffer, size, "%s/%lx.%lx.%lx%s",
+#ifdef OPENSSL_IS_BORINGSSL
+ "BoringSSL"
+#else
+#ifdef LIBRESSL_VERSION_NUMBER
+ "LibreSSL"
+#else
+ "OpenSSL"
+#endif
+#endif
+ , (ssleay_value>>28)&0xf,
+ (ssleay_value>>20)&0xff,
+ (ssleay_value>>12)&0xff,
+ sub);
+ }
+
+#else /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */
+
+#if(SSLEAY_VERSION_NUMBER >= 0x900000)
+ return snprintf(buffer, size, "OpenSSL/%lx.%lx.%lx",
+ (SSLEAY_VERSION_NUMBER>>28)&0xff,
+ (SSLEAY_VERSION_NUMBER>>20)&0xff,
+ (SSLEAY_VERSION_NUMBER>>12)&0xf);
+
+#else /* (SSLEAY_VERSION_NUMBER >= 0x900000) */
+ {
+ char sub[2];
+ sub[1]='\0';
+ if(SSLEAY_VERSION_NUMBER&0x0f) {
+ sub[0]=(SSLEAY_VERSION_NUMBER&0x0f) + 'a' -1;
+ }
+ else
+ sub[0]='\0';
+
+ return snprintf(buffer, size, "SSL/%x.%x.%x%s",
+ (SSLEAY_VERSION_NUMBER>>12)&0xff,
+ (SSLEAY_VERSION_NUMBER>>8)&0xf,
+ (SSLEAY_VERSION_NUMBER>>4)&0xf, sub);
+ }
+#endif /* (SSLEAY_VERSION_NUMBER >= 0x900000) */
+#endif /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */
+
+#endif /* YASSL_VERSION */
+}
+
+/* can be called with data == NULL */
+int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy,
+ size_t length)
+{
+ if(data)
+ Curl_ossl_seed(data); /* Initiate the seed if not already done */
+ RAND_bytes(entropy, curlx_uztosi(length));
+ return 0; /* 0 as in no problem */
+}
+
+void Curl_ossl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum /* output */,
+ size_t unused)
+{
+ MD5_CTX MD5pw;
+ (void)unused;
+ MD5_Init(&MD5pw);
+ MD5_Update(&MD5pw, tmp, tmplen);
+ MD5_Final(md5sum, &MD5pw);
+}
+#endif /* USE_SSLEAY */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/openssl.h b/external/libcurl_android/jni/libcurl/lib/vtls/openssl.h
new file mode 100755
index 00000000..1a55ffc2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/openssl.h
@@ -0,0 +1,101 @@
+#ifndef HEADER_CURL_SSLUSE_H
+#define HEADER_CURL_SSLUSE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_SSLEAY
+/*
+ * This header should only be needed to get included by vtls.c and openssl.c
+ */
+
+#include "urldata.h"
+
+CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex);
+CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+/* close a SSL connection */
+void Curl_ossl_close(struct connectdata *conn, int sockindex);
+
+/* tell OpenSSL to close down all open information regarding connections (and
+ thus session ID caching etc) */
+int Curl_ossl_close_all(struct SessionHandle *data);
+
+/* Sets an OpenSSL engine */
+CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine);
+
+/* function provided for the generic SSL-layer, called when a session id
+ should be freed */
+void Curl_ossl_session_free(void *ptr);
+
+/* Sets engine as default for all SSL operations */
+CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data);
+
+/* Build list of OpenSSL engines */
+struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data);
+
+int Curl_ossl_init(void);
+void Curl_ossl_cleanup(void);
+
+size_t Curl_ossl_version(char *buffer, size_t size);
+int Curl_ossl_check_cxn(struct connectdata *cxn);
+int Curl_ossl_shutdown(struct connectdata *conn, int sockindex);
+bool Curl_ossl_data_pending(const struct connectdata *conn,
+ int connindex);
+
+/* return 0 if a find random is filled in */
+int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy,
+ size_t length);
+void Curl_ossl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum /* output */,
+ size_t unused);
+
+/* this backend provides these functions: */
+#define have_curlssl_md5sum 1
+
+/* API setup for OpenSSL */
+#define curlssl_init Curl_ossl_init
+#define curlssl_cleanup Curl_ossl_cleanup
+#define curlssl_connect Curl_ossl_connect
+#define curlssl_connect_nonblocking Curl_ossl_connect_nonblocking
+#define curlssl_session_free(x) Curl_ossl_session_free(x)
+#define curlssl_close_all Curl_ossl_close_all
+#define curlssl_close Curl_ossl_close
+#define curlssl_shutdown(x,y) Curl_ossl_shutdown(x,y)
+#define curlssl_set_engine(x,y) Curl_ossl_set_engine(x,y)
+#define curlssl_set_engine_default(x) Curl_ossl_set_engine_default(x)
+#define curlssl_engines_list(x) Curl_ossl_engines_list(x)
+#define curlssl_version Curl_ossl_version
+#define curlssl_check_cxn Curl_ossl_check_cxn
+#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)
+#define curlssl_random(x,y,z) Curl_ossl_random(x,y,z)
+#define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d)
+#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
+
+#define DEFAULT_CIPHER_SELECTION "ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4"
+
+#endif /* USE_SSLEAY */
+#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/polarssl.c b/external/libcurl_android/jni/libcurl/lib/vtls/polarssl.c
new file mode 100755
index 00000000..5332b92c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/polarssl.c
@@ -0,0 +1,746 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_POLARSSL
+
+#include <polarssl/net.h>
+#include <polarssl/ssl.h>
+#include <polarssl/certs.h>
+#include <polarssl/x509.h>
+#include <polarssl/version.h>
+
+#if POLARSSL_VERSION_NUMBER < 0x01030000
+#error too old PolarSSL
+#endif
+
+#include <polarssl/error.h>
+#include <polarssl/entropy.h>
+#include <polarssl/ctr_drbg.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "polarssl.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "rawstr.h"
+#include "polarssl_threadlock.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* apply threading? */
+#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+#define THREADING_SUPPORT
+#endif
+
+#if defined(THREADING_SUPPORT)
+static entropy_context entropy;
+
+static int entropy_init_initialized = 0;
+
+/* start of entropy_init_mutex() */
+static void entropy_init_mutex(entropy_context *ctx)
+{
+ /* lock 0 = entropy_init_mutex() */
+ polarsslthreadlock_lock_function(0);
+ if(entropy_init_initialized == 0) {
+ entropy_init(ctx);
+ entropy_init_initialized = 1;
+ }
+ polarsslthreadlock_unlock_function(0);
+}
+/* end of entropy_init_mutex() */
+
+/* start of entropy_func_mutex() */
+static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
+{
+ int ret;
+ /* lock 1 = entropy_func_mutex() */
+ polarsslthreadlock_lock_function(1);
+ ret = entropy_func(data, output, len);
+ polarsslthreadlock_unlock_function(1);
+
+ return ret;
+}
+/* end of entropy_func_mutex() */
+
+#endif /* THREADING_SUPPORT */
+
+/* Define this to enable lots of debugging for PolarSSL */
+#undef POLARSSL_DEBUG
+
+#ifdef POLARSSL_DEBUG
+static void polarssl_debug(void *context, int level, const char *line)
+{
+ struct SessionHandle *data = NULL;
+
+ if(!context)
+ return;
+
+ data = (struct SessionHandle *)context;
+
+ infof(data, "%s", line);
+ (void) level;
+}
+#else
+#endif
+
+/* ALPN for http2? */
+#ifdef USE_NGHTTP2
+# undef HAS_ALPN
+# ifdef POLARSSL_SSL_ALPN
+# define HAS_ALPN
+# endif
+#endif
+
+static Curl_recv polarssl_recv;
+static Curl_send polarssl_send;
+
+
+static CURLcode
+polarssl_connect_step1(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+
+ bool sni = TRUE; /* default is SNI enabled */
+ int ret = -1;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ void *old_session = NULL;
+ size_t old_session_size = 0;
+ char errorbuf[128];
+ errorbuf[0]=0;
+
+ /* PolarSSL only supports SSLv3 and TLSv1 */
+ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ failf(data, "PolarSSL does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
+ sni = FALSE; /* SSLv3 has no SNI */
+
+#ifdef THREADING_SUPPORT
+ entropy_init_mutex(&entropy);
+
+ if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
+ connssl->ssn.id, connssl->ssn.length)) != 0) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
+ -ret, errorbuf);
+ }
+#else
+ entropy_init(&connssl->entropy);
+
+ if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
+ connssl->ssn.id, connssl->ssn.length)) != 0) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
+ -ret, errorbuf);
+ }
+#endif /* THREADING_SUPPORT */
+
+ /* Load the trusted CA */
+ memset(&connssl->cacert, 0, sizeof(x509_crt));
+
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ ret = x509_crt_parse_file(&connssl->cacert,
+ data->set.str[STRING_SSL_CAFILE]);
+
+ if(ret<0) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+
+ if(data->set.ssl.verifypeer)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+
+ if(data->set.str[STRING_SSL_CAPATH]) {
+ ret = x509_crt_parse_path(&connssl->cacert,
+ data->set.str[STRING_SSL_CAPATH]);
+
+ if(ret<0) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+
+ if(data->set.ssl.verifypeer)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+
+ /* Load the client certificate */
+ memset(&connssl->clicert, 0, sizeof(x509_crt));
+
+ if(data->set.str[STRING_CERT]) {
+ ret = x509_crt_parse_file(&connssl->clicert,
+ data->set.str[STRING_CERT]);
+
+ if(ret) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_CERT], -ret, errorbuf);
+
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* Load the client private key */
+ if(data->set.str[STRING_KEY]) {
+ pk_context pk;
+ pk_init(&pk);
+ ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
+ data->set.str[STRING_KEY_PASSWD]);
+ if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
+ ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+ if(ret == 0)
+ rsa_copy(&connssl->rsa, pk_rsa(pk));
+ else
+ rsa_free(&connssl->rsa);
+ pk_free(&pk);
+
+ if(ret) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_KEY], -ret, errorbuf);
+
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* Load the CRL */
+ memset(&connssl->crl, 0, sizeof(x509_crl));
+
+ if(data->set.str[STRING_SSL_CRLFILE]) {
+ ret = x509_crl_parse_file(&connssl->crl,
+ data->set.str[STRING_SSL_CRLFILE]);
+
+ if(ret) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
+ data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ }
+
+ infof(data, "PolarSSL: Connecting to %s:%d\n",
+ conn->host.name, conn->remote_port);
+
+ if(ssl_init(&connssl->ssl)) {
+ failf(data, "PolarSSL: ssl_init failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ switch(data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv3:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_0);
+ infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
+ break;
+ case CURL_SSLVERSION_TLSv1_0:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_1);
+ infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n");
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_2);
+ infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n");
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_3);
+ infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
+ break;
+ }
+
+ ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
+ ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
+
+ ssl_set_rng(&connssl->ssl, ctr_drbg_random,
+ &connssl->ctr_drbg);
+ ssl_set_bio(&connssl->ssl,
+ net_recv, &conn->sock[sockindex],
+ net_send, &conn->sock[sockindex]);
+
+ ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
+ if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
+ memcpy(&connssl->ssn, old_session, old_session_size);
+ infof(data, "PolarSSL re-using session\n");
+ }
+
+ ssl_set_session(&connssl->ssl,
+ &connssl->ssn);
+
+ ssl_set_ca_chain(&connssl->ssl,
+ &connssl->cacert,
+ &connssl->crl,
+ conn->host.name);
+
+ ssl_set_own_cert_rsa(&connssl->ssl,
+ &connssl->clicert, &connssl->rsa);
+
+ if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
+#ifdef ENABLE_IPV6
+ !Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
+#endif
+ sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+ infof(data, "WARNING: failed to configure "
+ "server name indication (SNI) TLS extension\n");
+ }
+
+#ifdef HAS_ALPN
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+ if(data->set.ssl_enable_alpn) {
+ static const char* protocols[] = {
+ NGHTTP2_PROTO_VERSION_ID, ALPN_HTTP_1_1, NULL
+ };
+ ssl_set_alpn_protocols(&connssl->ssl, protocols);
+ infof(data, "ALPN, offering %s, %s\n", protocols[0],
+ protocols[1]);
+ }
+ }
+#endif
+
+#ifdef POLARSSL_DEBUG
+ ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
+#endif
+
+ connssl->connecting_state = ssl_connect_2;
+
+ return CURLE_OK;
+}
+
+static CURLcode
+polarssl_connect_step2(struct connectdata *conn,
+ int sockindex)
+{
+ int ret;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ char buffer[1024];
+
+#ifdef HAS_ALPN
+ const char* next_protocol;
+#endif
+
+ char errorbuf[128];
+ errorbuf[0] = 0;
+
+ conn->recv[sockindex] = polarssl_recv;
+ conn->send[sockindex] = polarssl_send;
+
+ for(;;) {
+ if(!(ret = ssl_handshake(&connssl->ssl)))
+ break;
+ else if(ret != POLARSSL_ERR_NET_WANT_READ &&
+ ret != POLARSSL_ERR_NET_WANT_WRITE) {
+#ifdef POLARSSL_ERROR_C
+ error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+ failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
+ -ret, errorbuf);
+
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ if(ret == POLARSSL_ERR_NET_WANT_READ) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+ if(ret == POLARSSL_ERR_NET_WANT_WRITE) {
+ connssl->connecting_state = ssl_connect_2_writing;
+ return CURLE_OK;
+ }
+ failf(data, "SSL_connect failed with error %d.", ret);
+ return CURLE_SSL_CONNECT_ERROR;
+
+ }
+ }
+
+ infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
+ ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
+ );
+
+ ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+
+ if(ret && data->set.ssl.verifypeer) {
+ if(ret & BADCERT_EXPIRED)
+ failf(data, "Cert verify failed: BADCERT_EXPIRED");
+
+ if(ret & BADCERT_REVOKED) {
+ failf(data, "Cert verify failed: BADCERT_REVOKED");
+ return CURLE_SSL_CACERT;
+ }
+
+ if(ret & BADCERT_CN_MISMATCH)
+ failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
+
+ if(ret & BADCERT_NOT_TRUSTED)
+ failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
+
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(ssl_get_peer_cert(&(connssl->ssl))) {
+ /* If the session was resumed, there will be no peer certs */
+ memset(buffer, 0, sizeof(buffer));
+
+ if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
+ ssl_get_peer_cert(&(connssl->ssl))) != -1)
+ infof(data, "Dumping cert info:\n%s\n", buffer);
+ }
+
+#ifdef HAS_ALPN
+ if(data->set.ssl_enable_alpn) {
+ next_protocol = ssl_get_alpn_protocol(&connssl->ssl);
+
+ if(next_protocol != NULL) {
+ infof(data, "ALPN, server accepted to use %s\n", next_protocol);
+
+ if(strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
+ NGHTTP2_PROTO_VERSION_ID_LEN)) {
+ conn->negnpn = NPN_HTTP2;
+ }
+ else if(strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
+ conn->negnpn = NPN_HTTP1_1;
+ }
+ }
+ else {
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ }
+ }
+#endif
+
+ connssl->connecting_state = ssl_connect_3;
+ infof(data, "SSL connected\n");
+
+ return CURLE_OK;
+}
+
+static CURLcode
+polarssl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode = CURLE_OK;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ void *old_ssl_sessionid = NULL;
+ ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn ;
+ int incache;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+ /* Save the current session data for possible re-use */
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+ if(!incache) {
+ void *new_session = malloc(sizeof(ssl_session));
+
+ if(new_session) {
+ memcpy(new_session, our_ssl_sessionid,
+ sizeof(ssl_session));
+
+ retcode = Curl_ssl_addsessionid(conn, new_session,
+ sizeof(ssl_session));
+ }
+ else {
+ retcode = CURLE_OUT_OF_MEMORY;
+ }
+
+ if(retcode) {
+ failf(data, "failed to store ssl session");
+ return retcode;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return CURLE_OK;
+}
+
+static ssize_t polarssl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
+{
+ int ret = -1;
+
+ ret = ssl_write(&conn->ssl[sockindex].ssl,
+ (unsigned char *)mem, len);
+
+ if(ret < 0) {
+ *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ?
+ CURLE_AGAIN : CURLE_SEND_ERROR;
+ ret = -1;
+ }
+
+ return ret;
+}
+
+void Curl_polarssl_close_all(struct SessionHandle *data)
+{
+ (void)data;
+}
+
+void Curl_polarssl_close(struct connectdata *conn, int sockindex)
+{
+ rsa_free(&conn->ssl[sockindex].rsa);
+ x509_crt_free(&conn->ssl[sockindex].clicert);
+ x509_crt_free(&conn->ssl[sockindex].cacert);
+ x509_crl_free(&conn->ssl[sockindex].crl);
+ ssl_free(&conn->ssl[sockindex].ssl);
+}
+
+static ssize_t polarssl_recv(struct connectdata *conn,
+ int num,
+ char *buf,
+ size_t buffersize,
+ CURLcode *curlcode)
+{
+ int ret = -1;
+ ssize_t len = -1;
+
+ memset(buf, 0, buffersize);
+ ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
+
+ if(ret <= 0) {
+ if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
+ return 0;
+
+ *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ?
+ CURLE_AGAIN : CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ len = ret;
+
+ return len;
+}
+
+void Curl_polarssl_session_free(void *ptr)
+{
+ free(ptr);
+}
+
+size_t Curl_polarssl_version(char *buffer, size_t size)
+{
+ unsigned int version = version_get_number();
+ return snprintf(buffer, size, "PolarSSL/%d.%d.%d", version>>24,
+ (version>>16)&0xff, (version>>8)&0xff);
+}
+
+static CURLcode
+polarssl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode retcode;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ long timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1==connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ retcode = polarssl_connect_step1(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading
+ || connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd = ssl_connect_2_writing==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if
+ * this connection is part of a multi handle and this loop would
+ * execute again. This permits the owner of a multi handle to
+ * abort a connection attempt before step2 has completed while
+ * ensuring that a client using select() or epoll() will always
+ * have a valid fdset to wait on.
+ */
+ retcode = polarssl_connect_step2(conn, sockindex);
+ if(retcode || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return retcode;
+
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3==connssl->connecting_state) {
+ retcode = polarssl_connect_step3(conn, sockindex);
+ if(retcode)
+ return retcode;
+ }
+
+ if(ssl_connect_done==connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = polarssl_recv;
+ conn->send[sockindex] = polarssl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+CURLcode
+Curl_polarssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done)
+{
+ return polarssl_connect_common(conn, sockindex, TRUE, done);
+}
+
+
+CURLcode
+Curl_polarssl_connect(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode;
+ bool done = FALSE;
+
+ retcode = polarssl_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ return retcode;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+/*
+ * return 0 error initializing SSL
+ * return 1 SSL initialized successfully
+ */
+int polarssl_init(void)
+{
+ return polarsslthreadlock_thread_setup();
+}
+
+void polarssl_cleanup(void)
+{
+ (void)polarsslthreadlock_thread_cleanup();
+}
+
+#endif /* USE_POLARSSL */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/polarssl.h b/external/libcurl_android/jni/libcurl/lib/vtls/polarssl.h
new file mode 100755
index 00000000..9ab7e47e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/polarssl.h
@@ -0,0 +1,73 @@
+#ifndef HEADER_CURL_POLARSSL_H
+#define HEADER_CURL_POLARSSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_POLARSSL
+
+/* Called on first use PolarSSL, setup threading if supported */
+int polarssl_init(void);
+void polarssl_cleanup(void);
+
+
+CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
+
+CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+
+/* tell PolarSSL to close down all open information regarding connections (and
+ thus session ID caching etc) */
+void Curl_polarssl_close_all(struct SessionHandle *data);
+
+ /* close a SSL connection */
+void Curl_polarssl_close(struct connectdata *conn, int sockindex);
+
+void Curl_polarssl_session_free(void *ptr);
+size_t Curl_polarssl_version(char *buffer, size_t size);
+int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
+
+/* API setup for PolarSSL */
+#define curlssl_init() polarssl_init()
+#define curlssl_cleanup() polarssl_cleanup()
+#define curlssl_connect Curl_polarssl_connect
+#define curlssl_connect_nonblocking Curl_polarssl_connect_nonblocking
+#define curlssl_session_free(x) Curl_polarssl_session_free(x)
+#define curlssl_close_all Curl_polarssl_close_all
+#define curlssl_close Curl_polarssl_close
+#define curlssl_shutdown(x,y) 0
+#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
+#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
+#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
+#define curlssl_version Curl_polarssl_version
+#define curlssl_check_cxn(x) (x=x, -1)
+#define curlssl_data_pending(x,y) (x=x, y=y, 0)
+#define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL
+
+/* This might cause libcurl to use a weeker random!
+ TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that
+*/
+#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
+
+#endif /* USE_POLARSSL */
+#endif /* HEADER_CURL_POLARSSL_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/polarssl_threadlock.c b/external/libcurl_android/jni/libcurl/lib/vtls/polarssl_threadlock.c
new file mode 100755
index 00000000..ad187153
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/polarssl_threadlock.c
@@ -0,0 +1,156 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(USE_POLARSSL) && \
+ (defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32))
+
+#if defined(USE_THREADS_POSIX)
+# ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+# endif
+#elif defined(USE_THREADS_WIN32)
+# ifdef HAVE_PROCESS_H
+# include <process.h>
+# endif
+#endif
+
+#include "polarssl_threadlock.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* number of thread locks */
+#define NUMT 2
+
+/* This array will store all of the mutexes available to PolarSSL. */
+static POLARSSL_MUTEX_T *mutex_buf = NULL;
+
+int polarsslthreadlock_thread_setup(void)
+{
+ int i;
+ int ret;
+
+ mutex_buf = malloc(NUMT * sizeof(POLARSSL_MUTEX_T));
+ if(!mutex_buf)
+ return 0; /* error, no number of threads defined */
+
+#ifdef HAVE_PTHREAD_H
+ for(i = 0; i < NUMT; i++) {
+ ret = pthread_mutex_init(&mutex_buf[i], NULL);
+ if(ret)
+ return 0; /* pthread_mutex_init failed */
+ }
+#elif defined(HAVE_PROCESS_H)
+ for(i = 0; i < NUMT; i++) {
+ mutex_buf[i] = CreateMutex(0, FALSE, 0);
+ if(mutex_buf[i] == 0)
+ return 0; /* CreateMutex failed */
+ }
+#endif /* HAVE_PTHREAD_H */
+
+ return 1; /* OK */
+}
+
+int polarsslthreadlock_thread_cleanup(void)
+{
+ int i;
+ int ret;
+
+ if(!mutex_buf)
+ return 0; /* error, no threads locks defined */
+
+#ifdef HAVE_PTHREAD_H
+ for(i = 0; i < NUMT; i++) {
+ ret = pthread_mutex_destroy(&mutex_buf[i]);
+ if(ret)
+ return 0; /* pthread_mutex_destroy failed */
+ }
+#elif defined(HAVE_PROCESS_H)
+ for(i = 0; i < NUMT; i++) {
+ ret = CloseHandle(mutex_buf[i]);
+ if(!ret)
+ return 0; /* CloseHandle failed */
+ }
+#endif /* HAVE_PTHREAD_H */
+ free(mutex_buf);
+ mutex_buf = NULL;
+
+ return 1; /* OK */
+}
+
+int polarsslthreadlock_lock_function(int n)
+{
+ int ret;
+#ifdef HAVE_PTHREAD_H
+ if(n < NUMT) {
+ ret = pthread_mutex_lock(&mutex_buf[n]);
+ if(ret) {
+ DEBUGF(fprintf(stderr,
+ "Error: polarsslthreadlock_lock_function failed\n"));
+ return 0; /* pthread_mutex_lock failed */
+ }
+ }
+#elif defined(HAVE_PROCESS_H)
+ if(n < NUMT) {
+ ret = (WaitForSingleObject(mutex_buf[n], INFINITE)==WAIT_FAILED?1:0);
+ if(ret) {
+ DEBUGF(fprintf(stderr,
+ "Error: polarsslthreadlock_lock_function failed\n"));
+ return 0; /* pthread_mutex_lock failed */
+ }
+ }
+#endif /* HAVE_PTHREAD_H */
+ return 1; /* OK */
+}
+
+int polarsslthreadlock_unlock_function(int n)
+{
+ int ret;
+#ifdef HAVE_PTHREAD_H
+ if(n < NUMT) {
+ ret = pthread_mutex_unlock(&mutex_buf[n]);
+ if(ret) {
+ DEBUGF(fprintf(stderr,
+ "Error: polarsslthreadlock_unlock_function failed\n"));
+ return 0; /* pthread_mutex_unlock failed */
+ }
+ }
+#elif defined(HAVE_PROCESS_H)
+ if(n < NUMT) {
+ ret = ReleaseMutex(mutex_buf[n]);
+ if(!ret) {
+ DEBUGF(fprintf(stderr,
+ "Error: polarsslthreadlock_unlock_function failed\n"));
+ return 0; /* pthread_mutex_lock failed */
+ }
+ }
+#endif /* HAVE_PTHREAD_H */
+ return 1; /* OK */
+}
+
+#endif /* USE_POLARSSL */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/polarssl_threadlock.h b/external/libcurl_android/jni/libcurl/lib/vtls/polarssl_threadlock.h
new file mode 100755
index 00000000..b67b3f9a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/polarssl_threadlock.h
@@ -0,0 +1,53 @@
+#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H
+#define HEADER_CURL_POLARSSL_THREADLOCK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_POLARSSL
+
+#if defined(USE_THREADS_POSIX)
+# define POLARSSL_MUTEX_T pthread_mutex_t
+#elif defined(USE_THREADS_WIN32)
+# define POLARSSL_MUTEX_T HANDLE
+#endif
+
+#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+
+int polarsslthreadlock_thread_setup(void);
+int polarsslthreadlock_thread_cleanup(void);
+int polarsslthreadlock_lock_function(int n);
+int polarsslthreadlock_unlock_function(int n);
+
+#else
+
+#define polarsslthreadlock_thread_setup() 1
+#define polarsslthreadlock_thread_cleanup() 1
+#define polarsslthreadlock_lock_function(x) 1
+#define polarsslthreadlock_unlock_function(x) 1
+
+#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
+
+#endif /* USE_POLARSSL */
+
+#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/qssl.c b/external/libcurl_android/jni/libcurl/lib/vtls/qssl.c
new file mode 100755
index 00000000..4c320538
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/qssl.c
@@ -0,0 +1,527 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_QSOSSL
+
+#include <qsossl.h>
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "qssl.h"
+#include "vtls.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "x509asn1.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+
+int Curl_qsossl_init(void)
+
+{
+ /* Nothing to do here. We must have connection data to initialize ssl, so
+ * defer.
+ */
+
+ return 1;
+}
+
+
+void Curl_qsossl_cleanup(void)
+
+{
+ /* Nothing to do. */
+}
+
+
+static CURLcode Curl_qsossl_init_session(struct SessionHandle * data)
+
+{
+ int rc;
+ char * certname;
+ SSLInit initstr;
+ SSLInitApp initappstr;
+
+ /* Initialize the job for SSL according to the current parameters.
+ * QsoSSL offers two ways to do it: SSL_Init_Application() that uses an
+ * application identifier to select certificates in the main certificate
+ * store, and SSL_Init() that uses named keyring files and a password.
+ * It is not possible to have different keyrings for the CAs and the
+ * local certificate. We thus use the certificate name to identify the
+ * keyring if given, else the CA file name.
+ * If the key file name is given, it is taken as the password for the
+ * keyring in certificate file.
+ * We first try to SSL_Init_Application(), then SSL_Init() if it failed.
+ */
+
+ certname = data->set.str[STRING_CERT];
+
+ if(!certname) {
+ certname = data->set.str[STRING_SSL_CAFILE];
+
+ if(!certname)
+ return CURLE_OK; /* Use previous setup. */
+ }
+
+ memset((char *) &initappstr, 0, sizeof initappstr);
+ initappstr.applicationID = certname;
+ initappstr.applicationIDLen = strlen(certname);
+ initappstr.protocol = SSL_VERSION_CURRENT; /* TLSV1 compat. SSLV[23]. */
+ initappstr.sessionType = SSL_REGISTERED_AS_CLIENT;
+ rc = SSL_Init_Application(&initappstr);
+
+ if(rc == SSL_ERROR_NOT_REGISTERED) {
+ initstr.keyringFileName = certname;
+ initstr.keyringPassword = data->set.str[STRING_KEY];
+ initstr.cipherSuiteList = NULL; /* Use default. */
+ initstr.cipherSuiteListLen = 0;
+ rc = SSL_Init(&initstr);
+ }
+
+ switch (rc) {
+
+ case 0: /* No error. */
+ break;
+
+ case SSL_ERROR_IO:
+ failf(data, "SSL_Init() I/O error: %s", strerror(errno));
+ return CURLE_SSL_CONNECT_ERROR;
+
+ case SSL_ERROR_BAD_CIPHER_SUITE:
+ return CURLE_SSL_CIPHER;
+
+ case SSL_ERROR_KEYPASSWORD_EXPIRED:
+ case SSL_ERROR_NOT_REGISTERED:
+ return CURLE_SSL_CONNECT_ERROR;
+
+ case SSL_ERROR_NO_KEYRING:
+ return CURLE_SSL_CACERT;
+
+ case SSL_ERROR_CERT_EXPIRED:
+ return CURLE_SSL_CERTPROBLEM;
+
+ default:
+ failf(data, "SSL_Init(): %s", SSL_Strerror(rc, NULL));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ return CURLE_OK;
+}
+
+
+static CURLcode Curl_qsossl_create(struct connectdata * conn, int sockindex)
+
+{
+ SSLHandle * h;
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+
+ h = SSL_Create(conn->sock[sockindex], SSL_ENCRYPT);
+
+ if(!h) {
+ failf(conn->data, "SSL_Create() I/O error: %s", strerror(errno));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ connssl->handle = h;
+ return CURLE_OK;
+}
+
+
+static int Curl_qsossl_trap_cert(SSLHandle * h)
+
+{
+ return 1; /* Accept certificate. */
+}
+
+
+static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
+
+{
+ int rc;
+ struct SessionHandle * data = conn->data;
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+ SSLHandle * h = connssl->handle;
+ long timeout_ms;
+
+ h->exitPgm = data->set.ssl.verifypeer? NULL: Curl_qsossl_trap_cert;
+
+ /* figure out how long time we should wait at maximum */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* time-out, bail out, go home */
+ failf(data, "Connection time-out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* SSL_Handshake() timeout resolution is second, so round up. */
+ h->timeout = (timeout_ms + 1000 - 1) / 1000;
+
+ /* Set-up protocol. */
+
+ switch (data->set.ssl.version) {
+
+ default:
+ case CURL_SSLVERSION_DEFAULT:
+ h->protocol = SSL_VERSION_CURRENT; /* TLSV1 compat. SSLV[23]. */
+ break;
+
+ case CURL_SSLVERSION_TLSv1:
+ h->protocol = TLS_VERSION_1;
+ break;
+
+ case CURL_SSLVERSION_SSLv2:
+ h->protocol = SSL_VERSION_2;
+ break;
+
+ case CURL_SSLVERSION_SSLv3:
+ h->protocol = SSL_VERSION_3;
+ break;
+
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1_1:
+ case CURL_SSLVERSION_TLSv1_2:
+ failf(data, "TLS minor version cannot be set");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ h->peerCert = NULL;
+ h->peerCertLen = 0;
+ rc = SSL_Handshake(h, SSL_HANDSHAKE_AS_CLIENT);
+
+ switch (rc) {
+
+ case 0: /* No error. */
+ break;
+
+ case SSL_ERROR_BAD_CERTIFICATE:
+ case SSL_ERROR_BAD_CERT_SIG:
+ case SSL_ERROR_NOT_TRUSTED_ROOT:
+ return CURLE_PEER_FAILED_VERIFICATION;
+
+ case SSL_ERROR_BAD_CIPHER_SUITE:
+ case SSL_ERROR_NO_CIPHERS:
+ return CURLE_SSL_CIPHER;
+
+ case SSL_ERROR_CERTIFICATE_REJECTED:
+ case SSL_ERROR_CERT_EXPIRED:
+ case SSL_ERROR_NO_CERTIFICATE:
+ return CURLE_SSL_CERTPROBLEM;
+
+ case SSL_ERROR_IO:
+ failf(data, "SSL_Handshake() I/O error: %s", strerror(errno));
+ return CURLE_SSL_CONNECT_ERROR;
+
+ default:
+ failf(data, "SSL_Handshake(): %s", SSL_Strerror(rc, NULL));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ /* Verify host. */
+ rc = Curl_verifyhost(conn, h->peerCert, h->peerCert + h->peerCertLen);
+ if(rc != CURLE_OK)
+ return rc;
+
+ /* Gather certificate info. */
+ if(data->set.ssl.certinfo) {
+ if(Curl_ssl_init_certinfo(data, 1))
+ return CURLE_OUT_OF_MEMORY;
+ if(h->peerCert) {
+ rc = Curl_extract_certinfo(conn, 0, h->peerCert,
+ h->peerCert + h->peerCertLen);
+ if(rc != CURLE_OK)
+ return rc;
+ }
+ }
+
+ return CURLE_OK;
+}
+
+
+static Curl_recv qsossl_recv;
+static Curl_send qsossl_send;
+
+CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex)
+
+{
+ struct SessionHandle * data = conn->data;
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+ int rc;
+
+ rc = Curl_qsossl_init_session(data);
+
+ if(rc == CURLE_OK) {
+ rc = Curl_qsossl_create(conn, sockindex);
+
+ if(rc == CURLE_OK) {
+ rc = Curl_qsossl_handshake(conn, sockindex);
+ if(rc != CURLE_OK)
+ SSL_Destroy(connssl->handle);
+ }
+ }
+
+ if(rc == CURLE_OK) {
+ conn->recv[sockindex] = qsossl_recv;
+ conn->send[sockindex] = qsossl_send;
+ connssl->state = ssl_connection_complete;
+ }
+ else {
+ connssl->handle = NULL;
+ connssl->use = FALSE;
+ connssl->state = ssl_connection_none;
+ }
+
+ return rc;
+}
+
+
+static int Curl_qsossl_close_one(struct ssl_connect_data * conn,
+ struct SessionHandle * data)
+
+{
+ int rc;
+
+ if(!conn->handle)
+ return 0;
+
+ rc = SSL_Destroy(conn->handle);
+
+ if(rc) {
+ if(rc == SSL_ERROR_IO) {
+ failf(data, "SSL_Destroy() I/O error: %s", strerror(errno));
+ return -1;
+ }
+
+ /* An SSL error. */
+ failf(data, "SSL_Destroy() returned error %s", SSL_Strerror(rc, NULL));
+ return -1;
+ }
+
+ conn->handle = NULL;
+ return 0;
+}
+
+
+void Curl_qsossl_close(struct connectdata *conn, int sockindex)
+
+{
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(connssl->use)
+ (void) Curl_qsossl_close_one(connssl, data);
+}
+
+
+int Curl_qsossl_close_all(struct SessionHandle * data)
+
+{
+ /* Unimplemented. */
+ (void) data;
+ return 0;
+}
+
+
+int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex)
+
+{
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+ struct SessionHandle *data = conn->data;
+ ssize_t nread;
+ int what;
+ int rc;
+ char buf[120];
+
+ if(!connssl->handle)
+ return 0;
+
+ if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
+ return 0;
+
+ if(Curl_qsossl_close_one(connssl, data))
+ return -1;
+
+ rc = 0;
+
+ what = Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
+
+ for(;;) {
+ if(what < 0) {
+ /* anything that gets here is fatally bad */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ rc = -1;
+ break;
+ }
+
+ if(!what) { /* timeout */
+ failf(data, "SSL shutdown timeout");
+ break;
+ }
+
+ /* Something to read, let's do it and hope that it is the close
+ notify alert from the server. No way to SSL_Read now, so use read(). */
+
+ nread = read(conn->sock[sockindex], buf, sizeof(buf));
+
+ if(nread < 0) {
+ failf(data, "read: %s", strerror(errno));
+ rc = -1;
+ }
+
+ if(nread <= 0)
+ break;
+
+ what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
+ }
+
+ return rc;
+}
+
+
+static ssize_t qsossl_send(struct connectdata * conn, int sockindex,
+ const void * mem, size_t len, CURLcode * curlcode)
+
+{
+ /* SSL_Write() is said to return 'int' while write() and send() returns
+ 'size_t' */
+ int rc;
+
+ rc = SSL_Write(conn->ssl[sockindex].handle, (void *) mem, (int) len);
+
+ if(rc < 0) {
+ switch(rc) {
+
+ case SSL_ERROR_BAD_STATE:
+ /* The operation did not complete; the same SSL I/O function
+ should be called again later. This is basically an EWOULDBLOCK
+ equivalent. */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+
+ case SSL_ERROR_IO:
+ switch (errno) {
+ case EWOULDBLOCK:
+ case EINTR:
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ }
+
+ failf(conn->data, "SSL_Write() I/O error: %s", strerror(errno));
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ /* An SSL error. */
+ failf(conn->data, "SSL_Write() returned error %s",
+ SSL_Strerror(rc, NULL));
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+
+ return (ssize_t) rc; /* number of bytes */
+}
+
+
+static ssize_t qsossl_recv(struct connectdata * conn, int num, char * buf,
+ size_t buffersize, CURLcode * curlcode)
+
+{
+ char error_buffer[120]; /* OpenSSL documents that this must be at
+ least 120 bytes long. */
+ unsigned long sslerror;
+ int buffsize;
+ int nread;
+
+ buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ nread = SSL_Read(conn->ssl[num].handle, buf, buffsize);
+
+ if(nread < 0) {
+ /* failed SSL_read */
+
+ switch (nread) {
+
+ case SSL_ERROR_BAD_STATE:
+ /* there's data pending, re-invoke SSL_Read(). */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+
+ case SSL_ERROR_IO:
+ switch (errno) {
+ case EWOULDBLOCK:
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ }
+
+ failf(conn->data, "SSL_Read() I/O error: %s", strerror(errno));
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+
+ default:
+ failf(conn->data, "SSL read error: %s", SSL_Strerror(nread, NULL));
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+ }
+ return (ssize_t) nread;
+}
+
+
+size_t Curl_qsossl_version(char * buffer, size_t size)
+
+{
+ strncpy(buffer, "IBM OS/400 SSL", size);
+ return strlen(buffer);
+}
+
+
+int Curl_qsossl_check_cxn(struct connectdata * cxn)
+
+{
+ int err;
+ int errlen;
+
+ /* The only thing that can be tested here is at the socket level. */
+
+ if(!cxn->ssl[FIRSTSOCKET].handle)
+ return 0; /* connection has been closed */
+
+ err = 0;
+ errlen = sizeof err;
+
+ if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
+ (unsigned char *) &err, &errlen) ||
+ errlen != sizeof err || err)
+ return 0; /* connection has been closed */
+
+ return -1; /* connection status unknown */
+}
+
+#endif /* USE_QSOSSL */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/qssl.h b/external/libcurl_android/jni/libcurl/lib/vtls/qssl.h
new file mode 100755
index 00000000..9764eecb
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/qssl.h
@@ -0,0 +1,62 @@
+#ifndef HEADER_CURL_QSSL_H
+#define HEADER_CURL_QSSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/*
+ * This header should only be needed to get included by vtls.c and qssl.c
+ */
+
+#include "urldata.h"
+
+#ifdef USE_QSOSSL
+int Curl_qsossl_init(void);
+void Curl_qsossl_cleanup(void);
+CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex);
+void Curl_qsossl_close(struct connectdata *conn, int sockindex);
+int Curl_qsossl_close_all(struct SessionHandle * data);
+int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex);
+
+size_t Curl_qsossl_version(char * buffer, size_t size);
+int Curl_qsossl_check_cxn(struct connectdata * cxn);
+
+/* API setup for QsoSSL */
+#define curlssl_init Curl_qsossl_init
+#define curlssl_cleanup Curl_qsossl_cleanup
+#define curlssl_connect Curl_qsossl_connect
+
+/* No session handling for QsoSSL */
+#define curlssl_session_free(x) Curl_nop_stmt
+#define curlssl_close_all Curl_qsossl_close_all
+#define curlssl_close Curl_qsossl_close
+#define curlssl_shutdown(x,y) Curl_qsossl_shutdown(x,y)
+#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN
+#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN
+#define curlssl_engines_list(x) NULL
+#define curlssl_version Curl_qsossl_version
+#define curlssl_check_cxn(x) Curl_qsossl_check_cxn(x)
+#define curlssl_data_pending(x,y) 0
+#define CURL_SSL_BACKEND CURLSSLBACKEND_QSOSSL
+#endif /* USE_QSOSSL */
+
+#endif /* HEADER_CURL_QSSL_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/vtls.c b/external/libcurl_android/jni/libcurl/lib/vtls/vtls.c
new file mode 100755
index 00000000..88511b8b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/vtls.c
@@ -0,0 +1,705 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This file is for implementing all "generic" SSL functions that all libcurl
+ internals should use. It is then responsible for calling the proper
+ "backend" function.
+
+ SSL-functions in libcurl should call functions in this source file, and not
+ to any specific SSL-layer.
+
+ Curl_ssl_ - prefix for generic ones
+ Curl_ossl_ - prefix for OpenSSL ones
+ Curl_gtls_ - prefix for GnuTLS ones
+ Curl_nss_ - prefix for NSS ones
+ Curl_qssl_ - prefix for QsoSSL ones
+ Curl_gskit_ - prefix for GSKit ones
+ Curl_polarssl_ - prefix for PolarSSL ones
+ Curl_cyassl_ - prefix for CyaSSL ones
+ Curl_schannel_ - prefix for Schannel SSPI ones
+ Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones
+
+ Note that this source code uses curlssl_* functions, and they are all
+ defines/macros #defined by the lib-specific header files.
+
+ "SSL/TLS Strong Encryption: An Introduction"
+ http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html
+*/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "urldata.h"
+
+#include "vtls.h" /* generic SSL protos etc */
+#include "openssl.h" /* OpenSSL versions */
+#include "gtls.h" /* GnuTLS versions */
+#include "nssg.h" /* NSS versions */
+#include "qssl.h" /* QSOSSL versions */
+#include "gskit.h" /* Global Secure ToolKit versions */
+#include "polarssl.h" /* PolarSSL versions */
+#include "axtls.h" /* axTLS versions */
+#include "cyassl.h" /* CyaSSL versions */
+#include "curl_schannel.h" /* Schannel SSPI version */
+#include "curl_darwinssl.h" /* SecureTransport (Darwin) version */
+#include "slist.h"
+#include "sendf.h"
+#include "rawstr.h"
+#include "url.h"
+#include "curl_memory.h"
+#include "progress.h"
+#include "share.h"
+#include "timeval.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* convenience macro to check if this handle is using a shared SSL session */
+#define SSLSESSION_SHARED(data) (data->share && \
+ (data->share->specifier & \
+ (1<<CURL_LOCK_DATA_SSL_SESSION)))
+
+static bool safe_strequal(char* str1, char* str2)
+{
+ if(str1 && str2)
+ /* both pointers point to something then compare them */
+ return (0 != Curl_raw_equal(str1, str2)) ? TRUE : FALSE;
+ else
+ /* if both pointers are NULL then treat them as equal */
+ return (!str1 && !str2) ? TRUE : FALSE;
+}
+
+bool
+Curl_ssl_config_matches(struct ssl_config_data* data,
+ struct ssl_config_data* needle)
+{
+ if((data->version == needle->version) &&
+ (data->verifypeer == needle->verifypeer) &&
+ (data->verifyhost == needle->verifyhost) &&
+ safe_strequal(data->CApath, needle->CApath) &&
+ safe_strequal(data->CAfile, needle->CAfile) &&
+ safe_strequal(data->random_file, needle->random_file) &&
+ safe_strequal(data->egdsocket, needle->egdsocket) &&
+ safe_strequal(data->cipher_list, needle->cipher_list))
+ return TRUE;
+
+ return FALSE;
+}
+
+bool
+Curl_clone_ssl_config(struct ssl_config_data *source,
+ struct ssl_config_data *dest)
+{
+ dest->sessionid = source->sessionid;
+ dest->verifyhost = source->verifyhost;
+ dest->verifypeer = source->verifypeer;
+ dest->version = source->version;
+
+ if(source->CAfile) {
+ dest->CAfile = strdup(source->CAfile);
+ if(!dest->CAfile)
+ return FALSE;
+ }
+ else
+ dest->CAfile = NULL;
+
+ if(source->CApath) {
+ dest->CApath = strdup(source->CApath);
+ if(!dest->CApath)
+ return FALSE;
+ }
+ else
+ dest->CApath = NULL;
+
+ if(source->cipher_list) {
+ dest->cipher_list = strdup(source->cipher_list);
+ if(!dest->cipher_list)
+ return FALSE;
+ }
+ else
+ dest->cipher_list = NULL;
+
+ if(source->egdsocket) {
+ dest->egdsocket = strdup(source->egdsocket);
+ if(!dest->egdsocket)
+ return FALSE;
+ }
+ else
+ dest->egdsocket = NULL;
+
+ if(source->random_file) {
+ dest->random_file = strdup(source->random_file);
+ if(!dest->random_file)
+ return FALSE;
+ }
+ else
+ dest->random_file = NULL;
+
+ return TRUE;
+}
+
+void Curl_free_ssl_config(struct ssl_config_data* sslc)
+{
+ Curl_safefree(sslc->CAfile);
+ Curl_safefree(sslc->CApath);
+ Curl_safefree(sslc->cipher_list);
+ Curl_safefree(sslc->egdsocket);
+ Curl_safefree(sslc->random_file);
+}
+
+
+/*
+ * Curl_rand() returns a random unsigned integer, 32bit.
+ *
+ * This non-SSL function is put here only because this file is the only one
+ * with knowledge of what the underlying SSL libraries provide in terms of
+ * randomizers.
+ *
+ * NOTE: 'data' may be passed in as NULL when coming from external API without
+ * easy handle!
+ *
+ */
+
+unsigned int Curl_rand(struct SessionHandle *data)
+{
+ unsigned int r;
+ static unsigned int randseed;
+ static bool seeded = FALSE;
+
+#ifdef CURLDEBUG
+ char *force_entropy = getenv("CURL_ENTROPY");
+ if(force_entropy) {
+ if(!seeded) {
+ size_t elen = strlen(force_entropy);
+ size_t clen = sizeof(randseed);
+ size_t min = elen < clen ? elen : clen;
+ memcpy((char *)&randseed, force_entropy, min);
+ seeded = TRUE;
+ }
+ else
+ randseed++;
+ return randseed;
+ }
+#endif
+
+ /* data may be NULL! */
+ if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)))
+ return r;
+
+ /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we
+ instead perform a "best effort" */
+
+#ifdef RANDOM_FILE
+ if(!seeded) {
+ /* if there's a random file to read a seed from, use it */
+ int fd = open(RANDOM_FILE, O_RDONLY);
+ if(fd > -1) {
+ /* read random data into the randseed variable */
+ ssize_t nread = read(fd, &randseed, sizeof(randseed));
+ if(nread == sizeof(randseed))
+ seeded = TRUE;
+ close(fd);
+ }
+ }
+#endif
+
+ if(!seeded) {
+ struct timeval now = curlx_tvnow();
+ infof(data, "WARNING: Using weak random seed\n");
+ randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
+ randseed = randseed * 1103515245 + 12345;
+ randseed = randseed * 1103515245 + 12345;
+ randseed = randseed * 1103515245 + 12345;
+ seeded = TRUE;
+ }
+
+ /* Return an unsigned 32-bit pseudo-random number. */
+ r = randseed = randseed * 1103515245 + 12345;
+ return (r << 16) | ((r >> 16) & 0xFFFF);
+}
+
+int Curl_ssl_backend(void)
+{
+ return (int)CURL_SSL_BACKEND;
+}
+
+#ifdef USE_SSL
+
+/* "global" init done? */
+static bool init_ssl=FALSE;
+
+/**
+ * Global SSL init
+ *
+ * @retval 0 error initializing SSL
+ * @retval 1 SSL initialized successfully
+ */
+int Curl_ssl_init(void)
+{
+ /* make sure this is only done once */
+ if(init_ssl)
+ return 1;
+ init_ssl = TRUE; /* never again */
+
+ return curlssl_init();
+}
+
+
+/* Global cleanup */
+void Curl_ssl_cleanup(void)
+{
+ if(init_ssl) {
+ /* only cleanup if we did a previous init */
+ curlssl_cleanup();
+ init_ssl = FALSE;
+ }
+}
+
+CURLcode
+Curl_ssl_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode res;
+ /* mark this is being ssl-enabled from here on. */
+ conn->ssl[sockindex].use = TRUE;
+ conn->ssl[sockindex].state = ssl_connection_negotiating;
+
+ res = curlssl_connect(conn, sockindex);
+
+ if(!res)
+ Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
+
+ return res;
+}
+
+CURLcode
+Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
+ bool *done)
+{
+ CURLcode res;
+ /* mark this is being ssl requested from here on. */
+ conn->ssl[sockindex].use = TRUE;
+#ifdef curlssl_connect_nonblocking
+ res = curlssl_connect_nonblocking(conn, sockindex, done);
+#else
+ *done = TRUE; /* fallback to BLOCKING */
+ res = curlssl_connect(conn, sockindex);
+#endif /* non-blocking connect support */
+ if(!res && *done)
+ Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
+ return res;
+}
+
+/*
+ * Check if there's a session ID for the given connection in the cache, and if
+ * there's one suitable, it is provided. Returns TRUE when no entry matched.
+ */
+int Curl_ssl_getsessionid(struct connectdata *conn,
+ void **ssl_sessionid,
+ size_t *idsize) /* set 0 if unknown */
+{
+ struct curl_ssl_session *check;
+ struct SessionHandle *data = conn->data;
+ size_t i;
+ long *general_age;
+ bool no_match = TRUE;
+
+ *ssl_sessionid = NULL;
+
+ if(!conn->ssl_config.sessionid)
+ /* session ID re-use is disabled */
+ return TRUE;
+
+ /* Lock if shared */
+ if(SSLSESSION_SHARED(data)) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+ general_age = &data->share->sessionage;
+ }
+ else
+ general_age = &data->state.sessionage;
+
+ for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+ check = &data->state.session[i];
+ if(!check->sessionid)
+ /* not session ID means blank entry */
+ continue;
+ if(Curl_raw_equal(conn->host.name, check->name) &&
+ (conn->remote_port == check->remote_port) &&
+ Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
+ /* yes, we have a session ID! */
+ (*general_age)++; /* increase general age */
+ check->age = *general_age; /* set this as used in this age */
+ *ssl_sessionid = check->sessionid;
+ if(idsize)
+ *idsize = check->idsize;
+ no_match = FALSE;
+ break;
+ }
+ }
+
+ /* Unlock */
+ if(SSLSESSION_SHARED(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+
+ return no_match;
+}
+
+/*
+ * Kill a single session ID entry in the cache.
+ */
+void Curl_ssl_kill_session(struct curl_ssl_session *session)
+{
+ if(session->sessionid) {
+ /* defensive check */
+
+ /* free the ID the SSL-layer specific way */
+ curlssl_session_free(session->sessionid);
+
+ session->sessionid = NULL;
+ session->age = 0; /* fresh */
+
+ Curl_free_ssl_config(&session->ssl_config);
+
+ Curl_safefree(session->name);
+ }
+}
+
+/*
+ * Delete the given session ID from the cache.
+ */
+void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
+{
+ size_t i;
+ struct SessionHandle *data=conn->data;
+
+ if(SSLSESSION_SHARED(data))
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+
+ for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+ struct curl_ssl_session *check = &data->state.session[i];
+
+ if(check->sessionid == ssl_sessionid) {
+ Curl_ssl_kill_session(check);
+ break;
+ }
+ }
+
+ if(SSLSESSION_SHARED(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+}
+
+/*
+ * Store session id in the session cache. The ID passed on to this function
+ * must already have been extracted and allocated the proper way for the SSL
+ * layer. Curl_XXXX_session_free() will be called to free/kill the session ID
+ * later on.
+ */
+CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+ void *ssl_sessionid,
+ size_t idsize)
+{
+ size_t i;
+ struct SessionHandle *data=conn->data; /* the mother of all structs */
+ struct curl_ssl_session *store = &data->state.session[0];
+ long oldest_age=data->state.session[0].age; /* zero if unused */
+ char *clone_host;
+ long *general_age;
+
+ /* Even though session ID re-use might be disabled, that only disables USING
+ IT. We still store it here in case the re-using is again enabled for an
+ upcoming transfer */
+
+ clone_host = strdup(conn->host.name);
+ if(!clone_host)
+ return CURLE_OUT_OF_MEMORY; /* bail out */
+
+ /* Now we should add the session ID and the host name to the cache, (remove
+ the oldest if necessary) */
+
+ /* If using shared SSL session, lock! */
+ if(SSLSESSION_SHARED(data)) {
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+ general_age = &data->share->sessionage;
+ }
+ else {
+ general_age = &data->state.sessionage;
+ }
+
+ /* find an empty slot for us, or find the oldest */
+ for(i = 1; (i < data->set.ssl.max_ssl_sessions) &&
+ data->state.session[i].sessionid; i++) {
+ if(data->state.session[i].age < oldest_age) {
+ oldest_age = data->state.session[i].age;
+ store = &data->state.session[i];
+ }
+ }
+ if(i == data->set.ssl.max_ssl_sessions)
+ /* cache is full, we must "kill" the oldest entry! */
+ Curl_ssl_kill_session(store);
+ else
+ store = &data->state.session[i]; /* use this slot */
+
+ /* now init the session struct wisely */
+ store->sessionid = ssl_sessionid;
+ store->idsize = idsize;
+ store->age = *general_age; /* set current age */
+ if(store->name)
+ /* free it if there's one already present */
+ free(store->name);
+ store->name = clone_host; /* clone host name */
+ store->remote_port = conn->remote_port; /* port number */
+
+
+ /* Unlock */
+ if(SSLSESSION_SHARED(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
+
+ if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
+ store->sessionid = NULL; /* let caller free sessionid */
+ free(clone_host);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ return CURLE_OK;
+}
+
+
+void Curl_ssl_close_all(struct SessionHandle *data)
+{
+ size_t i;
+ /* kill the session ID cache if not shared */
+ if(data->state.session && !SSLSESSION_SHARED(data)) {
+ for(i = 0; i < data->set.ssl.max_ssl_sessions; i++)
+ /* the single-killer function handles empty table slots */
+ Curl_ssl_kill_session(&data->state.session[i]);
+
+ /* free the cache data */
+ Curl_safefree(data->state.session);
+ }
+
+ curlssl_close_all(data);
+}
+
+void Curl_ssl_close(struct connectdata *conn, int sockindex)
+{
+ DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
+ curlssl_close(conn, sockindex);
+}
+
+CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
+{
+ if(curlssl_shutdown(conn, sockindex))
+ return CURLE_SSL_SHUTDOWN_FAILED;
+
+ conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
+ conn->ssl[sockindex].state = ssl_connection_none;
+
+ conn->recv[sockindex] = Curl_recv_plain;
+ conn->send[sockindex] = Curl_send_plain;
+
+ return CURLE_OK;
+}
+
+/* Selects an SSL crypto engine
+ */
+CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
+{
+ return curlssl_set_engine(data, engine);
+}
+
+/* Selects the default SSL crypto engine
+ */
+CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
+{
+ return curlssl_set_engine_default(data);
+}
+
+/* Return list of OpenSSL crypto engine names. */
+struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
+{
+ return curlssl_engines_list(data);
+}
+
+/*
+ * This sets up a session ID cache to the specified size. Make sure this code
+ * is agnostic to what underlying SSL technology we use.
+ */
+CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount)
+{
+ struct curl_ssl_session *session;
+
+ if(data->state.session)
+ /* this is just a precaution to prevent multiple inits */
+ return CURLE_OK;
+
+ session = calloc(amount, sizeof(struct curl_ssl_session));
+ if(!session)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* store the info in the SSL section */
+ data->set.ssl.max_ssl_sessions = amount;
+ data->state.session = session;
+ data->state.sessionage = 1; /* this is brand new */
+ return CURLE_OK;
+}
+
+size_t Curl_ssl_version(char *buffer, size_t size)
+{
+ return curlssl_version(buffer, size);
+}
+
+/*
+ * This function tries to determine connection status.
+ *
+ * Return codes:
+ * 1 means the connection is still in place
+ * 0 means the connection has been closed
+ * -1 means the connection status is unknown
+ */
+int Curl_ssl_check_cxn(struct connectdata *conn)
+{
+ return curlssl_check_cxn(conn);
+}
+
+bool Curl_ssl_data_pending(const struct connectdata *conn,
+ int connindex)
+{
+ return curlssl_data_pending(conn, connindex);
+}
+
+void Curl_ssl_free_certinfo(struct SessionHandle *data)
+{
+ int i;
+ struct curl_certinfo *ci = &data->info.certs;
+ if(ci->num_of_certs) {
+ /* free all individual lists used */
+ for(i=0; i<ci->num_of_certs; i++) {
+ curl_slist_free_all(ci->certinfo[i]);
+ ci->certinfo[i] = NULL;
+ }
+ free(ci->certinfo); /* free the actual array too */
+ ci->certinfo = NULL;
+ ci->num_of_certs = 0;
+ }
+}
+
+int Curl_ssl_init_certinfo(struct SessionHandle * data,
+ int num)
+{
+ struct curl_certinfo * ci = &data->info.certs;
+ struct curl_slist * * table;
+
+ /* Initialize the certificate information structures. Return 0 if OK, else 1.
+ */
+ Curl_ssl_free_certinfo(data);
+ ci->num_of_certs = num;
+ table = calloc((size_t) num, sizeof(struct curl_slist *));
+ if(!table)
+ return 1;
+
+ ci->certinfo = table;
+ return 0;
+}
+
+/*
+ * 'value' is NOT a zero terminated string
+ */
+CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data,
+ int certnum,
+ const char *label,
+ const char *value,
+ size_t valuelen)
+{
+ struct curl_certinfo * ci = &data->info.certs;
+ char * output;
+ struct curl_slist * nl;
+ CURLcode res = CURLE_OK;
+ size_t labellen = strlen(label);
+ size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
+
+ output = malloc(outlen);
+ if(!output)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* sprintf the label and colon */
+ snprintf(output, outlen, "%s:", label);
+
+ /* memcpy the value (it might not be zero terminated) */
+ memcpy(&output[labellen+1], value, valuelen);
+
+ /* zero terminate the output */
+ output[labellen + 1 + valuelen] = 0;
+
+ nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
+ if(!nl) {
+ free(output);
+ curl_slist_free_all(ci->certinfo[certnum]);
+ res = CURLE_OUT_OF_MEMORY;
+ }
+
+ ci->certinfo[certnum] = nl;
+ return res;
+}
+
+/*
+ * This is a convenience function for push_certinfo_len that takes a zero
+ * terminated value.
+ */
+CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data,
+ int certnum,
+ const char *label,
+ const char *value)
+{
+ size_t valuelen = strlen(value);
+
+ return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
+}
+
+int Curl_ssl_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
+{
+ return curlssl_random(data, entropy, length);
+}
+
+#ifdef have_curlssl_md5sum
+void Curl_ssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len)
+{
+ curlssl_md5sum(tmp, tmplen, md5sum, md5len);
+}
+#endif
+
+#endif /* USE_SSL */
diff --git a/external/libcurl_android/jni/libcurl/lib/vtls/vtls.h b/external/libcurl_android/jni/libcurl/lib/vtls/vtls.h
new file mode 100755
index 00000000..e21fdef9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/vtls/vtls.h
@@ -0,0 +1,132 @@
+#ifndef HEADER_CURL_VTLS_H
+#define HEADER_CURL_VTLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifndef MD5_DIGEST_LENGTH
+#define MD5_DIGEST_LENGTH 16 /* fixed size */
+#endif
+
+/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
+#define ALPN_HTTP_1_1_LENGTH 8
+#define ALPN_HTTP_1_1 "http/1.1"
+
+bool Curl_ssl_config_matches(struct ssl_config_data* data,
+ struct ssl_config_data* needle);
+bool Curl_clone_ssl_config(struct ssl_config_data* source,
+ struct ssl_config_data* dest);
+void Curl_free_ssl_config(struct ssl_config_data* sslc);
+
+unsigned int Curl_rand(struct SessionHandle *);
+
+int Curl_ssl_backend(void);
+
+#ifdef USE_SSL
+int Curl_ssl_init(void);
+void Curl_ssl_cleanup(void);
+CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex);
+CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex,
+ bool *done);
+/* tell the SSL stuff to close down all open information regarding
+ connections (and thus session ID caching etc) */
+void Curl_ssl_close_all(struct SessionHandle *data);
+void Curl_ssl_close(struct connectdata *conn, int sockindex);
+CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex);
+CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine);
+/* Sets engine as default for all SSL operations */
+CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data);
+struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data);
+
+/* init the SSL session ID cache */
+CURLcode Curl_ssl_initsessions(struct SessionHandle *, size_t);
+size_t Curl_ssl_version(char *buffer, size_t size);
+bool Curl_ssl_data_pending(const struct connectdata *conn,
+ int connindex);
+int Curl_ssl_check_cxn(struct connectdata *conn);
+
+/* Certificate information list handling. */
+
+void Curl_ssl_free_certinfo(struct SessionHandle *data);
+int Curl_ssl_init_certinfo(struct SessionHandle * data, int num);
+CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle * data, int certnum,
+ const char * label, const char * value,
+ size_t valuelen);
+CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum,
+ const char * label, const char * value);
+
+/* Functions to be used by SSL library adaptation functions */
+
+/* extract a session ID */
+int Curl_ssl_getsessionid(struct connectdata *conn,
+ void **ssl_sessionid,
+ size_t *idsize) /* set 0 if unknown */;
+/* add a new session ID */
+CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+ void *ssl_sessionid,
+ size_t idsize);
+/* Kill a single session ID entry in the cache */
+void Curl_ssl_kill_session(struct curl_ssl_session *session);
+/* delete a session from the cache */
+void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
+
+/* get N random bytes into the buffer, return 0 if a find random is filled
+ in */
+int Curl_ssl_random(struct SessionHandle *data, unsigned char *buffer,
+ size_t length);
+void Curl_ssl_md5sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *md5sum, /* output */
+ size_t md5len);
+
+#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
+
+#ifdef have_curlssl_md5sum
+#define HAVE_CURL_SSL_MD5SUM
+#endif
+
+#else
+/* When SSL support is not present, just define away these function calls */
+#define Curl_ssl_init() 1
+#define Curl_ssl_cleanup() Curl_nop_stmt
+#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_close_all(x) Curl_nop_stmt
+#define Curl_ssl_close(x,y) Curl_nop_stmt
+#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN
+#define Curl_ssl_engines_list(x) NULL
+#define Curl_ssl_send(a,b,c,d,e) -1
+#define Curl_ssl_recv(a,b,c,d,e) -1
+#define Curl_ssl_initsessions(x,y) CURLE_OK
+#define Curl_ssl_version(x,y) 0
+#define Curl_ssl_data_pending(x,y) 0
+#define Curl_ssl_check_cxn(x) 0
+#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
+#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN
+#define Curl_ssl_kill_session(x) Curl_nop_stmt
+#define Curl_ssl_random(x,y,z) CURLE_NOT_BUILT_IN
+#define CURL_SSL_BACKEND CURLSSLBACKEND_NONE
+#endif
+
+#endif /* HEADER_CURL_VTLS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/warnless.c b/external/libcurl_android/jni/libcurl/lib/warnless.c
new file mode 100755
index 00000000..8c130d34
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/warnless.c
@@ -0,0 +1,486 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(__INTEL_COMPILER) && defined(__unix__)
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#endif /* __INTEL_COMPILER && __unix__ */
+
+#define BUILDING_WARNLESS_C 1
+
+#include "warnless.h"
+
+#define CURL_MASK_SCHAR 0x7F
+#define CURL_MASK_UCHAR 0xFF
+
+#if (SIZEOF_SHORT == 2)
+# define CURL_MASK_SSHORT 0x7FFF
+# define CURL_MASK_USHORT 0xFFFF
+#elif (SIZEOF_SHORT == 4)
+# define CURL_MASK_SSHORT 0x7FFFFFFF
+# define CURL_MASK_USHORT 0xFFFFFFFF
+#elif (SIZEOF_SHORT == 8)
+# define CURL_MASK_SSHORT 0x7FFFFFFFFFFFFFFF
+# define CURL_MASK_USHORT 0xFFFFFFFFFFFFFFFF
+#else
+# error "SIZEOF_SHORT not defined"
+#endif
+
+#if (SIZEOF_INT == 2)
+# define CURL_MASK_SINT 0x7FFF
+# define CURL_MASK_UINT 0xFFFF
+#elif (SIZEOF_INT == 4)
+# define CURL_MASK_SINT 0x7FFFFFFF
+# define CURL_MASK_UINT 0xFFFFFFFF
+#elif (SIZEOF_INT == 8)
+# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFF
+# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFF
+#elif (SIZEOF_INT == 16)
+# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+#else
+# error "SIZEOF_INT not defined"
+#endif
+
+#if (CURL_SIZEOF_LONG == 2)
+# define CURL_MASK_SLONG 0x7FFFL
+# define CURL_MASK_ULONG 0xFFFFUL
+#elif (CURL_SIZEOF_LONG == 4)
+# define CURL_MASK_SLONG 0x7FFFFFFFL
+# define CURL_MASK_ULONG 0xFFFFFFFFUL
+#elif (CURL_SIZEOF_LONG == 8)
+# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL
+# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL
+#elif (CURL_SIZEOF_LONG == 16)
+# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL
+# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL
+#else
+# error "CURL_SIZEOF_LONG not defined"
+#endif
+
+#if (CURL_SIZEOF_CURL_OFF_T == 2)
+# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFF)
+# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFF)
+#elif (CURL_SIZEOF_CURL_OFF_T == 4)
+# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFF)
+# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFF)
+#elif (CURL_SIZEOF_CURL_OFF_T == 8)
+# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
+# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF)
+#elif (CURL_SIZEOF_CURL_OFF_T == 16)
+# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
+# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
+#else
+# error "CURL_SIZEOF_CURL_OFF_T not defined"
+#endif
+
+#if (SIZEOF_SIZE_T == SIZEOF_SHORT)
+# define CURL_MASK_SSIZE_T CURL_MASK_SSHORT
+# define CURL_MASK_USIZE_T CURL_MASK_USHORT
+#elif (SIZEOF_SIZE_T == SIZEOF_INT)
+# define CURL_MASK_SSIZE_T CURL_MASK_SINT
+# define CURL_MASK_USIZE_T CURL_MASK_UINT
+#elif (SIZEOF_SIZE_T == CURL_SIZEOF_LONG)
+# define CURL_MASK_SSIZE_T CURL_MASK_SLONG
+# define CURL_MASK_USIZE_T CURL_MASK_ULONG
+#elif (SIZEOF_SIZE_T == CURL_SIZEOF_CURL_OFF_T)
+# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT
+# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT
+#else
+# error "SIZEOF_SIZE_T not defined"
+#endif
+
+/*
+** unsigned long to unsigned short
+*/
+
+unsigned short curlx_ultous(unsigned long ulnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_USHORT);
+ return (unsigned short)(ulnum & (unsigned long) CURL_MASK_USHORT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned long to unsigned char
+*/
+
+unsigned char curlx_ultouc(unsigned long ulnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_UCHAR);
+ return (unsigned char)(ulnum & (unsigned long) CURL_MASK_UCHAR);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned long to signed int
+*/
+
+int curlx_ultosi(unsigned long ulnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_SINT);
+ return (int)(ulnum & (unsigned long) CURL_MASK_SINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to signed curl_off_t
+*/
+
+curl_off_t curlx_uztoso(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT);
+ return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to signed int
+*/
+
+int curlx_uztosi(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_SINT);
+ return (int)(uznum & (size_t) CURL_MASK_SINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to unsigned long
+*/
+
+unsigned long curlx_uztoul(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+#if (CURL_SIZEOF_LONG < SIZEOF_SIZE_T)
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG);
+#endif
+ return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to unsigned int
+*/
+
+unsigned int curlx_uztoui(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+#if (SIZEOF_INT < SIZEOF_SIZE_T)
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_UINT);
+#endif
+ return (unsigned int)(uznum & (size_t) CURL_MASK_UINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed long to signed int
+*/
+
+int curlx_sltosi(long slnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(slnum >= 0);
+#if (SIZEOF_INT < CURL_SIZEOF_LONG)
+ DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT);
+#endif
+ return (int)(slnum & (long) CURL_MASK_SINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed long to unsigned int
+*/
+
+unsigned int curlx_sltoui(long slnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(slnum >= 0);
+#if (SIZEOF_INT < CURL_SIZEOF_LONG)
+ DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT);
+#endif
+ return (unsigned int)(slnum & (long) CURL_MASK_UINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed long to unsigned short
+*/
+
+unsigned short curlx_sltous(long slnum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(slnum >= 0);
+ DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_USHORT);
+ return (unsigned short)(slnum & (long) CURL_MASK_USHORT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** unsigned size_t to signed ssize_t
+*/
+
+ssize_t curlx_uztosz(size_t uznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(uznum <= (size_t) CURL_MASK_SSIZE_T);
+ return (ssize_t)(uznum & (size_t) CURL_MASK_SSIZE_T);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed curl_off_t to unsigned size_t
+*/
+
+size_t curlx_sotouz(curl_off_t sonum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(sonum >= 0);
+ return (size_t)(sonum & (curl_off_t) CURL_MASK_USIZE_T);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed ssize_t to signed int
+*/
+
+int curlx_sztosi(ssize_t sznum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(sznum >= 0);
+#if (SIZEOF_INT < SIZEOF_SIZE_T)
+ DEBUGASSERT((size_t) sznum <= (size_t) CURL_MASK_SINT);
+#endif
+ return (int)(sznum & (ssize_t) CURL_MASK_SINT);
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+/*
+** signed int to unsigned size_t
+*/
+
+size_t curlx_sitouz(int sinum)
+{
+#ifdef __INTEL_COMPILER
+# pragma warning(push)
+# pragma warning(disable:810) /* conversion may lose significant bits */
+#endif
+
+ DEBUGASSERT(sinum >= 0);
+ return (size_t) sinum;
+
+#ifdef __INTEL_COMPILER
+# pragma warning(pop)
+#endif
+}
+
+#ifdef USE_WINSOCK
+
+/*
+** curl_socket_t to signed int
+*/
+
+int curlx_sktosi(curl_socket_t s)
+{
+ return (int)((ssize_t) s);
+}
+
+/*
+** signed int to curl_socket_t
+*/
+
+curl_socket_t curlx_sitosk(int i)
+{
+ return (curl_socket_t)((ssize_t) i);
+}
+
+#endif /* USE_WINSOCK */
+
+#if defined(WIN32) || defined(_WIN32)
+
+ssize_t curlx_read(int fd, void *buf, size_t count)
+{
+ return (ssize_t)read(fd, buf, curlx_uztoui(count));
+}
+
+ssize_t curlx_write(int fd, const void *buf, size_t count)
+{
+ return (ssize_t)write(fd, buf, curlx_uztoui(count));
+}
+
+#endif /* WIN32 || _WIN32 */
+
+#if defined(__INTEL_COMPILER) && defined(__unix__)
+
+int curlx_FD_ISSET(int fd, fd_set *fdset)
+{
+ #pragma warning(push)
+ #pragma warning(disable:1469) /* clobber ignored */
+ return FD_ISSET(fd, fdset);
+ #pragma warning(pop)
+}
+
+void curlx_FD_SET(int fd, fd_set *fdset)
+{
+ #pragma warning(push)
+ #pragma warning(disable:1469) /* clobber ignored */
+ FD_SET(fd, fdset);
+ #pragma warning(pop)
+}
+
+void curlx_FD_ZERO(fd_set *fdset)
+{
+ #pragma warning(push)
+ #pragma warning(disable:593) /* variable was set but never used */
+ FD_ZERO(fdset);
+ #pragma warning(pop)
+}
+
+unsigned short curlx_htons(unsigned short usnum)
+{
+#if (__INTEL_COMPILER == 910) && defined(__i386__)
+ return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF));
+#else
+ #pragma warning(push)
+ #pragma warning(disable:810) /* conversion may lose significant bits */
+ return htons(usnum);
+ #pragma warning(pop)
+#endif
+}
+
+unsigned short curlx_ntohs(unsigned short usnum)
+{
+#if (__INTEL_COMPILER == 910) && defined(__i386__)
+ return (unsigned short)(((usnum << 8) & 0xFF00) | ((usnum >> 8) & 0x00FF));
+#else
+ #pragma warning(push)
+ #pragma warning(disable:810) /* conversion may lose significant bits */
+ return ntohs(usnum);
+ #pragma warning(pop)
+#endif
+}
+
+#endif /* __INTEL_COMPILER && __unix__ */
diff --git a/external/libcurl_android/jni/libcurl/lib/warnless.h b/external/libcurl_android/jni/libcurl/lib/warnless.h
new file mode 100755
index 00000000..ad77d3c2
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/warnless.h
@@ -0,0 +1,107 @@
+#ifndef HEADER_CURL_WARNLESS_H
+#define HEADER_CURL_WARNLESS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifdef USE_WINSOCK
+#include <curl/curl.h> /* for curl_socket_t */
+#endif
+
+unsigned short curlx_ultous(unsigned long ulnum);
+
+unsigned char curlx_ultouc(unsigned long ulnum);
+
+int curlx_ultosi(unsigned long ulnum);
+
+int curlx_uztosi(size_t uznum);
+
+curl_off_t curlx_uztoso(size_t uznum);
+
+unsigned long curlx_uztoul(size_t uznum);
+
+unsigned int curlx_uztoui(size_t uznum);
+
+int curlx_sltosi(long slnum);
+
+unsigned int curlx_sltoui(long slnum);
+
+unsigned short curlx_sltous(long slnum);
+
+ssize_t curlx_uztosz(size_t uznum);
+
+size_t curlx_sotouz(curl_off_t sonum);
+
+int curlx_sztosi(ssize_t sznum);
+
+size_t curlx_sitouz(int sinum);
+
+#ifdef USE_WINSOCK
+
+int curlx_sktosi(curl_socket_t s);
+
+curl_socket_t curlx_sitosk(int i);
+
+#endif /* USE_WINSOCK */
+
+#if defined(WIN32) || defined(_WIN32)
+
+ssize_t curlx_read(int fd, void *buf, size_t count);
+
+ssize_t curlx_write(int fd, const void *buf, size_t count);
+
+#ifndef BUILDING_WARNLESS_C
+# undef read
+# define read(fd, buf, count) curlx_read(fd, buf, count)
+# undef write
+# define write(fd, buf, count) curlx_write(fd, buf, count)
+#endif
+
+#endif /* WIN32 || _WIN32 */
+
+#if defined(__INTEL_COMPILER) && defined(__unix__)
+
+int curlx_FD_ISSET(int fd, fd_set *fdset);
+
+void curlx_FD_SET(int fd, fd_set *fdset);
+
+void curlx_FD_ZERO(fd_set *fdset);
+
+unsigned short curlx_htons(unsigned short usnum);
+
+unsigned short curlx_ntohs(unsigned short usnum);
+
+#ifndef BUILDING_WARNLESS_C
+# undef FD_ISSET
+# define FD_ISSET(a,b) curlx_FD_ISSET((a),(b))
+# undef FD_SET
+# define FD_SET(a,b) curlx_FD_SET((a),(b))
+# undef FD_ZERO
+# define FD_ZERO(a) curlx_FD_ZERO((a))
+# undef htons
+# define htons(a) curlx_htons((a))
+# undef ntohs
+# define ntohs(a) curlx_ntohs((a))
+#endif
+
+#endif /* __INTEL_COMPILER && __unix__ */
+
+#endif /* HEADER_CURL_WARNLESS_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/wildcard.c b/external/libcurl_android/jni/libcurl/lib/wildcard.c
new file mode 100755
index 00000000..7130d5e4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/wildcard.c
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include "wildcard.h"
+#include "llist.h"
+#include "fileinfo.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+CURLcode Curl_wildcard_init(struct WildcardData *wc)
+{
+ DEBUGASSERT(wc->filelist == NULL);
+ /* now allocate only wc->filelist, everything else
+ will be allocated if it is needed. */
+ wc->filelist = Curl_llist_alloc(Curl_fileinfo_dtor);
+ if(!wc->filelist) {;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
+void Curl_wildcard_dtor(struct WildcardData *wc)
+{
+ if(!wc)
+ return;
+
+ if(wc->tmp_dtor) {
+ wc->tmp_dtor(wc->tmp);
+ wc->tmp_dtor = ZERO_NULL;
+ wc->tmp = NULL;
+ }
+ DEBUGASSERT(wc->tmp == NULL);
+
+ if(wc->filelist) {
+ Curl_llist_destroy(wc->filelist, NULL);
+ wc->filelist = NULL;
+ }
+
+ if(wc->path) {
+ free(wc->path);
+ wc->path = NULL;
+ }
+
+ if(wc->pattern) {
+ free(wc->pattern);
+ wc->pattern = NULL;
+ }
+
+ wc->customptr = NULL;
+ wc->state = CURLWC_INIT;
+}
diff --git a/external/libcurl_android/jni/libcurl/lib/wildcard.h b/external/libcurl_android/jni/libcurl/lib/wildcard.h
new file mode 100755
index 00000000..16c80ecb
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/wildcard.h
@@ -0,0 +1,58 @@
+#ifndef HEADER_CURL_WILDCARD_H
+#define HEADER_CURL_WILDCARD_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curl.h>
+
+/* list of wildcard process states */
+typedef enum {
+ CURLWC_INIT = 0,
+ CURLWC_MATCHING, /* library is trying to get list of addresses for
+ downloading */
+ CURLWC_DOWNLOADING,
+ CURLWC_CLEAN, /* deallocate resources and reset settings */
+ CURLWC_SKIP, /* skip over concrete file */
+ CURLWC_ERROR, /* error cases */
+ CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop
+ will end */
+} curl_wildcard_states;
+
+typedef void (*curl_wildcard_tmp_dtor)(void *ptr);
+
+/* struct keeping information about wildcard download process */
+struct WildcardData {
+ curl_wildcard_states state;
+ char *path; /* path to the directory, where we trying wildcard-match */
+ char *pattern; /* wildcard pattern */
+ struct curl_llist *filelist; /* llist with struct Curl_fileinfo */
+ void *tmp; /* pointer to protocol specific temporary data */
+ curl_wildcard_tmp_dtor tmp_dtor;
+ void *customptr; /* for CURLOPT_CHUNK_DATA pointer */
+};
+
+CURLcode Curl_wildcard_init(struct WildcardData *wc);
+void Curl_wildcard_dtor(struct WildcardData *wc);
+
+struct SessionHandle;
+
+#endif /* HEADER_CURL_WILDCARD_H */
diff --git a/external/libcurl_android/jni/libcurl/lib/x509asn1.c b/external/libcurl_android/jni/libcurl/lib/x509asn1.c
new file mode 100755
index 00000000..1f87155a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/x509asn1.c
@@ -0,0 +1,1183 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_QSOSSL) || defined(USE_GSKIT) || defined(USE_NSS)
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "strequal.h"
+#include "hostcheck.h"
+#include "vtls/vtls.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "curl_base64.h"
+#include "x509asn1.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+
+/* ASN.1 OIDs. */
+static const char cnOID[] = "2.5.4.3"; /* Common name. */
+static const char sanOID[] = "2.5.29.17"; /* Subject alternative name. */
+
+static const curl_OID OIDtable[] = {
+ { "1.2.840.10040.4.1", "dsa" },
+ { "1.2.840.10040.4.3", "dsa-with-sha1" },
+ { "1.2.840.10045.2.1", "ecPublicKey" },
+ { "1.2.840.10045.3.0.1", "c2pnb163v1" },
+ { "1.2.840.10045.4.1", "ecdsa-with-SHA1" },
+ { "1.2.840.10046.2.1", "dhpublicnumber" },
+ { "1.2.840.113549.1.1.1", "rsaEncryption" },
+ { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" },
+ { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" },
+ { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" },
+ { "1.2.840.113549.1.1.10", "RSASSA-PSS" },
+ { "1.2.840.113549.1.1.14", "sha224WithRSAEncryption" },
+ { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" },
+ { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" },
+ { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" },
+ { "1.2.840.113549.2.2", "md2" },
+ { "1.2.840.113549.2.5", "md5" },
+ { "1.3.14.3.2.26", "sha1" },
+ { cnOID, "CN" },
+ { "2.5.4.4", "SN" },
+ { "2.5.4.5", "serialNumber" },
+ { "2.5.4.6", "C" },
+ { "2.5.4.7", "L" },
+ { "2.5.4.8", "ST" },
+ { "2.5.4.9", "streetAddress" },
+ { "2.5.4.10", "O" },
+ { "2.5.4.11", "OU" },
+ { "2.5.4.12", "title" },
+ { "2.5.4.13", "description" },
+ { "2.5.4.17", "postalCode" },
+ { "2.5.4.41", "name" },
+ { "2.5.4.42", "givenName" },
+ { "2.5.4.43", "initials" },
+ { "2.5.4.44", "generationQualifier" },
+ { "2.5.4.45", "X500UniqueIdentifier" },
+ { "2.5.4.46", "dnQualifier" },
+ { "2.5.4.65", "pseudonym" },
+ { "1.2.840.113549.1.9.1", "emailAddress" },
+ { "2.5.4.72", "role" },
+ { sanOID, "subjectAltName" },
+ { "2.5.29.18", "issuerAltName" },
+ { "2.5.29.19", "basicConstraints" },
+ { "2.16.840.1.101.3.4.2.4", "sha224" },
+ { "2.16.840.1.101.3.4.2.1", "sha256" },
+ { "2.16.840.1.101.3.4.2.2", "sha384" },
+ { "2.16.840.1.101.3.4.2.3", "sha512" },
+ { (const char *) NULL, (const char *) NULL }
+};
+
+/*
+ * Lightweight ASN.1 parser.
+ * In particular, it does not check for syntactic/lexical errors.
+ * It is intended to support certificate information gathering for SSL backends
+ * that offer a mean to get certificates as a whole, but do not supply
+ * entry points to get particular certificate sub-fields.
+ * Please note there is no pretention here to rewrite a full SSL library.
+ */
+
+
+const char * Curl_getASN1Element(curl_asn1Element * elem,
+ const char * beg, const char * end)
+{
+ unsigned char b;
+ unsigned long len;
+ curl_asn1Element lelem;
+
+ /* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg'
+ ending at `end'.
+ Returns a pointer in source string after the parsed element, or NULL
+ if an error occurs. */
+
+ if(beg >= end || !*beg)
+ return (const char *) NULL;
+
+ /* Process header byte. */
+ b = (unsigned char) *beg++;
+ elem->constructed = (b & 0x20) != 0;
+ elem->class = (b >> 6) & 3;
+ b &= 0x1F;
+ if(b == 0x1F)
+ return (const char *) NULL; /* Long tag values not supported here. */
+ elem->tag = b;
+
+ /* Process length. */
+ if(beg >= end)
+ return (const char *) NULL;
+ b = (unsigned char) *beg++;
+ if(!(b & 0x80))
+ len = b;
+ else if(!(b &= 0x7F)) {
+ /* Unspecified length. Since we have all the data, we can determine the
+ effective length by skipping element until an end element is found. */
+ if(!elem->constructed)
+ return (const char *) NULL;
+ elem->beg = beg;
+ while(beg < end && *beg) {
+ beg = Curl_getASN1Element(&lelem, beg, end);
+ if(!beg)
+ return (const char *) NULL;
+ }
+ if(beg >= end)
+ return (const char *) NULL;
+ elem->end = beg;
+ return beg + 1;
+ }
+ else if(beg + b > end)
+ return (const char *) NULL; /* Does not fit in source. */
+ else {
+ /* Get long length. */
+ len = 0;
+ do {
+ if(len & 0xFF000000L)
+ return (const char *) NULL; /* Lengths > 32 bits are not supported. */
+ len = (len << 8) | (unsigned char) *beg++;
+ } while(--b);
+ }
+ if((unsigned long) (end - beg) < len)
+ return (const char *) NULL; /* Element data does not fit in source. */
+ elem->beg = beg;
+ elem->end = beg + len;
+ return elem->end;
+}
+
+static const curl_OID * searchOID(const char * oid)
+{
+ const curl_OID * op;
+
+ /* Search the null terminated OID or OID identifier in local table.
+ Return the table entry pointer or NULL if not found. */
+
+ for(op = OIDtable; op->numoid; op++)
+ if(!strcmp(op->numoid, oid) || curl_strequal(op->textoid, oid))
+ return op;
+
+ return (const curl_OID *) NULL;
+}
+
+static const char * bool2str(const char * beg, const char * end)
+{
+ /* Convert an ASN.1 Boolean value into its string representation.
+ Return the dynamically allocated string, or NULL if source is not an
+ ASN.1 Boolean value. */
+
+ if(end - beg != 1)
+ return (const char *) NULL;
+ return strdup(*beg? "TRUE": "FALSE");
+}
+
+static const char * octet2str(const char * beg, const char * end)
+{
+ size_t n = end - beg;
+ char * buf;
+
+ /* Convert an ASN.1 octet string to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ buf = malloc(3 * n + 1);
+ if(buf)
+ for(n = 0; beg < end; n += 3)
+ snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+ return buf;
+}
+
+static const char * bit2str(const char * beg, const char * end)
+
+{
+ /* Convert an ASN.1 bit string to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(++beg > end)
+ return (const char *) NULL;
+ return octet2str(beg, end);
+}
+
+static const char * int2str(const char * beg, const char * end)
+{
+ long val = 0;
+ size_t n = end - beg;
+
+ /* Convert an ASN.1 integer value into its string representation.
+ Return the dynamically allocated string, or NULL if source is not an
+ ASN.1 integer value. */
+
+ if(!n)
+ return (const char *) NULL;
+
+ if(n > 4)
+ return octet2str(beg, end);
+
+ /* Represent integers <= 32-bit as a single value. */
+ if(*beg & 0x80)
+ val = ~val;
+
+ do
+ val = (val << 8) | *(const unsigned char *) beg++;
+ while(beg < end);
+ return curl_maprintf("%s%lx", (val < 0 || val >= 10)? "0x": "", val);
+}
+
+static ssize_t
+utf8asn1str(char * * to, int type, const char * from, const char * end)
+{
+ size_t inlength = end - from;
+ int size = 1;
+ size_t outlength;
+ int charsize;
+ unsigned int wc;
+ char * buf;
+
+ /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
+ destination buffer dynamically. The allocation size will normally be too
+ large: this is to avoid buffer overflows.
+ Terminate the string with a nul byte and return the converted
+ string length. */
+
+ *to = (char *) NULL;
+ switch (type) {
+ case CURL_ASN1_BMP_STRING:
+ size = 2;
+ break;
+ case CURL_ASN1_UNIVERSAL_STRING:
+ size = 4;
+ break;
+ case CURL_ASN1_NUMERIC_STRING:
+ case CURL_ASN1_PRINTABLE_STRING:
+ case CURL_ASN1_TELETEX_STRING:
+ case CURL_ASN1_IA5_STRING:
+ case CURL_ASN1_VISIBLE_STRING:
+ case CURL_ASN1_UTF8_STRING:
+ break;
+ default:
+ return -1; /* Conversion not supported. */
+ }
+
+ if(inlength % size)
+ return -1; /* Length inconsistent with character size. */
+ buf = malloc(4 * (inlength / size) + 1);
+ if(!buf)
+ return -1; /* Not enough memory. */
+
+ if(type == CURL_ASN1_UTF8_STRING) {
+ /* Just copy. */
+ outlength = inlength;
+ if(outlength)
+ memcpy(buf, from, outlength);
+ }
+ else {
+ for(outlength = 0; from < end;) {
+ wc = 0;
+ switch (size) {
+ case 4:
+ wc = (wc << 8) | *(const unsigned char *) from++;
+ wc = (wc << 8) | *(const unsigned char *) from++;
+ case 2:
+ wc = (wc << 8) | *(const unsigned char *) from++;
+ default: /* case 1: */
+ wc = (wc << 8) | *(const unsigned char *) from++;
+ }
+ charsize = 1;
+ if(wc >= 0x00000080) {
+ if(wc >= 0x00000800) {
+ if(wc >= 0x00010000) {
+ if(wc >= 0x00200000) {
+ free(buf);
+ return -1; /* Invalid char. size for target encoding. */
+ }
+ buf[outlength + 3] = (char) (0x80 | (wc & 0x3F));
+ wc = (wc >> 6) | 0x00010000;
+ charsize++;
+ }
+ buf[outlength + 2] = (char) (0x80 | (wc & 0x3F));
+ wc = (wc >> 6) | 0x00000800;
+ charsize++;
+ }
+ buf[outlength + 1] = (char) (0x80 | (wc & 0x3F));
+ wc = (wc >> 6) | 0x000000C0;
+ charsize++;
+ }
+ buf[outlength] = (char) wc;
+ outlength += charsize;
+ }
+ }
+ buf[outlength] = '\0';
+ *to = buf;
+ return outlength;
+}
+
+static const char * string2str(int type, const char * beg, const char * end)
+{
+ char * buf;
+
+ /* Convert an ASN.1 String into its UTF-8 string representation.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(utf8asn1str(&buf, type, beg, end) < 0)
+ return (const char *) NULL;
+ return buf;
+}
+
+static int encodeUint(char * buf, int n, unsigned int x)
+{
+ int i = 0;
+ unsigned int y = x / 10;
+
+ /* Decimal ASCII encode unsigned integer `x' in the `n'-byte buffer at `buf'.
+ Return the total number of encoded digits, even if larger than `n'. */
+
+ if(y) {
+ i += encodeUint(buf, n, y);
+ x -= y * 10;
+ }
+ if(i < n)
+ buf[i] = (char) ('0' + x);
+ i++;
+ if(i < n)
+ buf[i] = '\0'; /* Store a terminator if possible. */
+ return i;
+}
+
+static int encodeOID(char * buf, int n, const char * beg, const char * end)
+{
+ int i = 0;
+ unsigned int x;
+ unsigned int y;
+
+ /* Convert an ASN.1 OID into its dotted string representation.
+ Store the result in th `n'-byte buffer at `buf'.
+ Return the converted string length, or -1 if an error occurs. */
+
+ /* Process the first two numbers. */
+ y = *(const unsigned char *) beg++;
+ x = y / 40;
+ y -= x * 40;
+ i += encodeUint(buf + i, n - i, x);
+ if(i < n)
+ buf[i] = '.';
+ i++;
+ i += encodeUint(buf + i, n - i, y);
+
+ /* Process the trailing numbers. */
+ while(beg < end) {
+ if(i < n)
+ buf[i] = '.';
+ i++;
+ x = 0;
+ do {
+ if(x & 0xFF000000)
+ return -1;
+ y = *(const unsigned char *) beg++;
+ x = (x << 7) | (y & 0x7F);
+ } while(y & 0x80);
+ i += encodeUint(buf + i, n - i, x);
+ }
+ if(i < n)
+ buf[i] = '\0';
+ return i;
+}
+
+static const char * OID2str(const char * beg, const char * end, bool symbolic)
+{
+ char * buf = (char *) NULL;
+ const curl_OID * op;
+ int n;
+
+ /* Convert an ASN.1 OID into its dotted or symbolic string representation.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(beg < end) {
+ n = encodeOID((char *) NULL, -1, beg, end);
+ if(n >= 0) {
+ buf = malloc(n + 1);
+ if(buf) {
+ encodeOID(buf, n, beg, end);
+ buf[n] = '\0';
+
+ if(symbolic) {
+ op = searchOID(buf);
+ if(op) {
+ free(buf);
+ buf = strdup(op->textoid);
+ }
+ }
+ }
+ }
+ }
+ return buf;
+}
+
+static const char * GTime2str(const char * beg, const char * end)
+{
+ const char * tzp;
+ const char * fracp;
+ char sec1, sec2;
+ size_t fracl;
+ size_t tzl;
+ const char * sep = "";
+
+ /* Convert an ASN.1 Generalized time to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ for(fracp = beg; fracp < end && *fracp >= '0' && *fracp <= '9'; fracp++)
+ ;
+
+ /* Get seconds digits. */
+ sec1 = '0';
+ switch (fracp - beg - 12) {
+ case 0:
+ sec2 = '0';
+ break;
+ case 2:
+ sec1 = fracp[-2];
+ case 1:
+ sec2 = fracp[-1];
+ break;
+ default:
+ return (const char *) NULL;
+ }
+
+ /* Scan for timezone, measure fractional seconds. */
+ tzp = fracp;
+ fracl = 0;
+ if(fracp < end && (*fracp == '.' || *fracp == ',')) {
+ fracp++;
+ do
+ tzp++;
+ while(tzp < end && *tzp >= '0' && *tzp <= '9');
+ /* Strip leading zeroes in fractional seconds. */
+ for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--)
+ ;
+ }
+
+ /* Process timezone. */
+ if(tzp >= end)
+ ; /* Nothing to do. */
+ else if(*tzp == 'Z') {
+ tzp = " GMT";
+ end = tzp + 4;
+ }
+ else {
+ sep = " ";
+ tzp++;
+ }
+
+ tzl = end - tzp;
+ return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
+ beg, beg + 4, beg + 6,
+ beg + 8, beg + 10, sec1, sec2,
+ fracl? ".": "", fracl, fracp,
+ sep, tzl, tzp);
+}
+
+static const char * UTime2str(const char * beg, const char * end)
+{
+ const char * tzp;
+ size_t tzl;
+ const char * sec;
+
+ /* Convert an ASN.1 UTC time to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++)
+ ;
+ /* Get the seconds. */
+ sec = beg + 10;
+ switch (tzp - sec) {
+ case 0:
+ sec = "00";
+ case 2:
+ break;
+ default:
+ return (const char *) NULL;
+ }
+
+ /* Process timezone. */
+ if(tzp >= end)
+ return (const char *) NULL;
+ if(*tzp == 'Z') {
+ tzp = "GMT";
+ end = tzp + 3;
+ }
+ else
+ tzp++;
+
+ tzl = end - tzp;
+ return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
+ 20 - (*beg >= '5'), beg, beg + 2, beg + 4,
+ beg + 6, beg + 8, sec,
+ tzl, tzp);
+}
+
+const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
+{
+ static const char zero = '\0';
+
+ /* Convert an ASN.1 element to a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(elem->constructed)
+ return (const char *) NULL; /* No conversion of structured elements. */
+
+ if(!type)
+ type = elem->tag; /* Type not forced: use element tag as type. */
+
+ switch (type) {
+ case CURL_ASN1_BOOLEAN:
+ return bool2str(elem->beg, elem->end);
+ case CURL_ASN1_INTEGER:
+ case CURL_ASN1_ENUMERATED:
+ return int2str(elem->beg, elem->end);
+ case CURL_ASN1_BIT_STRING:
+ return bit2str(elem->beg, elem->end);
+ case CURL_ASN1_OCTET_STRING:
+ return octet2str(elem->beg, elem->end);
+ case CURL_ASN1_NULL:
+ return strdup(&zero);
+ case CURL_ASN1_OBJECT_IDENTIFIER:
+ return OID2str(elem->beg, elem->end, TRUE);
+ case CURL_ASN1_UTC_TIME:
+ return UTime2str(elem->beg, elem->end);
+ case CURL_ASN1_GENERALIZED_TIME:
+ return GTime2str(elem->beg, elem->end);
+ case CURL_ASN1_UTF8_STRING:
+ case CURL_ASN1_NUMERIC_STRING:
+ case CURL_ASN1_PRINTABLE_STRING:
+ case CURL_ASN1_TELETEX_STRING:
+ case CURL_ASN1_IA5_STRING:
+ case CURL_ASN1_VISIBLE_STRING:
+ case CURL_ASN1_UNIVERSAL_STRING:
+ case CURL_ASN1_BMP_STRING:
+ return string2str(type, elem->beg, elem->end);
+ }
+
+ return (const char *) NULL; /* Unsupported. */
+}
+
+static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn)
+{
+ curl_asn1Element rdn;
+ curl_asn1Element atv;
+ curl_asn1Element oid;
+ curl_asn1Element value;
+ size_t l = 0;
+ const char * p1;
+ const char * p2;
+ const char * p3;
+ const char * str;
+
+ /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'.
+ Return the total string length, even if larger than `n'. */
+
+ for(p1 = dn->beg; p1 < dn->end;) {
+ p1 = Curl_getASN1Element(&rdn, p1, dn->end);
+ for(p2 = rdn.beg; p2 < rdn.end;) {
+ p2 = Curl_getASN1Element(&atv, p2, rdn.end);
+ p3 = Curl_getASN1Element(&oid, atv.beg, atv.end);
+ Curl_getASN1Element(&value, p3, atv.end);
+ str = Curl_ASN1tostr(&oid, 0);
+ if(!str)
+ return -1;
+
+ /* Encode delimiter.
+ If attribute has a short uppercase name, delimiter is ", ". */
+ if(l) {
+ for(p3 = str; isupper(*p3); p3++)
+ ;
+ for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
+ if(l < n)
+ buf[l] = *p3;
+ l++;
+ }
+ }
+
+ /* Encode attribute name. */
+ for(p3 = str; *p3; p3++) {
+ if(l < n)
+ buf[l] = *p3;
+ l++;
+ }
+ free((char *) str);
+
+ /* Generate equal sign. */
+ if(l < n)
+ buf[l] = '=';
+ l++;
+
+ /* Generate value. */
+ str = Curl_ASN1tostr(&value, 0);
+ if(!str)
+ return -1;
+ for(p3 = str; *p3; p3++) {
+ if(l < n)
+ buf[l] = *p3;
+ l++;
+ }
+ free((char *) str);
+ }
+ }
+
+ return l;
+}
+
+const char * Curl_DNtostr(curl_asn1Element * dn)
+{
+ char * buf = (char *) NULL;
+ ssize_t n = encodeDN(buf, 0, dn);
+
+ /* Convert an ASN.1 distinguished name into a printable string.
+ Return the dynamically allocated string, or NULL if an error occurs. */
+
+ if(n >= 0) {
+ buf = malloc(n + 1);
+ if(buf) {
+ encodeDN(buf, n + 1, dn);
+ buf[n] = '\0';
+ }
+ }
+ return (const char *) buf;
+}
+
+/*
+ * X509 parser.
+ */
+
+void Curl_parseX509(curl_X509certificate * cert,
+ const char * beg, const char * end)
+{
+ curl_asn1Element elem;
+ curl_asn1Element tbsCertificate;
+ const char * ccp;
+ static const char defaultVersion = 0; /* v1. */
+
+ /* ASN.1 parse an X509 certificate into structure subfields.
+ Syntax is assumed to have already been checked by the SSL backend.
+ See RFC 5280. */
+
+ cert->certificate.beg = beg;
+ cert->certificate.end = end;
+
+ /* Get the sequence content. */
+ Curl_getASN1Element(&elem, beg, end);
+ beg = elem.beg;
+ end = elem.end;
+
+ /* Get tbsCertificate. */
+ beg = Curl_getASN1Element(&tbsCertificate, beg, end);
+ /* Skip the signatureAlgorithm. */
+ beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+ /* Get the signatureValue. */
+ Curl_getASN1Element(&cert->signature, beg, end);
+
+ /* Parse TBSCertificate. */
+ beg = tbsCertificate.beg;
+ end = tbsCertificate.end;
+ /* Get optional version, get serialNumber. */
+ cert->version.beg = &defaultVersion;
+ cert->version.end = &defaultVersion + sizeof defaultVersion;;
+ beg = Curl_getASN1Element(&elem, beg, end);
+ if(elem.tag == 0) {
+ Curl_getASN1Element(&cert->version, elem.beg, elem.end);
+ beg = Curl_getASN1Element(&elem, beg, end);
+ }
+ cert->serialNumber = elem;
+ /* Get signature algorithm. */
+ beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+ /* Get issuer. */
+ beg = Curl_getASN1Element(&cert->issuer, beg, end);
+ /* Get notBefore and notAfter. */
+ beg = Curl_getASN1Element(&elem, beg, end);
+ ccp = Curl_getASN1Element(&cert->notBefore, elem.beg, elem.end);
+ Curl_getASN1Element(&cert->notAfter, ccp, elem.end);
+ /* Get subject. */
+ beg = Curl_getASN1Element(&cert->subject, beg, end);
+ /* Get subjectPublicKeyAlgorithm and subjectPublicKey. */
+ beg = Curl_getASN1Element(&elem, beg, end);
+ ccp = Curl_getASN1Element(&cert->subjectPublicKeyAlgorithm,
+ elem.beg, elem.end);
+ Curl_getASN1Element(&cert->subjectPublicKey, ccp, elem.end);
+ /* Get optional issuerUiqueID, subjectUniqueID and extensions. */
+ cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0;
+ cert->extensions.tag = elem.tag = 0;
+ cert->issuerUniqueID.beg = cert->issuerUniqueID.end = "";
+ cert->subjectUniqueID.beg = cert->subjectUniqueID.end = "";
+ cert->extensions.beg = cert->extensions.end = "";
+ if(beg < end)
+ beg = Curl_getASN1Element(&elem, beg, end);
+ if(elem.tag == 1) {
+ cert->issuerUniqueID = elem;
+ if(beg < end)
+ beg = Curl_getASN1Element(&elem, beg, end);
+ }
+ if(elem.tag == 2) {
+ cert->subjectUniqueID = elem;
+ if(beg < end)
+ beg = Curl_getASN1Element(&elem, beg, end);
+ }
+ if(elem.tag == 3)
+ Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
+}
+
+static size_t copySubstring(char * to, const char * from)
+{
+ size_t i;
+
+ /* Copy at most 64-characters, terminate with a newline and returns the
+ effective number of stored characters. */
+
+ for(i = 0; i < 64; i++) {
+ to[i] = *from;
+ if(!*from++)
+ break;
+ }
+
+ to[i++] = '\n';
+ return i;
+}
+
+static const char * dumpAlgo(curl_asn1Element * param,
+ const char * beg, const char * end)
+{
+ curl_asn1Element oid;
+
+ /* Get algorithm parameters and return algorithm name. */
+
+ beg = Curl_getASN1Element(&oid, beg, end);
+ param->tag = 0;
+ param->beg = param->end = end;
+ if(beg < end)
+ Curl_getASN1Element(param, beg, end);
+ return OID2str(oid.beg, oid.end, TRUE);
+}
+
+static void do_pubkey_field(struct SessionHandle * data, int certnum,
+ const char * label, curl_asn1Element * elem)
+{
+ const char * output;
+
+ /* Generate a certificate information record for the public key. */
+
+ output = Curl_ASN1tostr(elem, 0);
+ if(output) {
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, label, output);
+ if(!certnum)
+ infof(data, " %s: %s\n", label, output);
+ free((char *) output);
+ }
+}
+
+static void do_pubkey(struct SessionHandle * data, int certnum,
+ const char * algo, curl_asn1Element * param,
+ curl_asn1Element * pubkey)
+{
+ curl_asn1Element elem;
+ curl_asn1Element pk;
+ const char * p;
+ const char * q;
+ unsigned long len;
+ unsigned int i;
+
+ /* Generate all information records for the public key. */
+
+ /* Get the public key (single element). */
+ Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
+
+ if(curl_strequal(algo, "rsaEncryption")) {
+ p = Curl_getASN1Element(&elem, pk.beg, pk.end);
+ /* Compute key length. */
+ for(q = elem.beg; !*q && q < elem.end; q++)
+ ;
+ len = (elem.end - q) * 8;
+ if(len)
+ for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1)
+ len--;
+ if(len > 32)
+ elem.beg = q; /* Strip leading zero bytes. */
+ if(!certnum)
+ infof(data, " RSA Public Key (%lu bits)\n", len);
+ if(data->set.ssl.certinfo) {
+ q = curl_maprintf("%lu", len);
+ if(q) {
+ Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q);
+ free((char *) q);
+ }
+ }
+ /* Generate coefficients. */
+ do_pubkey_field(data, certnum, "rsa(n)", &elem);
+ Curl_getASN1Element(&elem, p, pk.end);
+ do_pubkey_field(data, certnum, "rsa(e)", &elem);
+ }
+ else if(curl_strequal(algo, "dsa")) {
+ p = Curl_getASN1Element(&elem, param->beg, param->end);
+ do_pubkey_field(data, certnum, "dsa(p)", &elem);
+ p = Curl_getASN1Element(&elem, p, param->end);
+ do_pubkey_field(data, certnum, "dsa(q)", &elem);
+ Curl_getASN1Element(&elem, p, param->end);
+ do_pubkey_field(data, certnum, "dsa(g)", &elem);
+ do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
+ }
+ else if(curl_strequal(algo, "dhpublicnumber")) {
+ p = Curl_getASN1Element(&elem, param->beg, param->end);
+ do_pubkey_field(data, certnum, "dh(p)", &elem);
+ Curl_getASN1Element(&elem, param->beg, param->end);
+ do_pubkey_field(data, certnum, "dh(g)", &elem);
+ do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
+ }
+#if 0 /* Patent-encumbered. */
+ else if(curl_strequal(algo, "ecPublicKey")) {
+ /* Left TODO. */
+ }
+#endif
+}
+
+CURLcode Curl_extract_certinfo(struct connectdata * conn,
+ int certnum,
+ const char * beg,
+ const char * end)
+{
+ curl_X509certificate cert;
+ struct SessionHandle * data = conn->data;
+ curl_asn1Element param;
+ const char * ccp;
+ char * cp1;
+ size_t cl1;
+ char * cp2;
+ CURLcode cc;
+ unsigned long version;
+ size_t i;
+ size_t j;
+
+ if(!data->set.ssl.certinfo)
+ if(certnum)
+ return CURLE_OK;
+
+ /* Prepare the certificate information for curl_easy_getinfo(). */
+
+ /* Extract the certificate ASN.1 elements. */
+ Curl_parseX509(&cert, beg, end);
+
+ /* Subject. */
+ ccp = Curl_DNtostr(&cert.subject);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
+ if(!certnum)
+ infof(data, "%2d Subject: %s\n", certnum, ccp);
+ free((char *) ccp);
+
+ /* Issuer. */
+ ccp = Curl_DNtostr(&cert.issuer);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
+ if(!certnum)
+ infof(data, " Issuer: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Version (always fits in less than 32 bits). */
+ version = 0;
+ for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
+ version = (version << 8) | *(const unsigned char *) ccp;
+ if(data->set.ssl.certinfo) {
+ ccp = curl_maprintf("%lx", version);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_ssl_push_certinfo(data, certnum, "Version", ccp);
+ free((char *) ccp);
+ }
+ if(!certnum)
+ infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
+
+ /* Serial number. */
+ ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
+ if(!certnum)
+ infof(data, " Serial Number: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Signature algorithm .*/
+ ccp = dumpAlgo(&param, cert.signatureAlgorithm.beg,
+ cert.signatureAlgorithm.end);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
+ if(!certnum)
+ infof(data, " Signature Algorithm: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Start Date. */
+ ccp = Curl_ASN1tostr(&cert.notBefore, 0);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
+ if(!certnum)
+ infof(data, " Start Date: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Expire Date. */
+ ccp = Curl_ASN1tostr(&cert.notAfter, 0);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
+ if(!certnum)
+ infof(data, " Expire Date: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Public Key Algorithm. */
+ ccp = dumpAlgo(&param, cert.subjectPublicKeyAlgorithm.beg,
+ cert.subjectPublicKeyAlgorithm.end);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp);
+ if(!certnum)
+ infof(data, " Public Key Algorithm: %s\n", ccp);
+ do_pubkey(data, certnum, ccp, &param, &cert.subjectPublicKey);
+ free((char *) ccp);
+
+/* TODO: extensions. */
+
+ /* Signature. */
+ ccp = Curl_ASN1tostr(&cert.signature, 0);
+ if(!ccp)
+ return CURLE_OUT_OF_MEMORY;
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
+ if(!certnum)
+ infof(data, " Signature: %s\n", ccp);
+ free((char *) ccp);
+
+ /* Generate PEM certificate. */
+ cc = Curl_base64_encode(data, cert.certificate.beg,
+ cert.certificate.end - cert.certificate.beg,
+ &cp1, &cl1);
+ if(cc != CURLE_OK)
+ return cc;
+ /* Compute the number of characters in final certificate string. Format is:
+ -----BEGIN CERTIFICATE-----\n
+ <max 64 base64 characters>\n
+ .
+ .
+ .
+ -----END CERTIFICATE-----\n
+ */
+ i = 28 + cl1 + (cl1 + 64 - 1) / 64 + 26;
+ cp2 = malloc(i + 1);
+ if(!cp2) {
+ free(cp1);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ /* Build the certificate string. */
+ i = copySubstring(cp2, "-----BEGIN CERTIFICATE-----");
+ for(j = 0; j < cl1; j += 64)
+ i += copySubstring(cp2 + i, cp1 + j);
+ i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
+ cp2[i] = '\0';
+ free(cp1);
+ if(data->set.ssl.certinfo)
+ Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
+ if(!certnum)
+ infof(data, "%s\n", cp2);
+ free(cp2);
+ return CURLE_OK;
+}
+
+#endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */
+
+#if defined(USE_QSOSSL) || defined(USE_GSKIT)
+
+static const char * checkOID(const char * beg, const char * end,
+ const char * oid)
+{
+ curl_asn1Element e;
+ const char * ccp;
+ const char * p;
+ bool matched;
+
+ /* Check if first ASN.1 element at `beg' is the given OID.
+ Return a pointer in the source after the OID if found, else NULL. */
+
+ ccp = Curl_getASN1Element(&e, beg, end);
+ if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
+ return (const char *) NULL;
+
+ p = OID2str(e.beg, e.end, FALSE);
+ if(!p)
+ return (const char *) NULL;
+
+ matched = !strcmp(p, oid);
+ free((char *) p);
+ return matched? ccp: (const char *) NULL;
+}
+
+CURLcode Curl_verifyhost(struct connectdata * conn,
+ const char * beg, const char * end)
+{
+ struct SessionHandle * data = conn->data;
+ curl_X509certificate cert;
+ curl_asn1Element dn;
+ curl_asn1Element elem;
+ curl_asn1Element ext;
+ curl_asn1Element name;
+ int i;
+ const char * p;
+ const char * q;
+ char * dnsname;
+ int matched = -1;
+ size_t addrlen = (size_t) -1;
+ ssize_t len;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+
+ /* Verify that connection server matches info in X509 certificate at
+ `beg'..`end'. */
+
+ if(!data->set.ssl.verifyhost)
+ return CURLE_OK;
+
+ if(!beg)
+ return CURLE_PEER_FAILED_VERIFICATION;
+ Curl_parseX509(&cert, beg, end);
+
+ /* Get the server IP address. */
+#ifdef ENABLE_IPV6
+ if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+ addrlen = sizeof(struct in6_addr);
+ else
+#endif
+ if(Curl_inet_pton(AF_INET, conn->host.name, &addr))
+ addrlen = sizeof(struct in_addr);
+
+ /* Process extensions. */
+ for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
+ p = Curl_getASN1Element(&ext, p, cert.extensions.end);
+ /* Check if extension is a subjectAlternativeName. */
+ ext.beg = checkOID(ext.beg, ext.end, sanOID);
+ if(ext.beg) {
+ ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+ /* Skip critical if present. */
+ if(elem.tag == CURL_ASN1_BOOLEAN)
+ ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+ /* Parse the octet string contents: is a single sequence. */
+ Curl_getASN1Element(&elem, elem.beg, elem.end);
+ /* Check all GeneralNames. */
+ for(q = elem.beg; matched != 1 && q < elem.end;) {
+ q = Curl_getASN1Element(&name, q, elem.end);
+ switch (name.tag) {
+ case 2: /* DNS name. */
+ i = 0;
+ len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
+ name.beg, name.end);
+ if(len > 0)
+ if(strlen(dnsname) == (size_t) len)
+ i = Curl_cert_hostcheck((const char *) dnsname, conn->host.name);
+ if(dnsname)
+ free(dnsname);
+ if(!i)
+ return CURLE_PEER_FAILED_VERIFICATION;
+ matched = i;
+ break;
+
+ case 7: /* IP address. */
+ matched = (size_t) (name.end - q) == addrlen &&
+ !memcmp(&addr, q, addrlen);
+ break;
+ }
+ }
+ }
+ }
+
+ switch (matched) {
+ case 1:
+ /* an alternative name matched the server hostname */
+ infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
+ return CURLE_OK;
+ case 0:
+ /* an alternative name field existed, but didn't match and then
+ we MUST fail */
+ infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ /* Process subject. */
+ name.beg = name.end = "";
+ q = cert.subject.beg;
+ /* we have to look to the last occurrence of a commonName in the
+ distinguished one to get the most significant one. */
+ while(q < cert.subject.end) {
+ q = Curl_getASN1Element(&dn, q, cert.subject.end);
+ for(p = dn.beg; p < dn.end;) {
+ p = Curl_getASN1Element(&elem, p, dn.end);
+ /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */
+ elem.beg = checkOID(elem.beg, elem.end, cnOID);
+ if(elem.beg)
+ name = elem; /* Latch CN. */
+ }
+ }
+
+ /* Check the CN if found. */
+ if(!Curl_getASN1Element(&elem, name.beg, name.end))
+ failf(data, "SSL: unable to obtain common name from peer certificate");
+ else {
+ len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
+ if(len < 0) {
+ free(dnsname);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
+ failf(data, "SSL: illegal cert name field");
+ else if(Curl_cert_hostcheck((const char *) dnsname, conn->host.name)) {
+ infof(data, "\t common name: %s (matched)\n", dnsname);
+ free(dnsname);
+ return CURLE_OK;
+ }
+ else
+ failf(data, "SSL: certificate subject name '%s' does not match "
+ "target host name '%s'", dnsname, conn->host.dispname);
+ free(dnsname);
+ }
+
+ return CURLE_PEER_FAILED_VERIFICATION;
+}
+
+#endif /* USE_QSOSSL or USE_GSKIT */
diff --git a/external/libcurl_android/jni/libcurl/lib/x509asn1.h b/external/libcurl_android/jni/libcurl/lib/x509asn1.h
new file mode 100755
index 00000000..1741d6dc
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/lib/x509asn1.h
@@ -0,0 +1,129 @@
+#ifndef HEADER_CURL_X509ASN1_H
+#define HEADER_CURL_X509ASN1_H
+
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_QSOSSL) || defined(USE_GSKIT) || defined(USE_NSS)
+
+#include "urldata.h"
+
+/*
+ * Constants.
+ */
+
+/* ASN.1 classes. */
+#define CURL_ASN1_UNIVERSAL 0
+#define CURL_ASN1_APPLICATION 1
+#define CURL_ASN1_CONTEXT_SPECIFIC 2
+#define CURL_ASN1_PRIVATE 3
+
+/* ASN.1 types. */
+#define CURL_ASN1_BOOLEAN 1
+#define CURL_ASN1_INTEGER 2
+#define CURL_ASN1_BIT_STRING 3
+#define CURL_ASN1_OCTET_STRING 4
+#define CURL_ASN1_NULL 5
+#define CURL_ASN1_OBJECT_IDENTIFIER 6
+#define CURL_ASN1_OBJECT_DESCRIPTOR 7
+#define CURL_ASN1_INSTANCE_OF 8
+#define CURL_ASN1_REAL 9
+#define CURL_ASN1_ENUMERATED 10
+#define CURL_ASN1_EMBEDDED 11
+#define CURL_ASN1_UTF8_STRING 12
+#define CURL_ASN1_RELATIVE_OID 13
+#define CURL_ASN1_SEQUENCE 16
+#define CURL_ASN1_SET 17
+#define CURL_ASN1_NUMERIC_STRING 18
+#define CURL_ASN1_PRINTABLE_STRING 19
+#define CURL_ASN1_TELETEX_STRING 20
+#define CURL_ASN1_VIDEOTEX_STRING 21
+#define CURL_ASN1_IA5_STRING 22
+#define CURL_ASN1_UTC_TIME 23
+#define CURL_ASN1_GENERALIZED_TIME 24
+#define CURL_ASN1_GRAPHIC_STRING 25
+#define CURL_ASN1_VISIBLE_STRING 26
+#define CURL_ASN1_GENERAL_STRING 27
+#define CURL_ASN1_UNIVERSAL_STRING 28
+#define CURL_ASN1_CHARACTER_STRING 29
+#define CURL_ASN1_BMP_STRING 30
+
+
+/*
+ * Types.
+ */
+
+/* ASN.1 parsed element. */
+typedef struct {
+ const char * beg; /* Pointer to element data. */
+ const char * end; /* Pointer to 1st byte after element data. */
+ unsigned char class; /* ASN.1 element class. */
+ unsigned char tag; /* ASN.1 element tag. */
+ bool constructed; /* Element is constructed. */
+} curl_asn1Element;
+
+
+/* ASN.1 OID table entry. */
+typedef struct {
+ const char * numoid; /* Dotted-numeric OID. */
+ const char * textoid; /* OID name. */
+} curl_OID;
+
+
+/* X509 certificate: RFC 5280. */
+typedef struct {
+ curl_asn1Element certificate;
+ curl_asn1Element version;
+ curl_asn1Element serialNumber;
+ curl_asn1Element signatureAlgorithm;
+ curl_asn1Element signature;
+ curl_asn1Element issuer;
+ curl_asn1Element notBefore;
+ curl_asn1Element notAfter;
+ curl_asn1Element subject;
+ curl_asn1Element subjectPublicKeyAlgorithm;
+ curl_asn1Element subjectPublicKey;
+ curl_asn1Element issuerUniqueID;
+ curl_asn1Element subjectUniqueID;
+ curl_asn1Element extensions;
+} curl_X509certificate;
+
+
+/*
+ * Prototypes.
+ */
+
+const char * Curl_getASN1Element(curl_asn1Element * elem,
+ const char * beg, const char * end);
+const char * Curl_ASN1tostr(curl_asn1Element * elem, int type);
+const char * Curl_DNtostr(curl_asn1Element * dn);
+void Curl_parseX509(curl_X509certificate * cert,
+ const char * beg, const char * end);
+CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
+ const char * beg, const char * end);
+CURLcode Curl_verifyhost(struct connectdata * conn,
+ const char * beg, const char * end);
+
+#endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */
+#endif /* HEADER_CURL_X509ASN1_H */
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_binmode.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_binmode.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_binmode.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_bname.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_bname.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_bname.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_dbg.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_dbg.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_dbg.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_hdr.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_hdr.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_hdr.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_prg.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_prg.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_prg.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_rea.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_rea.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_rea.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_see.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_see.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_see.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_wrt.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_wrt.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cb_wrt.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cfgable.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cfgable.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_cfgable.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_convert.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_convert.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_convert.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_dirhie.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_dirhie.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_dirhie.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_doswin.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_doswin.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_doswin.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_easysrc.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_easysrc.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_easysrc.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_formparse.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_formparse.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_formparse.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_getparam.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_getparam.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_getparam.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_getpass.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_getpass.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_getpass.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_help.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_help.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_help.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_helpers.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_helpers.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_helpers.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_homedir.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_homedir.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_homedir.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_hugehelp.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_hugehelp.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_hugehelp.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_libinfo.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_libinfo.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_libinfo.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_main.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_main.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_main.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_metalink.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_metalink.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_metalink.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_mfiles.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_mfiles.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_mfiles.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_msgs.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_msgs.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_msgs.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_operate.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_operate.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_operate.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_operhlp.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_operhlp.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_operhlp.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_panykey.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_panykey.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_panykey.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_paramhlp.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_paramhlp.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_paramhlp.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_parsecfg.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_parsecfg.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_parsecfg.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_setopt.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_setopt.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_setopt.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_sleep.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_sleep.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_sleep.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_urlglob.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_urlglob.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_urlglob.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_util.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_util.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_util.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_vms.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_vms.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_vms.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_writeenv.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_writeenv.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_writeenv.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_writeout.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_writeout.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_writeout.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_xattr.Po b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_xattr.Po
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/curl-tool_xattr.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_binmode.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_binmode.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_binmode.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_bname.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_bname.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_bname.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_dbg.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_dbg.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_dbg.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_hdr.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_hdr.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_hdr.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_prg.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_prg.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_prg.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_rea.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_rea.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_rea.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_see.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_see.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_see.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_wrt.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_wrt.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cb_wrt.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cfgable.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cfgable.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_cfgable.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_convert.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_convert.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_convert.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_dirhie.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_dirhie.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_dirhie.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_doswin.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_doswin.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_doswin.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_easysrc.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_easysrc.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_easysrc.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_formparse.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_formparse.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_formparse.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_getparam.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_getparam.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_getparam.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_getpass.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_getpass.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_getpass.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_help.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_help.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_help.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_helpers.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_helpers.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_helpers.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_homedir.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_homedir.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_homedir.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_hugehelp.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_hugehelp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_hugehelp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_libinfo.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_libinfo.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_libinfo.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_main.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_main.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_main.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_metalink.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_metalink.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_metalink.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_mfiles.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_mfiles.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_mfiles.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_msgs.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_msgs.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_msgs.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_operate.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_operate.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_operate.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_operhlp.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_operhlp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_operhlp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_panykey.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_panykey.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_panykey.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_paramhlp.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_paramhlp.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_paramhlp.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_parsecfg.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_parsecfg.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_parsecfg.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_setopt.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_setopt.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_setopt.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_sleep.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_sleep.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_sleep.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_urlglob.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_urlglob.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_urlglob.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_util.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_util.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_util.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_vms.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_vms.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_vms.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_writeenv.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_writeenv.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_writeenv.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_writeout.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_writeout.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_writeout.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_xattr.Plo b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_xattr.Plo
new file mode 100755
index 00000000..9ce06a81
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/.deps/libcurltool_la-tool_xattr.Plo
@@ -0,0 +1 @@
+# dummy
diff --git a/external/libcurl_android/jni/libcurl/src/Makefile.inc b/external/libcurl_android/jni/libcurl/src/Makefile.inc
new file mode 100755
index 00000000..64d55ecf
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/Makefile.inc
@@ -0,0 +1,113 @@
+# ./src/Makefile.inc
+# Using the backslash as line continuation character might be problematic
+# with some make flavours, as Watcom's wmake showed us already. If we
+# ever want to change this in a portable manner then we should consider
+# this idea (posted to the libcurl list by Adam Kellas):
+# CSRC1 = file1.c file2.c file3.c
+# CSRC2 = file4.c file5.c file6.c
+# CSOURCES = $(CSRC1) $(CSRC2)
+
+# libcurl has sources that provide functions named curlx_* that aren't part of
+# the official API, but we re-use the code here to avoid duplication.
+CURLX_CFILES = \
+ ../lib/strtoofft.c \
+ ../lib/strdup.c \
+ ../lib/rawstr.c \
+ ../lib/nonblock.c \
+ ../lib/warnless.c
+
+CURLX_HFILES = \
+ ../lib/curl_setup.h \
+ ../lib/strtoofft.h \
+ ../lib/strdup.h \
+ ../lib/rawstr.h \
+ ../lib/nonblock.h \
+ ../lib/warnless.h
+
+CURL_CFILES = \
+ tool_binmode.c \
+ tool_bname.c \
+ tool_cb_dbg.c \
+ tool_cb_hdr.c \
+ tool_cb_prg.c \
+ tool_cb_rea.c \
+ tool_cb_see.c \
+ tool_cb_wrt.c \
+ tool_cfgable.c \
+ tool_convert.c \
+ tool_dirhie.c \
+ tool_doswin.c \
+ tool_easysrc.c \
+ tool_formparse.c \
+ tool_getparam.c \
+ tool_getpass.c \
+ tool_help.c \
+ tool_helpers.c \
+ tool_homedir.c \
+ tool_hugehelp.c \
+ tool_libinfo.c \
+ tool_main.c \
+ tool_metalink.c \
+ tool_mfiles.c \
+ tool_msgs.c \
+ tool_operate.c \
+ tool_operhlp.c \
+ tool_panykey.c \
+ tool_paramhlp.c \
+ tool_parsecfg.c \
+ tool_setopt.c \
+ tool_sleep.c \
+ tool_urlglob.c \
+ tool_util.c \
+ tool_vms.c \
+ tool_writeenv.c \
+ tool_writeout.c \
+ tool_xattr.c
+
+CURL_HFILES = \
+ tool_binmode.h \
+ tool_bname.h \
+ tool_cb_dbg.h \
+ tool_cb_hdr.h \
+ tool_cb_prg.h \
+ tool_cb_rea.h \
+ tool_cb_see.h \
+ tool_cb_wrt.h \
+ tool_cfgable.h \
+ tool_convert.h \
+ tool_dirhie.h \
+ tool_doswin.h \
+ tool_easysrc.h \
+ tool_formparse.h \
+ tool_getparam.h \
+ tool_getpass.h \
+ tool_help.h \
+ tool_helpers.h \
+ tool_homedir.h \
+ tool_hugehelp.h \
+ tool_libinfo.h \
+ tool_main.h \
+ tool_metalink.h \
+ tool_mfiles.h \
+ tool_msgs.h \
+ tool_operate.h \
+ tool_operhlp.h \
+ tool_panykey.h \
+ tool_paramhlp.h \
+ tool_parsecfg.h \
+ tool_sdecls.h \
+ tool_setopt.h \
+ tool_setup.h \
+ tool_sleep.h \
+ tool_urlglob.h \
+ tool_util.h \
+ tool_version.h \
+ tool_vms.h \
+ tool_writeenv.h \
+ tool_writeout.h \
+ tool_xattr.h
+
+CURL_RCFILES = curl.rc
+
+curl_SOURCES = $(CURL_CFILES) $(CURLX_CFILES) $(CURL_HFILES)
+
diff --git a/external/libcurl_android/jni/libcurl/src/curl.rc b/external/libcurl_android/jni/libcurl/src/curl.rc
new file mode 100755
index 00000000..3db59bd3
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/curl.rc
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include <winver.h>
+#include "tool_version.h"
+
+LANGUAGE 0x09,0x01
+
+#define RC_VERSION CURL_VERSION_MAJOR, CURL_VERSION_MINOR, CURL_VERSION_PATCH, 0
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RC_VERSION
+ PRODUCTVERSION RC_VERSION
+ FILEFLAGSMASK 0x3fL
+#if defined(DEBUGBUILD) || defined(_DEBUG)
+ FILEFLAGS 1
+#else
+ FILEFLAGS 0
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "cURL, http://curl.haxx.se/\0"
+ VALUE "FileDescription", "The cURL executable\0"
+ VALUE "FileVersion", CURL_VERSION "\0"
+ VALUE "InternalName", "curl\0"
+ VALUE "OriginalFilename", "curl.exe\0"
+ VALUE "ProductName", "The cURL executable\0"
+ VALUE "ProductVersion", CURL_VERSION "\0"
+ VALUE "LegalCopyright", "© " CURL_COPYRIGHT "\0"
+ VALUE "License", "http://curl.haxx.se/docs/copyright.html\0"
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/external/libcurl_android/jni/libcurl/src/tool_binmode.c b/external/libcurl_android/jni/libcurl/src/tool_binmode.c
new file mode 100755
index 00000000..92033ac0
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_binmode.c
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_SETMODE
+
+#ifdef HAVE_IO_H
+# include <io.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#include "tool_binmode.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void set_binmode(FILE *stream)
+{
+#ifdef O_BINARY
+# ifdef __HIGHC__
+ _setmode(stream, O_BINARY);
+# else
+ setmode(fileno(stream), O_BINARY);
+# endif
+#else
+ (void)stream;
+#endif
+}
+
+#endif /* HAVE_SETMODE */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_binmode.h b/external/libcurl_android/jni/libcurl/src/tool_binmode.h
new file mode 100755
index 00000000..b5cb08d5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_binmode.h
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_TOOL_BINMODE_H
+#define HEADER_CURL_TOOL_BINMODE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_SETMODE
+
+void set_binmode(FILE *stream);
+
+#else
+
+#define set_binmode(x) Curl_nop_stmt
+
+#endif /* HAVE_SETMODE */
+
+#endif /* HEADER_CURL_TOOL_BINMODE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_bname.c b/external/libcurl_android/jni/libcurl/src/tool_bname.c
new file mode 100755
index 00000000..27783054
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_bname.c
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_bname.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifndef HAVE_BASENAME
+
+char *tool_basename(char *path)
+{
+ char *s1;
+ char *s2;
+
+ s1 = strrchr(path, '/');
+ s2 = strrchr(path, '\\');
+
+ if(s1 && s2) {
+ path = (s1 > s2) ? s1 + 1 : s2 + 1;
+ }
+ else if(s1)
+ path = s1 + 1;
+ else if(s2)
+ path = s2 + 1;
+
+ return path;
+}
+
+#endif /* HAVE_BASENAME */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_bname.h b/external/libcurl_android/jni/libcurl/src/tool_bname.h
new file mode 100755
index 00000000..69cf92c1
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_bname.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_TOOL_BNAME_H
+#define HEADER_CURL_TOOL_BNAME_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef HAVE_BASENAME
+
+char *tool_basename(char *path);
+
+#define basename(x) tool_basename((x))
+
+#endif /* HAVE_BASENAME */
+
+#endif /* HEADER_CURL_TOOL_BNAME_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_dbg.c b/external/libcurl_android/jni/libcurl/src/tool_cb_dbg.c
new file mode 100755
index 00000000..010dae3b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_dbg.c
@@ -0,0 +1,275 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_cb_dbg.h"
+#include "tool_util.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+static void dump(const char *timebuf, const char *text,
+ FILE *stream, const unsigned char *ptr, size_t size,
+ trace tracetype, curl_infotype infotype);
+
+/*
+** callback for CURLOPT_DEBUGFUNCTION
+*/
+
+int tool_debug_cb(CURL *handle, curl_infotype type,
+ unsigned char *data, size_t size,
+ void *userdata)
+{
+ struct OperationConfig *operation = userdata;
+ struct GlobalConfig *config = operation->global;
+ FILE *output = config->errors;
+ const char *text;
+ struct timeval tv;
+ struct tm *now;
+ char timebuf[20];
+ time_t secs;
+ static time_t epoch_offset;
+ static int known_offset;
+
+ (void)handle; /* not used */
+
+ if(config->tracetime) {
+ tv = tvnow();
+ if(!known_offset) {
+ epoch_offset = time(NULL) - tv.tv_sec;
+ known_offset = 1;
+ }
+ secs = epoch_offset + tv.tv_sec;
+ now = localtime(&secs); /* not thread safe but we don't care */
+ snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
+ now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
+ }
+ else
+ timebuf[0] = 0;
+
+ if(!config->trace_stream) {
+ /* open for append */
+ if(curlx_strequal("-", config->trace_dump))
+ config->trace_stream = stdout;
+ else if(curlx_strequal("%", config->trace_dump))
+ /* Ok, this is somewhat hackish but we do it undocumented for now */
+ config->trace_stream = config->errors; /* aka stderr */
+ else {
+ config->trace_stream = fopen(config->trace_dump, "w");
+ config->trace_fopened = TRUE;
+ }
+ }
+
+ if(config->trace_stream)
+ output = config->trace_stream;
+
+ if(!output) {
+ warnf(operation, "Failed to create/open output");
+ return 0;
+ }
+
+ if(config->tracetype == TRACE_PLAIN) {
+ /*
+ * This is the trace look that is similar to what libcurl makes on its
+ * own.
+ */
+ static const char * const s_infotype[] = {
+ "*", "<", ">", "{", "}", "{", "}"
+ };
+ size_t i;
+ size_t st = 0;
+ static bool newl = FALSE;
+ static bool traced_data = FALSE;
+
+ switch(type) {
+ case CURLINFO_HEADER_OUT:
+ if(size > 0) {
+ for(i = 0; i < size - 1; i++) {
+ if(data[i] == '\n') { /* LF */
+ if(!newl) {
+ fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ }
+ (void)fwrite(data + st, i - st + 1, 1, output);
+ st = i + 1;
+ newl = FALSE;
+ }
+ }
+ if(!newl)
+ fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ (void)fwrite(data + st, i - st + 1, 1, output);
+ }
+ newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
+ traced_data = FALSE;
+ break;
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_IN:
+ if(!newl)
+ fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ (void)fwrite(data, size, 1, output);
+ newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
+ traced_data = FALSE;
+ break;
+ case CURLINFO_DATA_OUT:
+ case CURLINFO_DATA_IN:
+ case CURLINFO_SSL_DATA_IN:
+ case CURLINFO_SSL_DATA_OUT:
+ if(!traced_data) {
+ /* if the data is output to a tty and we're sending this debug trace
+ to stderr or stdout, we don't display the alert about the data not
+ being shown as the data _is_ shown then just not via this
+ function */
+ if(!config->isatty || ((output != stderr) && (output != stdout))) {
+ if(!newl)
+ fprintf(output, "%s%s ", timebuf, s_infotype[type]);
+ fprintf(output, "[data not shown]\n");
+ newl = FALSE;
+ traced_data = TRUE;
+ }
+ }
+ break;
+ default: /* nada */
+ newl = FALSE;
+ traced_data = FALSE;
+ break;
+ }
+
+ return 0;
+ }
+
+#ifdef CURL_DOES_CONVERSIONS
+ /* Special processing is needed for CURLINFO_HEADER_OUT blocks
+ * if they contain both headers and data (separated by CRLFCRLF).
+ * We dump the header text and then switch type to CURLINFO_DATA_OUT.
+ */
+ if((type == CURLINFO_HEADER_OUT) && (size > 4)) {
+ size_t i;
+ for(i = 0; i < size - 4; i++) {
+ if(memcmp(&data[i], "\r\n\r\n", 4) == 0) {
+ /* dump everything through the CRLFCRLF as a sent header */
+ text = "=> Send header";
+ dump(timebuf, text, output, data, i + 4, config->tracetype, type);
+ data += i + 3;
+ size -= i + 4;
+ type = CURLINFO_DATA_OUT;
+ data += 1;
+ break;
+ }
+ }
+ }
+#endif /* CURL_DOES_CONVERSIONS */
+
+ switch (type) {
+ case CURLINFO_TEXT:
+ fprintf(output, "%s== Info: %s", timebuf, data);
+ default: /* in case a new one is introduced to shock us */
+ return 0;
+
+ case CURLINFO_HEADER_OUT:
+ text = "=> Send header";
+ break;
+ case CURLINFO_DATA_OUT:
+ text = "=> Send data";
+ break;
+ case CURLINFO_HEADER_IN:
+ text = "<= Recv header";
+ break;
+ case CURLINFO_DATA_IN:
+ text = "<= Recv data";
+ break;
+ case CURLINFO_SSL_DATA_IN:
+ text = "<= Recv SSL data";
+ break;
+ case CURLINFO_SSL_DATA_OUT:
+ text = "=> Send SSL data";
+ break;
+ }
+
+ dump(timebuf, text, output, data, size, config->tracetype, type);
+ return 0;
+}
+
+static void dump(const char *timebuf, const char *text,
+ FILE *stream, const unsigned char *ptr, size_t size,
+ trace tracetype, curl_infotype infotype)
+{
+ size_t i;
+ size_t c;
+
+ unsigned int width = 0x10;
+
+ if(tracetype == TRACE_ASCII)
+ /* without the hex output, we can fit more on screen */
+ width = 0x40;
+
+ fprintf(stream, "%s%s, %zd bytes (0x%zx)\n", timebuf, text, size, size);
+
+ for(i = 0; i < size; i += width) {
+
+ fprintf(stream, "%04zx: ", i);
+
+ if(tracetype == TRACE_BIN) {
+ /* hex not disabled, show it */
+ for(c = 0; c < width; c++)
+ if(i+c < size)
+ fprintf(stream, "%02x ", ptr[i+c]);
+ else
+ fputs(" ", stream);
+ }
+
+ for(c = 0; (c < width) && (i+c < size); c++) {
+ /* check for 0D0A; if found, skip past and start a new line of output */
+ if((tracetype == TRACE_ASCII) &&
+ (i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) {
+ i += (c+2-width);
+ break;
+ }
+#ifdef CURL_DOES_CONVERSIONS
+ /* repeat the 0D0A check above but use the host encoding for CRLF */
+ if((tracetype == TRACE_ASCII) &&
+ (i+c+1 < size) && (ptr[i+c] == '\r') && (ptr[i+c+1] == '\n')) {
+ i += (c+2-width);
+ break;
+ }
+ /* convert to host encoding and print this character */
+ fprintf(stream, "%c", convert_char(infotype, ptr[i+c]));
+#else
+ (void)infotype;
+ fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ?
+ ptr[i+c] : UNPRINTABLE_CHAR);
+#endif /* CURL_DOES_CONVERSIONS */
+ /* check again for 0D0A, to avoid an extra \n if it's at width */
+ if((tracetype == TRACE_ASCII) &&
+ (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) {
+ i += (c+3-width);
+ break;
+ }
+ }
+ fputc('\n', stream); /* newline */
+ }
+ fflush(stream);
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_dbg.h b/external/libcurl_android/jni/libcurl/src/tool_cb_dbg.h
new file mode 100755
index 00000000..d0ed7b0d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_dbg.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_TOOL_CB_DBG_H
+#define HEADER_CURL_TOOL_CB_DBG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+** callback for CURLOPT_DEBUGFUNCTION
+*/
+
+int tool_debug_cb(CURL *handle, curl_infotype type,
+ unsigned char *data, size_t size,
+ void *userdata);
+
+#endif /* HEADER_CURL_TOOL_CB_DBG_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_hdr.c b/external/libcurl_android/jni/libcurl/src/tool_cb_hdr.c
new file mode 100755
index 00000000..ef340f79
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_hdr.c
@@ -0,0 +1,225 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_cb_hdr.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+static char *parse_filename(const char *ptr, size_t len);
+
+/*
+** callback for CURLOPT_HEADERFUNCTION
+*/
+
+size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ struct HdrCbData *hdrcbdata = userdata;
+ struct OutStruct *outs = hdrcbdata->outs;
+ struct OutStruct *heads = hdrcbdata->heads;
+ const char *str = ptr;
+ const size_t cb = size * nmemb;
+ const char *end = (char*)ptr + cb;
+
+ /*
+ * Once that libcurl has called back tool_header_cb() the returned value
+ * is checked against the amount that was intended to be written, if
+ * it does not match then it fails with CURLE_WRITE_ERROR. So at this
+ * point returning a value different from sz*nmemb indicates failure.
+ */
+ size_t failure = (size * nmemb) ? 0 : 1;
+
+ if(!heads->config)
+ return failure;
+
+#ifdef DEBUGBUILD
+ if(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
+ warnf(heads->config, "Header data exceeds single call write limit!\n");
+ return failure;
+ }
+#endif
+
+ /*
+ * Write header data when curl option --dump-header (-D) is given.
+ */
+
+ if(heads->config->headerfile && heads->stream) {
+ size_t rc = fwrite(ptr, size, nmemb, heads->stream);
+ if(rc != cb)
+ return rc;
+ }
+
+ /*
+ * This callback sets the filename where output shall be written when
+ * curl options --remote-name (-O) and --remote-header-name (-J) have
+ * been simultaneously given and additionally server returns an HTTP
+ * Content-Disposition header specifying a filename property.
+ */
+
+ if(hdrcbdata->honor_cd_filename &&
+ (cb > 20) && checkprefix("Content-disposition:", str)) {
+ const char *p = str + 20;
+
+ /* look for the 'filename=' parameter
+ (encoded filenames (*=) are not supported) */
+ for(;;) {
+ char *filename;
+ size_t len;
+
+ while(*p && (p < end) && !ISALPHA(*p))
+ p++;
+ if(p > end - 9)
+ break;
+
+ if(memcmp(p, "filename=", 9)) {
+ /* no match, find next parameter */
+ while((p < end) && (*p != ';'))
+ p++;
+ continue;
+ }
+ p += 9;
+
+ /* this expression below typecasts 'cb' only to avoid
+ warning: signed and unsigned type in conditional expression
+ */
+ len = (ssize_t)cb - (p - str);
+ filename = parse_filename(p, len);
+ if(filename) {
+ outs->filename = filename;
+ outs->alloc_filename = TRUE;
+ outs->is_cd_filename = TRUE;
+ outs->s_isreg = TRUE;
+ outs->fopened = FALSE;
+ outs->stream = NULL;
+ hdrcbdata->honor_cd_filename = FALSE;
+ break;
+ }
+ else
+ return failure;
+ }
+ }
+
+ return cb;
+}
+
+/*
+ * Copies a file name part and returns an ALLOCATED data buffer.
+ */
+static char *parse_filename(const char *ptr, size_t len)
+{
+ char *copy;
+ char *p;
+ char *q;
+ char stop = '\0';
+
+ /* simple implementation of strndup() */
+ copy = malloc(len+1);
+ if(!copy)
+ return NULL;
+ memcpy(copy, ptr, len);
+ copy[len] = '\0';
+
+ p = copy;
+ if(*p == '\'' || *p == '"') {
+ /* store the starting quote */
+ stop = *p;
+ p++;
+ }
+ else
+ stop = ';';
+
+ /* if the filename contains a path, only use filename portion */
+ q = strrchr(copy, '/');
+ if(q) {
+ p = q + 1;
+ if(!*p) {
+ Curl_safefree(copy);
+ return NULL;
+ }
+ }
+
+ /* If the filename contains a backslash, only use filename portion. The idea
+ is that even systems that don't handle backslashes as path separators
+ probably want the path removed for convenience. */
+ q = strrchr(p, '\\');
+ if(q) {
+ p = q + 1;
+ if(!*p) {
+ Curl_safefree(copy);
+ return NULL;
+ }
+ }
+
+ /* scan for the end letter and stop there */
+ q = p;
+ while(*q) {
+ if(q[1] && (q[0] == '\\'))
+ q++;
+ else if(q[0] == stop)
+ break;
+ q++;
+ }
+ *q = '\0';
+
+ /* make sure the file name doesn't end in \r or \n */
+ q = strchr(p, '\r');
+ if(q)
+ *q = '\0';
+
+ q = strchr(p, '\n');
+ if(q)
+ *q = '\0';
+
+ if(copy != p)
+ memmove(copy, p, strlen(p) + 1);
+
+ /* in case we built debug enabled, we allow an evironment variable
+ * named CURL_TESTDIR to prefix the given file name to put it into a
+ * specific directory
+ */
+#ifdef DEBUGBUILD
+ {
+ char *tdir = curlx_getenv("CURL_TESTDIR");
+ if(tdir) {
+ char buffer[512]; /* suitably large */
+ snprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy);
+ Curl_safefree(copy);
+ copy = strdup(buffer); /* clone the buffer, we don't use the libcurl
+ aprintf() or similar since we want to use the
+ same memory code as the "real" parse_filename
+ function */
+ curl_free(tdir);
+ }
+ }
+#endif
+
+ return copy;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_hdr.h b/external/libcurl_android/jni/libcurl/src/tool_cb_hdr.h
new file mode 100755
index 00000000..bd504313
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_hdr.h
@@ -0,0 +1,54 @@
+#ifndef HEADER_CURL_TOOL_CB_HDR_H
+#define HEADER_CURL_TOOL_CB_HDR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+ * curl operates using a single HdrCbData struct variable, a
+ * pointer to this is passed as userdata pointer to tool_header_cb.
+ *
+ * 'outs' member is a pointer to the OutStruct variable used to keep
+ * track of information relative to curl's output writing.
+ *
+ * 'heads' member is a pointer to the OutStruct variable used to keep
+ * track of information relative to header response writing.
+ *
+ * 'honor_cd_filename' member is TRUE when tool_header_cb is allowed
+ * to honor Content-Disposition filename property and accordingly
+ * set 'outs' filename, otherwise FALSE;
+ */
+
+struct HdrCbData {
+ struct OutStruct *outs;
+ struct OutStruct *heads;
+ bool honor_cd_filename;
+};
+
+/*
+** callback for CURLOPT_HEADERFUNCTION
+*/
+
+size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata);
+
+#endif /* HEADER_CURL_TOOL_CB_HDR_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_prg.c b/external/libcurl_android/jni/libcurl/src/tool_cb_prg.c
new file mode 100755
index 00000000..9e3c5fb4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_prg.c
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_cb_prg.h"
+#include "tool_util.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+** callback for CURLOPT_XFERINFOFUNCTION
+*/
+
+#define MAX_BARLENGTH 256
+
+int tool_progress_cb(void *clientp,
+ curl_off_t dltotal, curl_off_t dlnow,
+ curl_off_t ultotal, curl_off_t ulnow)
+{
+ /* The original progress-bar source code was written for curl by Lars Aas,
+ and this new edition inherits some of his concepts. */
+
+ char line[MAX_BARLENGTH+1];
+ char format[40];
+ double frac;
+ double percent;
+ int barwidth;
+ int num;
+ struct timeval now = tvnow();
+ struct ProgressData *bar = (struct ProgressData *)clientp;
+ curl_off_t total;
+ curl_off_t point;
+
+ /* expected transfer size */
+ total = dltotal + ultotal + bar->initial_size;
+
+ /* we've come this far */
+ point = dlnow + ulnow + bar->initial_size;
+
+ if(bar->calls && (tvdiff(now, bar->prevtime) < 100L) && point < total)
+ /* after first call, limit progress-bar updating to 10 Hz */
+ /* update when we're at 100% even if last update is less than 200ms ago */
+ return 0;
+
+ if(point > total)
+ /* we have got more than the expected total! */
+ total = point;
+
+ /* simply count invokes */
+ bar->calls++;
+
+ if(total < 1) {
+ curl_off_t prevblock = bar->prev / 1024;
+ curl_off_t thisblock = point / 1024;
+ while(thisblock > prevblock) {
+ fprintf(bar->out, "#");
+ prevblock++;
+ }
+ }
+ else if(point != bar->prev) {
+ frac = (double)point / (double)total;
+ percent = frac * 100.0f;
+ barwidth = bar->width - 7;
+ num = (int) (((double)barwidth) * frac);
+ if(num > MAX_BARLENGTH)
+ num = MAX_BARLENGTH;
+ memset(line, '#', num);
+ line[num] = '\0';
+ snprintf(format, sizeof(format), "\r%%-%ds %%5.1f%%%%", barwidth);
+ fprintf(bar->out, format, line, percent);
+ }
+ fflush(bar->out);
+ bar->prev = point;
+ bar->prevtime = now;
+
+ return 0;
+}
+
+void progressbarinit(struct ProgressData *bar,
+ struct OperationConfig *config)
+{
+#ifdef __EMX__
+ /* 20000318 mgs */
+ int scr_size[2];
+#endif
+ char *colp;
+
+ memset(bar, 0, sizeof(struct ProgressData));
+
+ /* pass this through to progress function so
+ * it can display progress towards total file
+ * not just the part that's left. (21-may-03, dbyron) */
+ if(config->use_resume)
+ bar->initial_size = config->resume_from;
+
+/* TODO: get terminal width through ansi escapes or something similar.
+ try to update width when xterm is resized... - 19990617 larsa */
+#ifndef __EMX__
+ /* 20000318 mgs
+ * OS/2 users most likely won't have this env var set, and besides that
+ * we're using our own way to determine screen width */
+ colp = curlx_getenv("COLUMNS");
+ if(colp) {
+ char *endptr;
+ long num = strtol(colp, &endptr, 10);
+ if((endptr != colp) && (endptr == colp + strlen(colp)) && (num > 0))
+ bar->width = (int)num;
+ else
+ bar->width = 79;
+ curl_free(colp);
+ }
+ else
+ bar->width = 79;
+#else
+ /* 20000318 mgs
+ * We use this emx library call to get the screen width, and subtract
+ * one from what we got in order to avoid a problem with the cursor
+ * advancing to the next line if we print a string that is as long as
+ * the screen is wide. */
+
+ _scrsize(scr_size);
+ bar->width = scr_size[0] - 1;
+#endif
+
+ bar->out = config->global->errors;
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_prg.h b/external/libcurl_android/jni/libcurl/src/tool_cb_prg.h
new file mode 100755
index 00000000..c635be80
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_prg.h
@@ -0,0 +1,50 @@
+#ifndef HEADER_CURL_TOOL_CB_PRG_H
+#define HEADER_CURL_TOOL_CB_PRG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define CURL_PROGRESS_STATS 0 /* default progress display */
+#define CURL_PROGRESS_BAR 1
+
+struct ProgressData {
+ int calls;
+ curl_off_t prev;
+ struct timeval prevtime;
+ int width;
+ FILE *out; /* where to write everything to */
+ curl_off_t initial_size;
+};
+
+void progressbarinit(struct ProgressData *bar,
+ struct OperationConfig *config);
+
+/*
+** callback for CURLOPT_PROGRESSFUNCTION
+*/
+
+int tool_progress_cb(void *clientp,
+ curl_off_t dltotal, curl_off_t dlnow,
+ curl_off_t ultotal, curl_off_t ulnow);
+
+#endif /* HEADER_CURL_TOOL_CB_PRG_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_rea.c b/external/libcurl_android/jni/libcurl/src/tool_cb_rea.c
new file mode 100755
index 00000000..4565a15d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_rea.c
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_cb_rea.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+** callback for CURLOPT_READFUNCTION
+*/
+
+size_t tool_read_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
+{
+ ssize_t rc;
+ struct InStruct *in = userdata;
+
+ rc = read(in->fd, buffer, sz*nmemb);
+ if(rc < 0) {
+ if(errno == EAGAIN) {
+ errno = 0;
+ in->config->readbusy = TRUE;
+ return CURL_READFUNC_PAUSE;
+ }
+ /* since size_t is unsigned we can't return negative values fine */
+ rc = 0;
+ }
+ in->config->readbusy = FALSE;
+ return (size_t)rc;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_rea.h b/external/libcurl_android/jni/libcurl/src/tool_cb_rea.h
new file mode 100755
index 00000000..4294166a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_rea.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_TOOL_CB_REA_H
+#define HEADER_CURL_TOOL_CB_REA_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+** callback for CURLOPT_READFUNCTION
+*/
+
+size_t tool_read_cb(void *buffer, size_t sz, size_t nmemb, void *userdata);
+
+#endif /* HEADER_CURL_TOOL_CB_REA_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_see.c b/external/libcurl_android/jni/libcurl/src/tool_cb_see.c
new file mode 100755
index 00000000..2f49e1d9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_see.c
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_cb_see.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* OUR_MAX_SEEK_L has 'long' data type, OUR_MAX_SEEK_O has 'curl_off_t,
+ both represent the same value. Maximum offset used here when we lseek
+ using a 'long' data type offset */
+
+#define OUR_MAX_SEEK_L 2147483647L - 1L
+#define OUR_MAX_SEEK_O CURL_OFF_T_C(0x7FFFFFFF) - CURL_OFF_T_C(0x1)
+
+/*
+** callback for CURLOPT_SEEKFUNCTION
+**
+** Notice that this is not supposed to return the resulting offset. This
+** shall only return CURL_SEEKFUNC_* return codes.
+*/
+
+int tool_seek_cb(void *userdata, curl_off_t offset, int whence)
+{
+ struct InStruct *in = userdata;
+
+#if(CURL_SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES)
+
+ /* The offset check following here is only interesting if curl_off_t is
+ larger than off_t and we are not using the WIN32 large file support
+ macros that provide the support to do 64bit seeks correctly */
+
+ if(offset > OUR_MAX_SEEK_O) {
+ /* Some precaution code to work around problems with different data sizes
+ to allow seeking >32bit even if off_t is 32bit. Should be very rare and
+ is really valid on weirdo-systems. */
+ curl_off_t left = offset;
+
+ if(whence != SEEK_SET)
+ /* this code path doesn't support other types */
+ return CURL_SEEKFUNC_FAIL;
+
+ if(LSEEK_ERROR == lseek(in->fd, 0, SEEK_SET))
+ /* couldn't rewind to beginning */
+ return CURL_SEEKFUNC_FAIL;
+
+ while(left) {
+ long step = (left > OUR_MAX_SEEK_O) ? OUR_MAX_SEEK_L : (long)left;
+ if(LSEEK_ERROR == lseek(in->fd, step, SEEK_CUR))
+ /* couldn't seek forwards the desired amount */
+ return CURL_SEEKFUNC_FAIL;
+ left -= step;
+ }
+ return CURL_SEEKFUNC_OK;
+ }
+#endif
+
+ if(LSEEK_ERROR == lseek(in->fd, offset, whence))
+ /* couldn't rewind, the reason is in errno but errno is just not portable
+ enough and we don't actually care that much why we failed. We'll let
+ libcurl know that it may try other means if it wants to. */
+ return CURL_SEEKFUNC_CANTSEEK;
+
+ return CURL_SEEKFUNC_OK;
+}
+
+#if defined(WIN32) && !defined(__MINGW64__)
+
+#ifdef __BORLANDC__
+/* 64-bit lseek-like function unavailable */
+# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
+#endif
+
+#ifdef __POCC__
+# if(__POCC__ < 450)
+/* 64-bit lseek-like function unavailable */
+# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence)
+# else
+# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence)
+# endif
+#endif
+
+#ifdef _WIN32_WCE
+/* 64-bit lseek-like function unavailable */
+# undef _lseeki64
+# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
+# undef _get_osfhandle
+# define _get_osfhandle(fd) (fd)
+#endif
+
+/*
+ * Truncate a file handle at a 64-bit position 'where'.
+ */
+
+int tool_ftruncate64(int fd, curl_off_t where)
+{
+ if(_lseeki64(fd, where, SEEK_SET) < 0)
+ return -1;
+
+ if(!SetEndOfFile((HANDLE)_get_osfhandle(fd)))
+ return -1;
+
+ return 0;
+}
+
+#endif /* WIN32 && ! __MINGW64__ */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_see.h b/external/libcurl_android/jni/libcurl/src/tool_cb_see.h
new file mode 100755
index 00000000..ceb22d65
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_see.h
@@ -0,0 +1,46 @@
+#ifndef HEADER_CURL_TOOL_CB_SEE_H
+#define HEADER_CURL_TOOL_CB_SEE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(WIN32) && !defined(__MINGW64__)
+
+int tool_ftruncate64(int fd, curl_off_t where);
+
+#undef ftruncate
+#define ftruncate(fd,where) tool_ftruncate64(fd,where)
+
+#ifndef HAVE_FTRUNCATE
+# define HAVE_FTRUNCATE 1
+#endif
+
+#endif /* WIN32 && ! __MINGW64__ */
+
+/*
+** callback for CURLOPT_SEEKFUNCTION
+*/
+
+int tool_seek_cb(void *userdata, curl_off_t offset, int whence);
+
+#endif /* HEADER_CURL_TOOL_CB_SEE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_wrt.c b/external/libcurl_android/jni/libcurl/src/tool_cb_wrt.c
new file mode 100755
index 00000000..dfbf95cc
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_wrt.c
@@ -0,0 +1,152 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_cb_wrt.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+** callback for CURLOPT_WRITEFUNCTION
+*/
+
+size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
+{
+ size_t rc;
+ struct OutStruct *outs = userdata;
+ struct OperationConfig *config = outs->config;
+
+ /*
+ * Once that libcurl has called back tool_write_cb() the returned value
+ * is checked against the amount that was intended to be written, if
+ * it does not match then it fails with CURLE_WRITE_ERROR. So at this
+ * point returning a value different from sz*nmemb indicates failure.
+ */
+ const size_t failure = (sz * nmemb) ? 0 : 1;
+
+ if(!config)
+ return failure;
+
+#ifdef DEBUGBUILD
+ if(config->include_headers) {
+ if(sz * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
+ warnf(config, "Header data size exceeds single call write limit!\n");
+ return failure;
+ }
+ }
+ else {
+ if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) {
+ warnf(config, "Data size exceeds single call write limit!\n");
+ return failure;
+ }
+ }
+
+ {
+ /* Some internal congruency checks on received OutStruct */
+ bool check_fails = FALSE;
+ if(outs->filename) {
+ /* regular file */
+ if(!*outs->filename)
+ check_fails = TRUE;
+ if(!outs->s_isreg)
+ check_fails = TRUE;
+ if(outs->fopened && !outs->stream)
+ check_fails = TRUE;
+ if(!outs->fopened && outs->stream)
+ check_fails = TRUE;
+ if(!outs->fopened && outs->bytes)
+ check_fails = TRUE;
+ }
+ else {
+ /* standard stream */
+ if(!outs->stream || outs->s_isreg || outs->fopened)
+ check_fails = TRUE;
+ if(outs->alloc_filename || outs->is_cd_filename || outs->init)
+ check_fails = TRUE;
+ }
+ if(check_fails) {
+ warnf(config, "Invalid output struct data for write callback\n");
+ return failure;
+ }
+ }
+#endif
+
+ if(!outs->stream) {
+ FILE *file;
+
+ if(!outs->filename || !*outs->filename) {
+ warnf(config, "Remote filename has no length!\n");
+ return failure;
+ }
+
+ if(outs->is_cd_filename) {
+ /* don't overwrite existing files */
+ file = fopen(outs->filename, "rb");
+ if(file) {
+ fclose(file);
+ warnf(config, "Refusing to overwrite %s: %s\n", outs->filename,
+ strerror(EEXIST));
+ return failure;
+ }
+ }
+
+ /* open file for writing */
+ file = fopen(outs->filename, "wb");
+ if(!file) {
+ warnf(config, "Failed to create the file %s: %s\n", outs->filename,
+ strerror(errno));
+ return failure;
+ }
+ outs->s_isreg = TRUE;
+ outs->fopened = TRUE;
+ outs->stream = file;
+ outs->bytes = 0;
+ outs->init = 0;
+ }
+
+ rc = fwrite(buffer, sz, nmemb, outs->stream);
+
+ if((sz * nmemb) == rc)
+ /* we added this amount of data to the output */
+ outs->bytes += (sz * nmemb);
+
+ if(config->readbusy) {
+ config->readbusy = FALSE;
+ curl_easy_pause(config->easy, CURLPAUSE_CONT);
+ }
+
+ if(config->nobuffer) {
+ /* output buffering disabled */
+ int res = fflush(outs->stream);
+ if(res)
+ return failure;
+ }
+
+ return rc;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cb_wrt.h b/external/libcurl_android/jni/libcurl/src/tool_cb_wrt.h
new file mode 100755
index 00000000..380d8dd6
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cb_wrt.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_TOOL_CB_WRT_H
+#define HEADER_CURL_TOOL_CB_WRT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+** callback for CURLOPT_WRITEFUNCTION
+*/
+
+size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata);
+
+#endif /* HEADER_CURL_TOOL_CB_WRT_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cfgable.c b/external/libcurl_android/jni/libcurl/src/tool_cfgable.c
new file mode 100755
index 00000000..2fdae073
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cfgable.c
@@ -0,0 +1,154 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_cfgable.h"
+#include "tool_main.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void config_init(struct OperationConfig* config)
+{
+ memset(config, 0, sizeof(struct OperationConfig));
+
+ config->postfieldsize = -1;
+ config->use_httpget = FALSE;
+ config->create_dirs = FALSE;
+ config->maxredirs = DEFAULT_MAXREDIRS;
+ config->proto = CURLPROTO_ALL; /* FIXME: better to read from library */
+ config->proto_present = FALSE;
+ config->proto_redir =
+ CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
+ config->proto_redir_present = FALSE;
+}
+
+static void free_config_fields(struct OperationConfig *config)
+{
+ struct getout *urlnode;
+
+ Curl_safefree(config->random_file);
+ Curl_safefree(config->egd_file);
+ Curl_safefree(config->useragent);
+ Curl_safefree(config->cookie);
+ Curl_safefree(config->cookiejar);
+ Curl_safefree(config->cookiefile);
+
+ Curl_safefree(config->postfields);
+ Curl_safefree(config->referer);
+
+ Curl_safefree(config->headerfile);
+ Curl_safefree(config->ftpport);
+ Curl_safefree(config->iface);
+
+ Curl_safefree(config->range);
+
+ Curl_safefree(config->userpwd);
+ Curl_safefree(config->tls_username);
+ Curl_safefree(config->tls_password);
+ Curl_safefree(config->tls_authtype);
+ Curl_safefree(config->proxyuserpwd);
+ Curl_safefree(config->proxy);
+
+ Curl_safefree(config->dns_ipv6_addr);
+ Curl_safefree(config->dns_ipv4_addr);
+ Curl_safefree(config->dns_interface);
+ Curl_safefree(config->dns_servers);
+
+ Curl_safefree(config->noproxy);
+
+ Curl_safefree(config->mail_from);
+ curl_slist_free_all(config->mail_rcpt);
+ Curl_safefree(config->mail_auth);
+
+ Curl_safefree(config->netrc_file);
+
+ urlnode = config->url_list;
+ while(urlnode) {
+ struct getout *next = urlnode->next;
+ Curl_safefree(urlnode->url);
+ Curl_safefree(urlnode->outfile);
+ Curl_safefree(urlnode->infile);
+ Curl_safefree(urlnode);
+ urlnode = next;
+ }
+ config->url_list = NULL;
+ config->url_last = NULL;
+ config->url_get = NULL;
+ config->url_out = NULL;
+
+ Curl_safefree(config->cipher_list);
+ Curl_safefree(config->cert);
+ Curl_safefree(config->cert_type);
+ Curl_safefree(config->cacert);
+ Curl_safefree(config->capath);
+ Curl_safefree(config->crlfile);
+ Curl_safefree(config->key);
+ Curl_safefree(config->key_type);
+ Curl_safefree(config->key_passwd);
+ Curl_safefree(config->pubkey);
+ Curl_safefree(config->hostpubmd5);
+ Curl_safefree(config->engine);
+
+ Curl_safefree(config->customrequest);
+ Curl_safefree(config->krblevel);
+
+ Curl_safefree(config->xoauth2_bearer);
+
+ Curl_safefree(config->writeout);
+
+ curl_slist_free_all(config->quote);
+ curl_slist_free_all(config->postquote);
+ curl_slist_free_all(config->prequote);
+
+ curl_slist_free_all(config->headers);
+ curl_slist_free_all(config->proxyheaders);
+
+ if(config->httppost) {
+ curl_formfree(config->httppost);
+ config->httppost = NULL;
+ }
+ config->last_post = NULL;
+
+ curl_slist_free_all(config->telnet_options);
+ curl_slist_free_all(config->resolve);
+
+ Curl_safefree(config->socksproxy);
+ Curl_safefree(config->socks5_gssapi_service);
+
+ Curl_safefree(config->ftp_account);
+ Curl_safefree(config->ftp_alternative_to_user);
+}
+
+void config_free(struct OperationConfig *config)
+{
+ struct OperationConfig *last = config;
+
+ /* Free each of the structures in reverse order */
+ while(last) {
+ struct OperationConfig *prev = last->prev;
+
+ free_config_fields(last);
+ free(last);
+
+ last = prev;
+ }
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_cfgable.h b/external/libcurl_android/jni/libcurl/src/tool_cfgable.h
new file mode 100755
index 00000000..4ef26902
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_cfgable.h
@@ -0,0 +1,238 @@
+#ifndef HEADER_CURL_TOOL_CFGABLE_H
+#define HEADER_CURL_TOOL_CFGABLE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_sdecls.h"
+
+#include "tool_metalink.h"
+
+struct GlobalConfig;
+
+struct OperationConfig {
+ CURL *easy; /* A copy of the handle from GlobalConfig */
+ bool remote_time;
+ char *random_file;
+ char *egd_file;
+ char *useragent;
+ char *cookie; /* single line with specified cookies */
+ char *cookiejar; /* write to this file */
+ char *cookiefile; /* read from this file */
+ bool cookiesession; /* new session? */
+ bool encoding; /* Accept-Encoding please */
+ bool tr_encoding; /* Transfer-Encoding please */
+ unsigned long authtype; /* auth bitmask */
+ bool use_resume;
+ bool resume_from_current;
+ bool disable_epsv;
+ bool disable_eprt;
+ bool ftp_pret;
+ long proto;
+ bool proto_present;
+ long proto_redir;
+ bool proto_redir_present;
+ curl_off_t resume_from;
+ char *postfields;
+ curl_off_t postfieldsize;
+ char *referer;
+ double timeout;
+ double connecttimeout;
+ long maxredirs;
+ curl_off_t max_filesize;
+ char *headerfile;
+ char *ftpport;
+ char *iface;
+ int localport;
+ int localportrange;
+ unsigned short porttouse;
+ char *range;
+ long low_speed_limit;
+ long low_speed_time;
+ char *dns_servers; /* dot notation: 1.1.1.1;2.2.2.2 */
+ char *dns_interface; /* interface name */
+ char *dns_ipv4_addr; /* dot notation */
+ char *dns_ipv6_addr; /* dot notation */
+ char *userpwd;
+ char *login_options;
+ char *tls_username;
+ char *tls_password;
+ char *tls_authtype;
+ char *proxyuserpwd;
+ char *proxy;
+ int proxyver; /* set to CURLPROXY_HTTP* define */
+ char *noproxy;
+ char *mail_from;
+ struct curl_slist *mail_rcpt;
+ char *mail_auth;
+ bool sasl_ir; /* Enable/disable SASL initial response */
+ bool proxytunnel;
+ bool ftp_append; /* APPE on ftp */
+ bool use_ascii; /* select ascii or text transfer */
+ bool autoreferer; /* automatically set referer */
+ bool failonerror; /* fail on (HTTP) errors */
+ bool include_headers; /* send headers to data output */
+ bool no_body; /* don't get the body */
+ bool dirlistonly; /* only get the FTP dir list */
+ bool followlocation; /* follow http redirects */
+ bool unrestricted_auth; /* Continue to send authentication (user+password)
+ when following ocations, even when hostname
+ changed */
+ bool netrc_opt;
+ bool netrc;
+ char *netrc_file;
+ struct getout *url_list; /* point to the first node */
+ struct getout *url_last; /* point to the last/current node */
+ struct getout *url_get; /* point to the node to fill in URL */
+ struct getout *url_out; /* point to the node to fill in outfile */
+ char *cipher_list;
+ char *cert;
+ char *cert_type;
+ char *cacert;
+ char *capath;
+ char *crlfile;
+ char *key;
+ char *key_type;
+ char *key_passwd;
+ char *pubkey;
+ char *hostpubmd5;
+ char *engine;
+ bool crlf;
+ char *customrequest;
+ char *krblevel;
+ long httpversion;
+ bool nobuffer;
+ bool readbusy; /* set when reading input returns EAGAIN */
+ bool globoff;
+ bool use_httpget;
+ bool insecure_ok; /* set TRUE to allow insecure SSL connects */
+ bool create_dirs;
+ bool ftp_create_dirs;
+ bool ftp_skip_ip;
+ bool proxynegotiate;
+ bool proxyntlm;
+ bool proxydigest;
+ bool proxybasic;
+ bool proxyanyauth;
+ char *writeout; /* %-styled format string to output */
+ bool writeenv; /* write results to environment, if available */
+ struct curl_slist *quote;
+ struct curl_slist *postquote;
+ struct curl_slist *prequote;
+ long ssl_version;
+ long ip_version;
+ curl_TimeCond timecond;
+ time_t condtime;
+ struct curl_slist *headers;
+ struct curl_slist *proxyheaders;
+ struct curl_httppost *httppost;
+ struct curl_httppost *last_post;
+ struct curl_slist *telnet_options;
+ struct curl_slist *resolve;
+ HttpReq httpreq;
+
+ /* for bandwidth limiting features: */
+ curl_off_t sendpersecond; /* send to peer */
+ curl_off_t recvpersecond; /* receive from peer */
+
+ bool ftp_ssl;
+ bool ftp_ssl_reqd;
+ bool ftp_ssl_control;
+ bool ftp_ssl_ccc;
+ int ftp_ssl_ccc_mode;
+
+ char *socksproxy; /* set to server string */
+ int socksver; /* set to CURLPROXY_SOCKS* define */
+ char *socks5_gssapi_service; /* set service name for gssapi principal
+ * default rcmd */
+ int socks5_gssapi_nec ; /* The NEC reference server does not protect
+ * the encryption type exchange */
+
+ bool tcp_nodelay;
+ long req_retry; /* number of retries */
+ long retry_delay; /* delay between retries (in seconds) */
+ long retry_maxtime; /* maximum time to keep retrying */
+
+ char *ftp_account; /* for ACCT */
+ char *ftp_alternative_to_user; /* send command if USER/PASS fails */
+ int ftp_filemethod;
+ long tftp_blksize; /* TFTP BLKSIZE option */
+ bool ignorecl; /* --ignore-content-length */
+ bool disable_sessionid;
+
+ bool raw;
+ bool post301;
+ bool post302;
+ bool post303;
+ bool nokeepalive; /* for keepalive needs */
+ long alivetime;
+ bool content_disposition; /* use Content-disposition filename */
+
+ int default_node_flags; /* default flags to search for each 'node', which
+ is basically each given URL to transfer */
+
+ bool xattr; /* store metadata in extended attributes */
+ long gssapi_delegation;
+ bool ssl_allow_beast; /* allow this SSL vulnerability */
+
+ bool use_metalink; /* process given URLs as metalink XML file */
+ metalinkfile *metalinkfile_list; /* point to the first node */
+ metalinkfile *metalinkfile_last; /* point to the last/current node */
+#ifdef CURLDEBUG
+ bool test_event_based;
+#endif
+ char *xoauth2_bearer; /* XOAUTH2 bearer token */
+ bool nonpn; /* enable/disable TLS NPN extension */
+ bool noalpn; /* enable/disable TLS ALPN extension */
+
+ struct GlobalConfig *global;
+ struct OperationConfig *prev;
+ struct OperationConfig *next; /* Always last in the struct */
+};
+
+struct GlobalConfig {
+ CURL *easy; /* Once we have one, we keep it here */
+ int showerror; /* -1 == unset, default => show errors
+ 0 => -s is used to NOT show errors
+ 1 => -S has been used to show errors */
+ bool mute; /* don't show messages, --silent given */
+ bool noprogress; /* don't show progress bar --silent given */
+ bool isatty; /* Updated internally if output is a tty */
+ FILE *errors; /* Error stream, defaults to stderr */
+ bool errors_fopened; /* Whether error stream isn't stderr */
+ char *trace_dump; /* file to dump the network trace to */
+ FILE *trace_stream;
+ bool trace_fopened;
+ trace tracetype;
+ bool tracetime; /* include timestamp? */
+ int progressmode; /* CURL_PROGRESS_BAR / CURL_PROGRESS_STATS */
+ char *libcurl; /* Output libcurl code to this file name */
+
+ struct OperationConfig *first;
+ struct OperationConfig *current;
+ struct OperationConfig *last; /* Always last in the struct */
+};
+
+void config_init(struct OperationConfig *config);
+void config_free(struct OperationConfig *config);
+
+#endif /* HEADER_CURL_TOOL_CFGABLE_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_convert.c b/external/libcurl_android/jni/libcurl/src/tool_convert.c
new file mode 100755
index 00000000..ecce036a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_convert.c
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef CURL_DOES_CONVERSIONS
+
+#ifdef HAVE_ICONV
+# include <iconv.h>
+#endif
+
+#include "tool_convert.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef HAVE_ICONV
+
+/* curl tool iconv conversion descriptors */
+static iconv_t inbound_cd = (iconv_t)-1;
+static iconv_t outbound_cd = (iconv_t)-1;
+
+/* set default codesets for iconv */
+#ifndef CURL_ICONV_CODESET_OF_NETWORK
+# define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
+#endif
+
+/*
+ * convert_to_network() is a curl tool function to convert
+ * from the host encoding to ASCII on non-ASCII platforms.
+ */
+CURLcode convert_to_network(char *buffer, size_t length)
+{
+ /* translate from the host encoding to the network encoding */
+ char *input_ptr, *output_ptr;
+ size_t res, in_bytes, out_bytes;
+
+ /* open an iconv conversion descriptor if necessary */
+ if(outbound_cd == (iconv_t)-1) {
+ outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
+ CURL_ICONV_CODESET_OF_HOST);
+ if(outbound_cd == (iconv_t)-1) {
+ return CURLE_CONV_FAILED;
+ }
+ }
+ /* call iconv */
+ input_ptr = output_ptr = buffer;
+ in_bytes = out_bytes = length;
+ res = iconv(outbound_cd, &input_ptr, &in_bytes,
+ &output_ptr, &out_bytes);
+ if((res == (size_t)-1) || (in_bytes != 0)) {
+ return CURLE_CONV_FAILED;
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * convert_from_network() is a curl tool function
+ * for performing ASCII conversions on non-ASCII platforms.
+ */
+CURLcode convert_from_network(char *buffer, size_t length)
+{
+ /* translate from the network encoding to the host encoding */
+ char *input_ptr, *output_ptr;
+ size_t res, in_bytes, out_bytes;
+
+ /* open an iconv conversion descriptor if necessary */
+ if(inbound_cd == (iconv_t)-1) {
+ inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_OF_NETWORK);
+ if(inbound_cd == (iconv_t)-1) {
+ return CURLE_CONV_FAILED;
+ }
+ }
+ /* call iconv */
+ input_ptr = output_ptr = buffer;
+ in_bytes = out_bytes = length;
+ res = iconv(inbound_cd, &input_ptr, &in_bytes,
+ &output_ptr, &out_bytes);
+ if((res == (size_t)-1) || (in_bytes != 0)) {
+ return CURLE_CONV_FAILED;
+ }
+
+ return CURLE_OK;
+}
+
+void convert_cleanup(void)
+{
+ /* close iconv conversion descriptors */
+ if(inbound_cd != (iconv_t)-1)
+ (void)iconv_close(inbound_cd);
+ if(outbound_cd != (iconv_t)-1)
+ (void)iconv_close(outbound_cd);
+}
+
+#endif /* HAVE_ICONV */
+
+char convert_char(curl_infotype infotype, char this_char)
+{
+/* determine how this specific character should be displayed */
+ switch(infotype) {
+ case CURLINFO_DATA_IN:
+ case CURLINFO_DATA_OUT:
+ case CURLINFO_SSL_DATA_IN:
+ case CURLINFO_SSL_DATA_OUT:
+ /* data, treat as ASCII */
+ if((this_char >= 0x20) && (this_char < 0x7f)) {
+ /* printable ASCII hex value: convert to host encoding */
+ (void)convert_from_network(&this_char, 1);
+ }
+ else {
+ /* non-printable ASCII, use a replacement character */
+ return UNPRINTABLE_CHAR;
+ }
+ /* fall through to default */
+ default:
+ /* treat as host encoding */
+ if(ISPRINT(this_char)
+ && (this_char != '\t')
+ && (this_char != '\r')
+ && (this_char != '\n')) {
+ /* printable characters excluding tabs and line end characters */
+ return this_char;
+ }
+ break;
+ }
+ /* non-printable, use a replacement character */
+ return UNPRINTABLE_CHAR;
+}
+
+#endif /* CURL_DOES_CONVERSIONS */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_convert.h b/external/libcurl_android/jni/libcurl/src/tool_convert.h
new file mode 100755
index 00000000..32d473f9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_convert.h
@@ -0,0 +1,45 @@
+#ifndef HEADER_CURL_TOOL_CONVERT_H
+#define HEADER_CURL_TOOL_CONVERT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef CURL_DOES_CONVERSIONS
+
+#ifdef HAVE_ICONV
+
+CURLcode convert_to_network(char *buffer, size_t length);
+CURLcode convert_from_network(char *buffer, size_t length);
+void convert_cleanup(void);
+
+#endif /* HAVE_ICONV */
+
+char convert_char(curl_infotype infotype, char this_char);
+
+#endif /* CURL_DOES_CONVERSIONS */
+
+#if !defined(CURL_DOES_CONVERSIONS) || !defined(HAVE_ICONV)
+#define convert_cleanup() Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_TOOL_CONVERT_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_dirhie.c b/external/libcurl_android/jni/libcurl/src/tool_dirhie.c
new file mode 100755
index 00000000..5965f7a7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_dirhie.c
@@ -0,0 +1,147 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include <sys/stat.h>
+
+#ifdef WIN32
+# include <direct.h>
+#endif
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_dirhie.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef NETWARE
+# ifndef __NOVELL_LIBC__
+# define mkdir mkdir_510
+# endif
+#endif
+
+#ifdef WIN32
+# define mkdir(x,y) (mkdir)((x))
+# ifndef __POCC__
+# define F_OK 0
+# endif
+#endif
+
+static void show_dir_errno(FILE *errors, const char *name)
+{
+ switch(ERRNO) {
+#ifdef EACCES
+ case EACCES:
+ fprintf(errors, "You don't have permission to create %s.\n", name);
+ break;
+#endif
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG:
+ fprintf(errors, "The directory name %s is too long.\n", name);
+ break;
+#endif
+#ifdef EROFS
+ case EROFS:
+ fprintf(errors, "%s resides on a read-only file system.\n", name);
+ break;
+#endif
+#ifdef ENOSPC
+ case ENOSPC:
+ fprintf(errors, "No space left on the file system that will "
+ "contain the directory %s.\n", name);
+ break;
+#endif
+#ifdef EDQUOT
+ case EDQUOT:
+ fprintf(errors, "Cannot create directory %s because you "
+ "exceeded your quota.\n", name);
+ break;
+#endif
+ default :
+ fprintf(errors, "Error creating directory %s.\n", name);
+ break;
+ }
+}
+
+/*
+ * Create the needed directory hierarchy recursively in order to save
+ * multi-GETs in file output, ie:
+ * curl "http://my.site/dir[1-5]/file[1-5].txt" -o "dir#1/file#2.txt"
+ * should create all the dir* automagically
+ */
+
+CURLcode create_dir_hierarchy(const char *outfile, FILE *errors)
+{
+ char *tempdir;
+ char *tempdir2;
+ char *outdup;
+ char *dirbuildup;
+ CURLcode result = CURLE_OK;
+ size_t outlen;
+
+ outlen = strlen(outfile);
+ outdup = strdup(outfile);
+ if(!outdup)
+ return CURLE_OUT_OF_MEMORY;
+
+ dirbuildup = malloc(outlen + 1);
+ if(!dirbuildup) {
+ Curl_safefree(outdup);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ dirbuildup[0] = '\0';
+
+ tempdir = strtok(outdup, DIR_CHAR);
+
+ while(tempdir != NULL) {
+ tempdir2 = strtok(NULL, DIR_CHAR);
+ /* since strtok returns a token for the last word even
+ if not ending with DIR_CHAR, we need to prune it */
+ if(tempdir2 != NULL) {
+ size_t dlen = strlen(dirbuildup);
+ if(dlen)
+ snprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir);
+ else {
+ if(0 != strncmp(outdup, DIR_CHAR, 1))
+ strcpy(dirbuildup, tempdir);
+ else
+ snprintf(dirbuildup, outlen, "%s%s", DIR_CHAR, tempdir);
+ }
+ if(access(dirbuildup, F_OK) == -1) {
+ if(-1 == mkdir(dirbuildup,(mode_t)0000750)) {
+ show_dir_errno(errors, dirbuildup);
+ result = CURLE_WRITE_ERROR;
+ break; /* get out of loop */
+ }
+ }
+ }
+ tempdir = tempdir2;
+ }
+
+ Curl_safefree(dirbuildup);
+ Curl_safefree(outdup);
+
+ return result;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_dirhie.h b/external/libcurl_android/jni/libcurl/src/tool_dirhie.h
new file mode 100755
index 00000000..5f19575d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_dirhie.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TOOL_DIRHIE_H
+#define HEADER_CURL_TOOL_DIRHIE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+CURLcode create_dir_hierarchy(const char *outfile, FILE *errors);
+
+#endif /* HEADER_CURL_TOOL_DIRHIE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_doswin.c b/external/libcurl_android/jni/libcurl/src/tool_doswin.c
new file mode 100755
index 00000000..dd6e8bb8
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_doswin.c
@@ -0,0 +1,299 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(MSDOS) || defined(WIN32)
+
+#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
+# include <libgen.h>
+#endif
+
+#ifdef WIN32
+# include "tool_cfgable.h"
+# include "tool_libinfo.h"
+#endif
+
+#include "tool_bname.h"
+#include "tool_doswin.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+ * Macros ALWAYS_TRUE and ALWAYS_FALSE are used to avoid compiler warnings.
+ */
+
+#define ALWAYS_TRUE (1)
+#define ALWAYS_FALSE (0)
+
+#if defined(_MSC_VER) && !defined(__POCC__)
+# undef ALWAYS_TRUE
+# undef ALWAYS_FALSE
+# if (_MSC_VER < 1500)
+# define ALWAYS_TRUE (0, 1)
+# define ALWAYS_FALSE (1, 0)
+# else
+# define ALWAYS_TRUE \
+__pragma(warning(push)) \
+__pragma(warning(disable:4127)) \
+(1) \
+__pragma(warning(pop))
+# define ALWAYS_FALSE \
+__pragma(warning(push)) \
+__pragma(warning(disable:4127)) \
+(0) \
+__pragma(warning(pop))
+# endif
+#endif
+
+#ifdef WIN32
+# undef PATH_MAX
+# define PATH_MAX MAX_PATH
+#endif
+
+#ifndef S_ISCHR
+# ifdef S_IFCHR
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# else
+# define S_ISCHR(m) (0) /* cannot tell if file is a device */
+# endif
+#endif
+
+#ifdef WIN32
+# define _use_lfn(f) ALWAYS_TRUE /* long file names always available */
+#elif !defined(__DJGPP__) || (__DJGPP__ < 2) /* DJGPP 2.0 has _use_lfn() */
+# define _use_lfn(f) ALWAYS_FALSE /* long file names never available */
+#elif defined(__DJGPP__)
+# include <fcntl.h> /* _use_lfn(f) prototype */
+#endif
+
+static const char *msdosify (const char *file_name);
+static char *rename_if_dos_device_name (char *file_name);
+
+/*
+ * sanitize_dos_name: returns a newly allocated string holding a
+ * valid file name which will be a transformation of given argument
+ * in case this wasn't already a valid file name.
+ *
+ * This function takes ownership of given argument, free'ing it before
+ * returning. Caller is responsible of free'ing returned string. Upon
+ * out of memory condition function returns NULL.
+ */
+
+char *sanitize_dos_name(char *file_name)
+{
+ char new_name[PATH_MAX];
+
+ if(!file_name)
+ return NULL;
+
+ if(strlen(file_name) >= PATH_MAX)
+ file_name[PATH_MAX-1] = '\0'; /* truncate it */
+
+ strcpy(new_name, msdosify(file_name));
+
+ Curl_safefree(file_name);
+
+ return strdup(rename_if_dos_device_name(new_name));
+}
+
+/* The following functions are taken with modification from the DJGPP
+ * port of tar 1.12. They use algorithms originally from DJTAR. */
+
+static const char *msdosify (const char *file_name)
+{
+ static char dos_name[PATH_MAX];
+ static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */
+ "|<>\\\":?*"; /* illegal in DOS & W95 */
+ static const char *illegal_chars_w95 = &illegal_chars_dos[8];
+ int idx, dot_idx;
+ const char *s = file_name;
+ char *d = dos_name;
+ const char *const dlimit = dos_name + sizeof(dos_name) - 1;
+ const char *illegal_aliens = illegal_chars_dos;
+ size_t len = sizeof(illegal_chars_dos) - 1;
+
+ /* Support for Windows 9X VFAT systems, when available. */
+ if(_use_lfn(file_name)) {
+ illegal_aliens = illegal_chars_w95;
+ len -= (illegal_chars_w95 - illegal_chars_dos);
+ }
+
+ /* Get past the drive letter, if any. */
+ if(s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') {
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+
+ for(idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) {
+ if(memchr(illegal_aliens, *s, len)) {
+ /* Dots are special: DOS doesn't allow them as the leading character,
+ and a file name cannot have more than a single dot. We leave the
+ first non-leading dot alone, unless it comes too close to the
+ beginning of the name: we want sh.lex.c to become sh_lex.c, not
+ sh.lex-c. */
+ if(*s == '.') {
+ if(idx == 0 && (s[1] == '/' || (s[1] == '.' && s[2] == '/'))) {
+ /* Copy "./" and "../" verbatim. */
+ *d++ = *s++;
+ if(*s == '.')
+ *d++ = *s++;
+ *d = *s;
+ }
+ else if(idx == 0)
+ *d = '_';
+ else if(dot_idx >= 0) {
+ if(dot_idx < 5) { /* 5 is a heuristic ad-hoc'ery */
+ d[dot_idx - idx] = '_'; /* replace previous dot */
+ *d = '.';
+ }
+ else
+ *d = '-';
+ }
+ else
+ *d = '.';
+
+ if(*s == '.')
+ dot_idx = idx;
+ }
+ else if(*s == '+' && s[1] == '+') {
+ if(idx - 2 == dot_idx) { /* .c++, .h++ etc. */
+ *d++ = 'x';
+ *d = 'x';
+ }
+ else {
+ /* libg++ etc. */
+ memcpy (d, "plus", 4);
+ d += 3;
+ }
+ s++;
+ idx++;
+ }
+ else
+ *d = '_';
+ }
+ else
+ *d = *s;
+ if(*s == '/') {
+ idx = 0;
+ dot_idx = -1;
+ }
+ else
+ idx++;
+ }
+
+ *d = '\0';
+ return dos_name;
+}
+
+static char *rename_if_dos_device_name (char *file_name)
+{
+ /* We could have a file whose name is a device on MS-DOS. Trying to
+ * retrieve such a file would fail at best and wedge us at worst. We need
+ * to rename such files. */
+ char *base;
+ struct_stat st_buf;
+ char fname[PATH_MAX];
+
+ strncpy(fname, file_name, PATH_MAX-1);
+ fname[PATH_MAX-1] = '\0';
+ base = basename(fname);
+ if(((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) {
+ size_t blen = strlen(base);
+
+ if(strlen(fname) >= PATH_MAX-1) {
+ /* Make room for the '_' */
+ blen--;
+ base[blen] = '\0';
+ }
+ /* Prepend a '_'. */
+ memmove(base + 1, base, blen + 1);
+ base[0] = '_';
+ strcpy(file_name, fname);
+ }
+ return file_name;
+}
+
+#if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
+
+/*
+ * Disable program default argument globbing. We do it on our own.
+ */
+char **__crt0_glob_function(char *arg)
+{
+ (void)arg;
+ return (char**)0;
+}
+
+#endif /* MSDOS && (__DJGPP__ || __GO32__) */
+
+#ifdef WIN32
+
+/*
+ * Function to find CACert bundle on a Win32 platform using SearchPath.
+ * (SearchPath is already declared via inclusions done in setup header file)
+ * (Use the ASCII version instead of the unicode one!)
+ * The order of the directories it searches is:
+ * 1. application's directory
+ * 2. current working directory
+ * 3. Windows System directory (e.g. C:\windows\system32)
+ * 4. Windows Directory (e.g. C:\windows)
+ * 5. all directories along %PATH%
+ *
+ * For WinXP and later search order actually depends on registry value:
+ * HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeProcessSearchMode
+ */
+
+CURLcode FindWin32CACert(struct OperationConfig *config,
+ const char *bundle_file)
+{
+ CURLcode result = CURLE_OK;
+
+ /* search and set cert file only if libcurl supports SSL */
+ if(curlinfo->features & CURL_VERSION_SSL) {
+
+ DWORD res_len;
+ DWORD buf_tchar_size = PATH_MAX + 1;
+ DWORD buf_bytes_size = sizeof(TCHAR) * buf_tchar_size;
+ char *ptr = NULL;
+
+ char *buf = malloc(buf_bytes_size);
+ if(!buf)
+ return CURLE_OUT_OF_MEMORY;
+ buf[0] = '\0';
+
+ res_len = SearchPathA(NULL, bundle_file, NULL, buf_tchar_size, buf, &ptr);
+ if(res_len > 0) {
+ Curl_safefree(config->cacert);
+ config->cacert = strdup(buf);
+ if(!config->cacert)
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_safefree(buf);
+ }
+
+ return result;
+}
+
+#endif /* WIN32 */
+
+#endif /* MSDOS || WIN32 */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_doswin.h b/external/libcurl_android/jni/libcurl/src/tool_doswin.h
new file mode 100755
index 00000000..cd216dbc
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_doswin.h
@@ -0,0 +1,46 @@
+#ifndef HEADER_CURL_TOOL_DOSWIN_H
+#define HEADER_CURL_TOOL_DOSWIN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(MSDOS) || defined(WIN32)
+
+char *sanitize_dos_name(char *file_name);
+
+#if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
+
+char **__crt0_glob_function(char *arg);
+
+#endif /* MSDOS && (__DJGPP__ || __GO32__) */
+
+#ifdef WIN32
+
+CURLcode FindWin32CACert(struct OperationConfig *config,
+ const char *bundle_file);
+
+#endif /* WIN32 */
+
+#endif /* MSDOS || WIN32 */
+
+#endif /* HEADER_CURL_TOOL_DOSWIN_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_easysrc.c b/external/libcurl_android/jni/libcurl/src/tool_easysrc.c
new file mode 100755
index 00000000..3db27bb5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_easysrc.c
@@ -0,0 +1,229 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_easysrc.h"
+#include "tool_msgs.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* global variable definitions, for easy-interface source code generation */
+
+struct curl_slist *easysrc_decl = NULL; /* Variable declarations */
+struct curl_slist *easysrc_data = NULL; /* Build slists, forms etc. */
+struct curl_slist *easysrc_code = NULL; /* Setopt calls */
+struct curl_slist *easysrc_toohard = NULL; /* Unconvertible setopt */
+struct curl_slist *easysrc_clean = NULL; /* Clean up allocated data */
+int easysrc_form_count = 0;
+int easysrc_slist_count = 0;
+
+static const char *const srchead[]={
+ "/********* Sample code generated by the curl command line tool **********",
+ " * All curl_easy_setopt() options are documented at:",
+ " * http://curl.haxx.se/libcurl/c/curl_easy_setopt.html",
+ " ************************************************************************/",
+ "#include <curl/curl.h>",
+ "",
+ "int main(int argc, char *argv[])",
+ "{",
+ " CURLcode ret;",
+ " CURL *hnd;",
+ NULL
+};
+/* easysrc_decl declarations come here */
+/* easysrc_data initialisations come here */
+/* easysrc_code statements come here */
+static const char *const srchard[]={
+ "/* Here is a list of options the curl code used that cannot get generated",
+ " as source easily. You may select to either not use them or implement",
+ " them yourself.",
+ "",
+ NULL
+};
+static const char *const srcend[]={
+ "",
+ " return (int)ret;",
+ "}",
+ "/**** End of sample code ****/",
+ NULL
+};
+
+/* Clean up all source code if we run out of memory */
+static void easysrc_free(void)
+{
+ curl_slist_free_all(easysrc_decl);
+ easysrc_decl = NULL;
+ curl_slist_free_all(easysrc_data);
+ easysrc_data = NULL;
+ curl_slist_free_all(easysrc_code);
+ easysrc_code = NULL;
+ curl_slist_free_all(easysrc_toohard);
+ easysrc_toohard = NULL;
+ curl_slist_free_all(easysrc_clean);
+ easysrc_clean = NULL;
+}
+
+/* Add a source line to the main code or remarks */
+CURLcode easysrc_add(struct curl_slist **plist, const char *line)
+{
+ CURLcode ret = CURLE_OK;
+ struct curl_slist *list =
+ curl_slist_append(*plist, line);
+ if(!list) {
+ easysrc_free();
+ ret = CURLE_OUT_OF_MEMORY;
+ }
+ else
+ *plist = list;
+ return ret;
+}
+
+CURLcode easysrc_addf(struct curl_slist **plist, const char *fmt, ...)
+{
+ CURLcode ret;
+ char *bufp;
+ va_list ap;
+ va_start(ap, fmt);
+ bufp = curlx_mvaprintf(fmt, ap);
+ va_end(ap);
+ if(! bufp) {
+ ret = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ ret = easysrc_add(plist, bufp);
+ curl_free(bufp);
+ }
+ return ret;
+}
+
+#define CHKRET(v) do {CURLcode ret = (v); if(ret) return ret;} WHILE_FALSE
+
+CURLcode easysrc_init(void)
+{
+ CHKRET(easysrc_add(&easysrc_code,
+ "hnd = curl_easy_init();"));
+ return CURLE_OK;
+}
+
+CURLcode easysrc_perform(void)
+{
+ /* Note any setopt calls which we could not convert */
+ if(easysrc_toohard) {
+ int i;
+ struct curl_slist *ptr;
+ const char *c;
+ CHKRET(easysrc_add(&easysrc_code, ""));
+ /* Preamble comment */
+ for(i=0; ((c = srchard[i]) != NULL); i++)
+ CHKRET(easysrc_add(&easysrc_code, c));
+ /* Each unconverted option */
+ for(ptr=easysrc_toohard; ptr; ptr = ptr->next)
+ CHKRET(easysrc_add(&easysrc_code, ptr->data));
+ CHKRET(easysrc_add(&easysrc_code, ""));
+ CHKRET(easysrc_add(&easysrc_code, "*/"));
+
+ curl_slist_free_all(easysrc_toohard);
+ easysrc_toohard = NULL;
+ }
+
+ CHKRET(easysrc_add(&easysrc_code, ""));
+ CHKRET(easysrc_add(&easysrc_code, "ret = curl_easy_perform(hnd);"));
+ CHKRET(easysrc_add(&easysrc_code, ""));
+
+ return CURLE_OK;
+}
+
+CURLcode easysrc_cleanup(void)
+{
+ CHKRET(easysrc_add(&easysrc_code, "curl_easy_cleanup(hnd);"));
+ CHKRET(easysrc_add(&easysrc_code, "hnd = NULL;"));
+
+ return CURLE_OK;
+}
+
+void dumpeasysrc(struct GlobalConfig *config)
+{
+ struct curl_slist *ptr;
+ char *o = config->libcurl;
+
+ if(o) {
+ FILE *out;
+ bool fopened = FALSE;
+ if(strcmp(o, "-")) {
+ out = fopen(o, "w");
+ fopened = TRUE;
+ }
+ else
+ out = stdout;
+ if(!out)
+ warnf(config->current, "Failed to open %s to write libcurl code!\n", o);
+ else {
+ int i;
+ const char *c;
+
+ for(i=0; ((c = srchead[i]) != NULL); i++)
+ fprintf(out, "%s\n", c);
+
+ /* Declare variables used for complex setopt values */
+ for(ptr=easysrc_decl; ptr; ptr = ptr->next)
+ fprintf(out, " %s\n", ptr->data);
+
+ /* Set up complex values for setopt calls */
+ if(easysrc_data) {
+ fprintf(out, "\n");
+
+ for(ptr=easysrc_data; ptr; ptr = ptr->next)
+ fprintf(out, " %s\n", ptr->data);
+ }
+
+ fprintf(out, "\n");
+ for(ptr=easysrc_code; ptr; ptr = ptr->next) {
+ if(ptr->data[0]) {
+ fprintf(out, " %s\n", ptr->data);
+ }
+ else {
+ fprintf(out, "\n");
+ }
+ }
+
+ for(ptr=easysrc_clean; ptr; ptr = ptr->next)
+ fprintf(out, " %s\n", ptr->data);
+
+ for(i=0; ((c = srcend[i]) != NULL); i++)
+ fprintf(out, "%s\n", c);
+
+ if(fopened)
+ fclose(out);
+ }
+ }
+
+ easysrc_free();
+}
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_easysrc.h b/external/libcurl_android/jni/libcurl/src/tool_easysrc.h
new file mode 100755
index 00000000..07a4b787
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_easysrc.h
@@ -0,0 +1,48 @@
+#ifndef HEADER_CURL_TOOL_EASYSRC_H
+#define HEADER_CURL_TOOL_EASYSRC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+/* global variable declarations, for easy-interface source code generation */
+
+extern struct curl_slist *easysrc_decl; /* Variable declarations */
+extern struct curl_slist *easysrc_data; /* Build slists, forms etc. */
+extern struct curl_slist *easysrc_code; /* Setopt calls etc. */
+extern struct curl_slist *easysrc_toohard; /* Unconvertible setopt */
+extern struct curl_slist *easysrc_clean; /* Clean up (reverse order) */
+
+extern int easysrc_form_count; /* Number of curl_httppost variables */
+extern int easysrc_slist_count; /* Number of curl_slist variables */
+
+extern CURLcode easysrc_init(void);
+extern CURLcode easysrc_add(struct curl_slist **plist, const char *bupf);
+extern CURLcode easysrc_addf(struct curl_slist **plist, const char *fmt, ...);
+extern CURLcode easysrc_perform(void);
+extern CURLcode easysrc_cleanup(void);
+
+void dumpeasysrc(struct GlobalConfig *config);
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
+
+#endif /* HEADER_CURL_TOOL_EASYSRC_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_formparse.c b/external/libcurl_android/jni/libcurl/src/tool_formparse.c
new file mode 100755
index 00000000..1dcd897e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_formparse.c
@@ -0,0 +1,361 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_mfiles.h"
+#include "tool_msgs.h"
+#include "tool_formparse.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+
+/*
+ * helper function to get a word from form param
+ * after call get_parm_word, str either point to string end
+ * or point to any of end chars.
+ */
+static char *get_param_word(char **str, char **end_pos)
+{
+ char *ptr = *str;
+ char *word_begin = NULL;
+ char *ptr2;
+ char *escape = NULL;
+ const char *end_chars = ";,";
+
+ /* the first non-space char is here */
+ word_begin = ptr;
+ if(*ptr == '"') {
+ ++ptr;
+ while(*ptr) {
+ if(*ptr == '\\') {
+ if(ptr[1] == '\\' || ptr[1] == '"') {
+ /* remember the first escape position */
+ if(!escape)
+ escape = ptr;
+ /* skip escape of back-slash or double-quote */
+ ptr += 2;
+ continue;
+ }
+ }
+ if(*ptr == '"') {
+ *end_pos = ptr;
+ if(escape) {
+ /* has escape, we restore the unescaped string here */
+ ptr = ptr2 = escape;
+ do {
+ if(*ptr == '\\' && (ptr[1] == '\\' || ptr[1] == '"'))
+ ++ptr;
+ *ptr2++ = *ptr++;
+ }
+ while(ptr < *end_pos);
+ *end_pos = ptr2;
+ }
+ while(*ptr && NULL==strchr(end_chars, *ptr))
+ ++ptr;
+ *str = ptr;
+ return word_begin+1;
+ }
+ ++ptr;
+ }
+ /* end quote is missing, treat it as non-quoted. */
+ ptr = word_begin;
+ }
+
+ while(*ptr && NULL==strchr(end_chars, *ptr))
+ ++ptr;
+ *str = *end_pos = ptr;
+ return word_begin;
+}
+
+/***************************************************************************
+ *
+ * formparse()
+ *
+ * Reads a 'name=value' parameter and builds the appropriate linked list.
+ *
+ * Specify files to upload with 'name=@filename', or 'name=@"filename"'
+ * in case the filename contain ',' or ';'. Supports specified
+ * given Content-Type of the files. Such as ';type=<content-type>'.
+ *
+ * If literal_value is set, any initial '@' or '<' in the value string
+ * loses its special meaning, as does any embedded ';type='.
+ *
+ * You may specify more than one file for a single name (field). Specify
+ * multiple files by writing it like:
+ *
+ * 'name=@filename,filename2,filename3'
+ *
+ * or use double-quotes quote the filename:
+ *
+ * 'name=@"filename","filename2","filename3"'
+ *
+ * If you want content-types specified for each too, write them like:
+ *
+ * 'name=@filename;type=image/gif,filename2,filename3'
+ *
+ * If you want custom headers added for a single part, write them in a separate
+ * file and do like this:
+ *
+ * 'name=foo;headers=@headerfile' or why not
+ * 'name=@filemame;headers=@headerfile'
+ *
+ * To upload a file, but to fake the file name that will be included in the
+ * formpost, do like this:
+ *
+ * 'name=@filename;filename=/dev/null' or quote the faked filename like:
+ * 'name=@filename;filename="play, play, and play.txt"'
+ *
+ * If filename/path contains ',' or ';', it must be quoted by double-quotes,
+ * else curl will fail to figure out the correct filename. if the filename
+ * tobe quoted contains '"' or '\', '"' and '\' must be escaped by backslash.
+ *
+ * This function uses curl_formadd to fulfill it's job. Is heavily based on
+ * the old curl_formparse code.
+ *
+ ***************************************************************************/
+
+int formparse(struct OperationConfig *config,
+ const char *input,
+ struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ bool literal_value)
+{
+ /* nextarg MUST be a string in the format 'name=contents' and we'll
+ build a linked list with the info */
+ char name[256];
+ char *contents = NULL;
+ char type_major[128] = "";
+ char type_minor[128] = "";
+ char *contp;
+ const char *type = NULL;
+ char *sep;
+
+ if((1 == sscanf(input, "%255[^=]=", name)) &&
+ ((contp = strchr(input, '=')) != NULL)) {
+ /* the input was using the correct format */
+
+ /* Allocate the contents */
+ contents = strdup(contp+1);
+ if(!contents) {
+ fprintf(config->global->errors, "out of memory\n");
+ return 1;
+ }
+ contp = contents;
+
+ if('@' == contp[0] && !literal_value) {
+
+ /* we use the @-letter to indicate file name(s) */
+
+ struct multi_files *multi_start = NULL;
+ struct multi_files *multi_current = NULL;
+
+ char *ptr = contp;
+ char *end = ptr + strlen(ptr);
+
+ do {
+ /* since this was a file, it may have a content-type specifier
+ at the end too, or a filename. Or both. */
+ char *filename = NULL;
+ char *word_end;
+ bool semicolon;
+
+ type = NULL;
+
+ ++ptr;
+ contp = get_param_word(&ptr, &word_end);
+ semicolon = (';' == *ptr) ? TRUE : FALSE;
+ *word_end = '\0'; /* terminate the contp */
+
+ /* have other content, continue parse */
+ while(semicolon) {
+ /* have type or filename field */
+ ++ptr;
+ while(*ptr && (ISSPACE(*ptr)))
+ ++ptr;
+
+ if(checkprefix("type=", ptr)) {
+ /* set type pointer */
+ type = &ptr[5];
+
+ /* verify that this is a fine type specifier */
+ if(2 != sscanf(type, "%127[^/]/%127[^;,\n]",
+ type_major, type_minor)) {
+ warnf(config, "Illegally formatted content-type field!\n");
+ Curl_safefree(contents);
+ FreeMultiInfo(&multi_start, &multi_current);
+ return 2; /* illegal content-type syntax! */
+ }
+
+ /* now point beyond the content-type specifier */
+ sep = (char *)type + strlen(type_major)+strlen(type_minor)+1;
+
+ /* there's a semicolon following - we check if it is a filename
+ specified and if not we simply assume that it is text that
+ the user wants included in the type and include that too up
+ to the next sep. */
+ ptr = sep;
+ if(*sep==';') {
+ if(!checkprefix(";filename=", sep)) {
+ ptr = sep + 1;
+ (void)get_param_word(&ptr, &sep);
+ semicolon = (';' == *ptr) ? TRUE : FALSE;
+ }
+ }
+ else
+ semicolon = FALSE;
+
+ if(*sep)
+ *sep = '\0'; /* zero terminate type string */
+ }
+ else if(checkprefix("filename=", ptr)) {
+ ptr += 9;
+ filename = get_param_word(&ptr, &word_end);
+ semicolon = (';' == *ptr) ? TRUE : FALSE;
+ *word_end = '\0';
+ }
+ else {
+ /* unknown prefix, skip to next block */
+ char *unknown = NULL;
+ unknown = get_param_word(&ptr, &word_end);
+ semicolon = (';' == *ptr) ? TRUE : FALSE;
+ if(*unknown) {
+ *word_end = '\0';
+ warnf(config, "skip unknown form field: %s\n", unknown);
+ }
+ }
+ }
+ /* now ptr point to comma or string end */
+
+
+ /* if type == NULL curl_formadd takes care of the problem */
+
+ if(*contp && !AddMultiFiles(contp, type, filename, &multi_start,
+ &multi_current)) {
+ warnf(config, "Error building form post!\n");
+ Curl_safefree(contents);
+ FreeMultiInfo(&multi_start, &multi_current);
+ return 3;
+ }
+
+ /* *ptr could be '\0', so we just check with the string end */
+ } while(ptr < end); /* loop if there's another file name */
+
+ /* now we add the multiple files section */
+ if(multi_start) {
+ struct curl_forms *forms = NULL;
+ struct multi_files *start = multi_start;
+ unsigned int i, count = 0;
+ while(start) {
+ start = start->next;
+ ++count;
+ }
+ forms = malloc((count+1)*sizeof(struct curl_forms));
+ if(!forms) {
+ fprintf(config->global->errors, "Error building form post!\n");
+ Curl_safefree(contents);
+ FreeMultiInfo(&multi_start, &multi_current);
+ return 4;
+ }
+ for(i = 0, start = multi_start; i < count; ++i, start = start->next) {
+ forms[i].option = start->form.option;
+ forms[i].value = start->form.value;
+ }
+ forms[count].option = CURLFORM_END;
+ FreeMultiInfo(&multi_start, &multi_current);
+ if(curl_formadd(httppost, last_post,
+ CURLFORM_COPYNAME, name,
+ CURLFORM_ARRAY, forms, CURLFORM_END) != 0) {
+ warnf(config, "curl_formadd failed!\n");
+ Curl_safefree(forms);
+ Curl_safefree(contents);
+ return 5;
+ }
+ Curl_safefree(forms);
+ }
+ }
+ else {
+ struct curl_forms info[4];
+ int i = 0;
+ char *ct = literal_value ? NULL : strstr(contp, ";type=");
+
+ info[i].option = CURLFORM_COPYNAME;
+ info[i].value = name;
+ i++;
+
+ if(ct) {
+ info[i].option = CURLFORM_CONTENTTYPE;
+ info[i].value = &ct[6];
+ i++;
+ ct[0] = '\0'; /* zero terminate here */
+ }
+
+ if(contp[0]=='<' && !literal_value) {
+ info[i].option = CURLFORM_FILECONTENT;
+ info[i].value = contp+1;
+ i++;
+ info[i].option = CURLFORM_END;
+
+ if(curl_formadd(httppost, last_post,
+ CURLFORM_ARRAY, info, CURLFORM_END ) != 0) {
+ warnf(config, "curl_formadd failed, possibly the file %s is bad!\n",
+ contp+1);
+ Curl_safefree(contents);
+ return 6;
+ }
+ }
+ else {
+#ifdef CURL_DOES_CONVERSIONS
+ if(convert_to_network(contp, strlen(contp))) {
+ warnf(config, "curl_formadd failed!\n");
+ Curl_safefree(contents);
+ return 7;
+ }
+#endif
+ info[i].option = CURLFORM_COPYCONTENTS;
+ info[i].value = contp;
+ i++;
+ info[i].option = CURLFORM_END;
+ if(curl_formadd(httppost, last_post,
+ CURLFORM_ARRAY, info, CURLFORM_END) != 0) {
+ warnf(config, "curl_formadd failed!\n");
+ Curl_safefree(contents);
+ return 8;
+ }
+ }
+ }
+
+ }
+ else {
+ warnf(config, "Illegally formatted input field!\n");
+ return 1;
+ }
+ Curl_safefree(contents);
+ return 0;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_formparse.h b/external/libcurl_android/jni/libcurl/src/tool_formparse.h
new file mode 100755
index 00000000..f7736264
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_formparse.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_TOOL_FORMPARSE_H
+#define HEADER_CURL_TOOL_FORMPARSE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+int formparse(struct OperationConfig *config,
+ const char *input,
+ struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ bool literal_value);
+
+#endif /* HEADER_CURL_TOOL_FORMPARSE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_getparam.c b/external/libcurl_android/jni/libcurl/src/tool_getparam.c
new file mode 100755
index 00000000..180878ba
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_getparam.c
@@ -0,0 +1,1889 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_binmode.h"
+#include "tool_cfgable.h"
+#include "tool_cb_prg.h"
+#include "tool_formparse.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+#include "tool_libinfo.h"
+#include "tool_metalink.h"
+#include "tool_msgs.h"
+#include "tool_paramhlp.h"
+#include "tool_parsecfg.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef MSDOS
+# define USE_WATT32
+#endif
+
+#define GetStr(str,val) do { \
+ if(*(str)) { \
+ free(*(str)); \
+ *(str) = NULL; \
+ } \
+ if((val)) { \
+ *(str) = strdup((val)); \
+ if(!(*(str))) \
+ return PARAM_NO_MEM; \
+ } \
+} WHILE_FALSE
+
+struct LongShort {
+ const char *letter; /* short name option */
+ const char *lname; /* long name option */
+ bool extraparam; /* whether it takes an additional argument */
+};
+
+static const struct LongShort aliases[]= {
+ /* all these ones, starting with "*" or "$" as a short-option have *no*
+ short option to mention. */
+ {"*", "url", TRUE},
+ {"*4", "dns-ipv4-addr", TRUE},
+ {"*6", "dns-ipv6-addr", TRUE},
+ {"*a", "random-file", TRUE},
+ {"*b", "egd-file", TRUE},
+ {"*B", "oauth2-bearer", TRUE},
+ {"*c", "connect-timeout", TRUE},
+ {"*d", "ciphers", TRUE},
+ {"*D", "dns-interface", TRUE},
+ {"*e", "disable-epsv", FALSE},
+ {"*E", "epsv", FALSE},
+ /* 'epsv' made like this to make --no-epsv and --epsv to work
+ although --disable-epsv is the documented option */
+#ifdef USE_ENVIRONMENT
+ {"*f", "environment", FALSE},
+#endif
+ {"*F", "dns-servers", TRUE},
+ {"*g", "trace", TRUE},
+ {"*G", "npn", FALSE},
+ {"*h", "trace-ascii", TRUE},
+ {"*H", "alpn", FALSE},
+ {"*i", "limit-rate", TRUE},
+ {"*j", "compressed", FALSE},
+ {"*J", "tr-encoding", FALSE},
+ {"*k", "digest", FALSE},
+ {"*l", "negotiate", FALSE},
+ {"*m", "ntlm", FALSE},
+ {"*M", "ntlm-wb", FALSE},
+ {"*n", "basic", FALSE},
+ {"*o", "anyauth", FALSE},
+#ifdef USE_WATT32
+ {"*p", "wdebug", FALSE},
+#endif
+ {"*q", "ftp-create-dirs", FALSE},
+ {"*r", "create-dirs", FALSE},
+ {"*s", "max-redirs", TRUE},
+ {"*t", "proxy-ntlm", FALSE},
+ {"*u", "crlf", FALSE},
+ {"*v", "stderr", TRUE},
+ {"*w", "interface", TRUE},
+ {"*x", "krb" , TRUE},
+ {"*x", "krb4" , TRUE},
+ /* 'krb4' is the previous name */
+ {"*y", "max-filesize", TRUE},
+ {"*z", "disable-eprt", FALSE},
+ {"*Z", "eprt", FALSE},
+ /* 'eprt' made like this to make --no-eprt and --eprt to work
+ although --disable-eprt is the documented option */
+ {"$a", "ftp-ssl", FALSE},
+ /* 'ftp-ssl' deprecated name since 7.20.0 */
+ {"$a", "ssl", FALSE},
+ /* 'ssl' new option name in 7.20.0, previously this was ftp-ssl */
+ {"$b", "ftp-pasv", FALSE},
+ {"$c", "socks5", TRUE},
+ {"$c", "socks", TRUE},
+ /* 'socks' is how the option once was documented but we prefer
+ the --socks5 version for explicit version */
+ {"$d", "tcp-nodelay", FALSE},
+ {"$e", "proxy-digest", FALSE},
+ {"$f", "proxy-basic", FALSE},
+ {"$g", "retry", TRUE},
+ {"$h", "retry-delay", TRUE},
+ {"$i", "retry-max-time", TRUE},
+ {"$k", "proxy-negotiate", FALSE},
+ {"$m", "ftp-account", TRUE},
+ {"$n", "proxy-anyauth", FALSE},
+ {"$o", "trace-time", FALSE},
+ {"$p", "ignore-content-length", FALSE},
+ {"$q", "ftp-skip-pasv-ip", FALSE},
+ {"$r", "ftp-method", TRUE},
+ {"$s", "local-port", TRUE},
+ {"$t", "socks4", TRUE},
+ {"$T", "socks4a", TRUE},
+ {"$u", "ftp-alternative-to-user", TRUE},
+ {"$v", "ftp-ssl-reqd", FALSE},
+ /* 'ftp-ssl-reqd' deprecated name since 7.20.0 */
+ {"$v", "ssl-reqd", FALSE},
+ /* 'ssl-reqd' new in 7.20.0, previously this was ftp-ssl-reqd */
+ {"$w", "sessionid", FALSE},
+ /* ¡sessionid' listed as --no-sessionid in the help */
+ {"$x", "ftp-ssl-control", FALSE},
+ {"$y", "ftp-ssl-ccc", FALSE},
+ {"$j", "ftp-ssl-ccc-mode", TRUE},
+ {"$z", "libcurl", TRUE},
+ {"$#", "raw", FALSE},
+ {"$0", "post301", FALSE},
+ {"$1", "keepalive", FALSE},
+ /* 'keepalive' listed as --no-keepalive in the help */
+ {"$2", "socks5-hostname", TRUE},
+ {"$3", "keepalive-time", TRUE},
+ {"$4", "post302", FALSE},
+ {"$5", "noproxy", TRUE},
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ {"$6", "socks5-gssapi-service", TRUE},
+ {"$7", "socks5-gssapi-nec", FALSE},
+#endif
+ {"$8", "proxy1.0", TRUE},
+ {"$9", "tftp-blksize", TRUE},
+ {"$A", "mail-from", TRUE},
+ {"$B", "mail-rcpt", TRUE},
+ {"$C", "ftp-pret", FALSE},
+ {"$D", "proto", TRUE},
+ {"$E", "proto-redir", TRUE},
+ {"$F", "resolve", TRUE},
+ {"$G", "delegation", TRUE},
+ {"$H", "mail-auth", TRUE},
+ {"$I", "post303", FALSE},
+ {"$J", "metalink", FALSE},
+ {"$K", "sasl-ir", FALSE},
+ {"$L", "test-event", FALSE},
+ {"0", "http1.0", FALSE},
+ {"01", "http1.1", FALSE},
+ {"02", "http2", FALSE},
+ {"1", "tlsv1", FALSE},
+ {"10", "tlsv1.0", FALSE},
+ {"11", "tlsv1.1", FALSE},
+ {"12", "tlsv1.2", FALSE},
+ {"2", "sslv2", FALSE},
+ {"3", "sslv3", FALSE},
+ {"4", "ipv4", FALSE},
+ {"6", "ipv6", FALSE},
+ {"a", "append", FALSE},
+ {"A", "user-agent", TRUE},
+ {"b", "cookie", TRUE},
+ {"B", "use-ascii", FALSE},
+ {"c", "cookie-jar", TRUE},
+ {"C", "continue-at", TRUE},
+ {"d", "data", TRUE},
+ {"da", "data-ascii", TRUE},
+ {"db", "data-binary", TRUE},
+ {"de", "data-urlencode", TRUE},
+ {"D", "dump-header", TRUE},
+ {"e", "referer", TRUE},
+ {"E", "cert", TRUE},
+ {"Ea", "cacert", TRUE},
+ {"Eb", "cert-type", TRUE},
+ {"Ec", "key", TRUE},
+ {"Ed", "key-type", TRUE},
+ {"Ee", "pass", TRUE},
+ {"Ef", "engine", TRUE},
+ {"Eg", "capath ", TRUE},
+ {"Eh", "pubkey", TRUE},
+ {"Ei", "hostpubmd5", TRUE},
+ {"Ej", "crlfile", TRUE},
+ {"Ek", "tlsuser", TRUE},
+ {"El", "tlspassword", TRUE},
+ {"Em", "tlsauthtype", TRUE},
+ {"En", "ssl-allow-beast", FALSE},
+ {"Eo", "login-options", TRUE},
+ {"f", "fail", FALSE},
+ {"F", "form", TRUE},
+ {"Fs", "form-string", TRUE},
+ {"g", "globoff", FALSE},
+ {"G", "get", FALSE},
+ {"h", "help", FALSE},
+ {"H", "header", TRUE},
+ {"Hp", "proxy-header", TRUE},
+ {"i", "include", FALSE},
+ {"I", "head", FALSE},
+ {"j", "junk-session-cookies", FALSE},
+ {"J", "remote-header-name", FALSE},
+ {"k", "insecure", FALSE},
+ {"K", "config", TRUE},
+ {"l", "list-only", FALSE},
+ {"L", "location", FALSE},
+ {"Lt", "location-trusted", FALSE},
+ {"m", "max-time", TRUE},
+ {"M", "manual", FALSE},
+ {"n", "netrc", FALSE},
+ {"no", "netrc-optional", FALSE},
+ {"ne", "netrc-file", TRUE},
+ {"N", "buffer", FALSE},
+ /* 'buffer' listed as --no-buffer in the help */
+ {"o", "output", TRUE},
+ {"O", "remote-name", FALSE},
+ {"Oa", "remote-name-all", FALSE},
+ {"p", "proxytunnel", FALSE},
+ {"P", "ftpport", TRUE},
+ /* 'ftpport' old version */
+ {"P", "ftp-port", TRUE},
+ {"q", "disable", FALSE},
+ {"Q", "quote", TRUE},
+ {"r", "range", TRUE},
+ {"R", "remote-time", FALSE},
+ {"s", "silent", FALSE},
+ {"S", "show-error", FALSE},
+ {"t", "telnet-options", TRUE},
+ /* 'telnet-options' documented as telnet-option */
+ {"T", "upload-file", TRUE},
+ {"u", "user", TRUE},
+ {"U", "proxy-user", TRUE},
+ {"v", "verbose", FALSE},
+ {"V", "version", FALSE},
+ {"w", "write-out", TRUE},
+ {"x", "proxy", TRUE},
+ {"X", "request", TRUE},
+ {"X", "http-request", TRUE},
+ /* 'http-request' OBSOLETE VERSION */
+ {"Y", "speed-limit", TRUE},
+ {"y", "speed-time", TRUE},
+ {"z", "time-cond", TRUE},
+ {"#", "progress-bar", FALSE},
+ {":", "next", FALSE},
+ {"~", "xattr", FALSE},
+};
+
+/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
+ * We allow ':' and '\' to be escaped by '\' so that we can use certificate
+ * nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
+ * for details. */
+#ifndef UNITTESTS
+static
+#endif
+void parse_cert_parameter(const char *cert_parameter,
+ char **certname,
+ char **passphrase)
+{
+ size_t param_length = strlen(cert_parameter);
+ size_t span;
+ const char *param_place = NULL;
+ char *certname_place = NULL;
+ *certname = NULL;
+ *passphrase = NULL;
+
+ /* most trivial assumption: cert_parameter is empty */
+ if(param_length == 0)
+ return;
+
+ /* next less trivial: cert_parameter contains no colon nor backslash; this
+ * means no passphrase was given and no characters escaped */
+ if(!strpbrk(cert_parameter, ":\\")) {
+ *certname = strdup(cert_parameter);
+ return;
+ }
+ /* deal with escaped chars; find unescaped colon if it exists */
+ certname_place = malloc(param_length + 1);
+ if(!certname_place)
+ return;
+
+ *certname = certname_place;
+ param_place = cert_parameter;
+ while(*param_place) {
+ span = strcspn(param_place, ":\\");
+ strncpy(certname_place, param_place, span);
+ param_place += span;
+ certname_place += span;
+ /* we just ate all the non-special chars. now we're on either a special
+ * char or the end of the string. */
+ switch(*param_place) {
+ case '\0':
+ break;
+ case '\\':
+ param_place++;
+ switch(*param_place) {
+ case '\0':
+ *certname_place++ = '\\';
+ break;
+ case '\\':
+ *certname_place++ = '\\';
+ param_place++;
+ break;
+ case ':':
+ *certname_place++ = ':';
+ param_place++;
+ break;
+ default:
+ *certname_place++ = '\\';
+ *certname_place++ = *param_place;
+ param_place++;
+ break;
+ }
+ break;
+ case ':':
+ /* Since we live in a world of weirdness and confusion, the win32
+ dudes can use : when using drive letters and thus c:\file:password
+ needs to work. In order not to break compatibility, we still use : as
+ separator, but we try to detect when it is used for a file name! On
+ windows. */
+#ifdef WIN32
+ if(param_place &&
+ (param_place == &cert_parameter[1]) &&
+ (cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
+ (ISALPHA(cert_parameter[0])) ) {
+ /* colon in the second column, followed by a backslash, and the
+ first character is an alphabetic letter:
+
+ this is a drive letter colon */
+ *certname_place++ = ':';
+ param_place++;
+ break;
+ }
+#endif
+ /* escaped colons and Windows drive letter colons were handled
+ * above; if we're still here, this is a separating colon */
+ param_place++;
+ if(strlen(param_place) > 0) {
+ *passphrase = strdup(param_place);
+ }
+ goto done;
+ }
+ }
+done:
+ *certname_place = '\0';
+}
+
+ParameterError getparameter(char *flag, /* f or -long-flag */
+ char *nextarg, /* NULL if unset */
+ bool *usedarg, /* set to TRUE if the arg
+ has been used */
+ struct GlobalConfig *global,
+ struct OperationConfig *config)
+{
+ char letter;
+ char subletter = '\0'; /* subletters can only occur on long options */
+ int rc;
+ const char *parse = NULL;
+ unsigned int j;
+ time_t now;
+ int hit = -1;
+ bool longopt = FALSE;
+ bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
+ ParameterError err;
+ bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
+ by using --OPTION or --no-OPTION */
+
+
+ if(('-' != flag[0]) ||
+ (('-' == flag[0]) && ('-' == flag[1]))) {
+ /* this should be a long name */
+ char *word = ('-' == flag[0]) ? flag+2 : flag;
+ size_t fnam = strlen(word);
+ int numhits = 0;
+
+ if(!strncmp(word, "no-", 3)) {
+ /* disable this option but ignore the "no-" part when looking for it */
+ word += 3;
+ toggle = FALSE;
+ }
+
+ for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
+ if(curlx_strnequal(aliases[j].lname, word, fnam)) {
+ longopt = TRUE;
+ numhits++;
+ if(curlx_raw_equal(aliases[j].lname, word)) {
+ parse = aliases[j].letter;
+ hit = j;
+ numhits = 1; /* a single unique hit */
+ break;
+ }
+ parse = aliases[j].letter;
+ hit = j;
+ }
+ }
+ if(numhits > 1) {
+ /* this is at least the second match! */
+ return PARAM_OPTION_AMBIGUOUS;
+ }
+ if(hit < 0) {
+ return PARAM_OPTION_UNKNOWN;
+ }
+ }
+ else {
+ flag++; /* prefixed with one dash, pass it */
+ hit = -1;
+ parse = flag;
+ }
+
+ do {
+ /* we can loop here if we have multiple single-letters */
+
+ if(!longopt) {
+ if(NULL != parse) {
+ letter = (char)*parse;
+ }
+ else {
+ letter = '\0';
+ }
+ subletter='\0';
+ }
+ else {
+ letter = parse[0];
+ subletter = parse[1];
+ }
+ *usedarg = FALSE; /* default is that we don't use the arg */
+
+ if(hit < 0) {
+ for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
+ if(letter == aliases[j].letter[0]) {
+ hit = j;
+ break;
+ }
+ }
+ if(hit < 0) {
+ return PARAM_OPTION_UNKNOWN;
+ }
+ }
+
+ if(aliases[hit].extraparam) {
+ /* this option requires an extra parameter */
+ if(!longopt && parse[1]) {
+ nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
+ singleopt = TRUE; /* don't loop anymore after this */
+ }
+ else if(!nextarg)
+ return PARAM_REQUIRES_PARAMETER;
+ else
+ *usedarg = TRUE; /* mark it as used */
+ }
+
+ switch(letter) {
+ case '*': /* options without a short option */
+ switch(subletter) {
+ case '4': /* --dns-ipv4-addr */
+ /* addr in dot notation */
+ GetStr(&config->dns_ipv4_addr, nextarg);
+ break;
+ case '6': /* --dns-ipv6-addr */
+ /* addr in dot notation */
+ GetStr(&config->dns_ipv6_addr, nextarg);
+ break;
+ case 'a': /* random-file */
+ GetStr(&config->random_file, nextarg);
+ break;
+ case 'b': /* egd-file */
+ GetStr(&config->egd_file, nextarg);
+ break;
+ case 'B': /* XOAUTH2 Bearer */
+ GetStr(&config->xoauth2_bearer, nextarg);
+ break;
+ case 'c': /* connect-timeout */
+ err = str2udouble(&config->connecttimeout, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'd': /* ciphers */
+ GetStr(&config->cipher_list, nextarg);
+ break;
+ case 'D': /* --dns-interface */
+ /* interface name */
+ GetStr(&config->dns_interface, nextarg);
+ break;
+ case 'e': /* --disable-epsv */
+ config->disable_epsv = toggle;
+ break;
+ case 'E': /* --epsv */
+ config->disable_epsv = (!toggle)?TRUE:FALSE;
+ break;
+#ifdef USE_ENVIRONMENT
+ case 'f':
+ config->writeenv = toggle;
+ break;
+#endif
+ case 'F': /* --dns-servers */
+ /* IP addrs of DNS servers */
+ GetStr(&config->dns_servers, nextarg);
+ break;
+ case 'g': /* --trace */
+ GetStr(&global->trace_dump, nextarg);
+ if(global->tracetype && (global->tracetype != TRACE_BIN))
+ warnf(config, "--trace overrides an earlier trace/verbose option\n");
+ global->tracetype = TRACE_BIN;
+ break;
+ case 'G': /* --npn */
+ config->nonpn = (!toggle)?TRUE:FALSE;
+ break;
+ case 'h': /* --trace-ascii */
+ GetStr(&global->trace_dump, nextarg);
+ if(global->tracetype && (global->tracetype != TRACE_ASCII))
+ warnf(config,
+ "--trace-ascii overrides an earlier trace/verbose option\n");
+ global->tracetype = TRACE_ASCII;
+ break;
+ case 'H': /* --alpn */
+ config->noalpn = (!toggle)?TRUE:FALSE;
+ break;
+ case 'i': /* --limit-rate */
+ {
+ /* We support G, M, K too */
+ char *unit;
+ curl_off_t value = curlx_strtoofft(nextarg, &unit, 0);
+
+ if(!*unit)
+ unit = (char *)"b";
+ else if(strlen(unit) > 1)
+ unit = (char *)"w"; /* unsupported */
+
+ switch(*unit) {
+ case 'G':
+ case 'g':
+ value *= 1024*1024*1024;
+ break;
+ case 'M':
+ case 'm':
+ value *= 1024*1024;
+ break;
+ case 'K':
+ case 'k':
+ value *= 1024;
+ break;
+ case 'b':
+ case 'B':
+ /* for plain bytes, leave as-is */
+ break;
+ default:
+ warnf(config, "unsupported rate unit. Use G, M, K or B!\n");
+ return PARAM_BAD_USE;
+ }
+ config->recvpersecond = value;
+ config->sendpersecond = value;
+ }
+ break;
+
+ case 'j': /* --compressed */
+ if(toggle && !(curlinfo->features & CURL_VERSION_LIBZ))
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->encoding = toggle;
+ break;
+
+ case 'J': /* --tr-encoding */
+ config->tr_encoding = toggle;
+ break;
+
+ case 'k': /* --digest */
+ if(toggle)
+ config->authtype |= CURLAUTH_DIGEST;
+ else
+ config->authtype &= ~CURLAUTH_DIGEST;
+ break;
+
+ case 'l': /* --negotiate */
+ if(toggle) {
+ if(curlinfo->features & CURL_VERSION_SPNEGO)
+ config->authtype |= CURLAUTH_NEGOTIATE;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ else
+ config->authtype &= ~CURLAUTH_NEGOTIATE;
+ break;
+
+ case 'm': /* --ntlm */
+ if(toggle) {
+ if(curlinfo->features & CURL_VERSION_NTLM)
+ config->authtype |= CURLAUTH_NTLM;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ else
+ config->authtype &= ~CURLAUTH_NTLM;
+ break;
+
+ case 'M': /* --ntlm-wb */
+ if(toggle) {
+ if(curlinfo->features & CURL_VERSION_NTLM_WB)
+ config->authtype |= CURLAUTH_NTLM_WB;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ }
+ else
+ config->authtype &= ~CURLAUTH_NTLM_WB;
+ break;
+
+ case 'n': /* --basic for completeness */
+ if(toggle)
+ config->authtype |= CURLAUTH_BASIC;
+ else
+ config->authtype &= ~CURLAUTH_BASIC;
+ break;
+
+ case 'o': /* --anyauth, let libcurl pick it */
+ if(toggle)
+ config->authtype = CURLAUTH_ANY;
+ /* --no-anyauth simply doesn't touch it */
+ break;
+
+#ifdef USE_WATT32
+ case 'p': /* --wdebug */
+ dbug_init();
+ break;
+#endif
+ case 'q': /* --ftp-create-dirs */
+ config->ftp_create_dirs = toggle;
+ break;
+
+ case 'r': /* --create-dirs */
+ config->create_dirs = toggle;
+ break;
+
+ case 's': /* --max-redirs */
+ /* specified max no of redirects (http(s)), this accepts -1 as a
+ special condition */
+ err = str2num(&config->maxredirs, nextarg);
+ if(err)
+ return err;
+ if(config->maxredirs < -1)
+ return PARAM_BAD_NUMERIC;
+ break;
+
+ case 't': /* --proxy-ntlm */
+ if(curlinfo->features & CURL_VERSION_NTLM)
+ config->proxyntlm = toggle;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+
+ case 'u': /* --crlf */
+ /* LF -> CRLF conversion? */
+ config->crlf = toggle;
+ break;
+
+ case 'v': /* --stderr */
+ if(strcmp(nextarg, "-")) {
+ FILE *newfile = fopen(nextarg, "wt");
+ if(!newfile)
+ warnf(config, "Failed to open %s!\n", nextarg);
+ else {
+ if(global->errors_fopened)
+ fclose(global->errors);
+ global->errors = newfile;
+ global->errors_fopened = TRUE;
+ }
+ }
+ else
+ global->errors = stdout;
+ break;
+ case 'w': /* --interface */
+ /* interface */
+ GetStr(&config->iface, nextarg);
+ break;
+ case 'x': /* --krb */
+ /* kerberos level string */
+ if(curlinfo->features & CURL_VERSION_KERBEROS4)
+ GetStr(&config->krblevel, nextarg);
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case 'y': /* --max-filesize */
+ err = str2offset(&config->max_filesize, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'z': /* --disable-eprt */
+ config->disable_eprt = toggle;
+ break;
+ case 'Z': /* --eprt */
+ config->disable_eprt = (!toggle)?TRUE:FALSE;
+ break;
+
+ default: /* the URL! */
+ {
+ struct getout *url;
+ if(config->url_get || ((config->url_get = config->url_list) != NULL)) {
+ /* there's a node here, if it already is filled-in continue to find
+ an "empty" node */
+ while(config->url_get && (config->url_get->flags & GETOUT_URL))
+ config->url_get = config->url_get->next;
+ }
+
+ /* now there might or might not be an available node to fill in! */
+
+ if(config->url_get)
+ /* existing node */
+ url = config->url_get;
+ else
+ /* there was no free node, create one! */
+ url = new_getout(config);
+
+ if(!url)
+ return PARAM_NO_MEM;
+ else {
+ /* fill in the URL */
+ GetStr(&url->url, nextarg);
+ url->flags |= GETOUT_URL;
+ }
+ }
+ }
+ break;
+ case '$': /* more options without a short option */
+ switch(subletter) {
+ case 'a': /* --ftp-ssl */
+ if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->ftp_ssl = toggle;
+ break;
+ case 'b': /* --ftp-pasv */
+ Curl_safefree(config->ftpport);
+ break;
+ case 'c': /* --socks5 specifies a socks5 proxy to use, and resolves
+ the name locally and passes on the resolved address */
+ GetStr(&config->socksproxy, nextarg);
+ config->socksver = CURLPROXY_SOCKS5;
+ break;
+ case 't': /* --socks4 specifies a socks4 proxy to use */
+ GetStr(&config->socksproxy, nextarg);
+ config->socksver = CURLPROXY_SOCKS4;
+ break;
+ case 'T': /* --socks4a specifies a socks4a proxy to use */
+ GetStr(&config->socksproxy, nextarg);
+ config->socksver = CURLPROXY_SOCKS4A;
+ break;
+ case '2': /* --socks5-hostname specifies a socks5 proxy and enables name
+ resolving with the proxy */
+ GetStr(&config->socksproxy, nextarg);
+ config->socksver = CURLPROXY_SOCKS5_HOSTNAME;
+ break;
+ case 'd': /* --tcp-nodelay option */
+ config->tcp_nodelay = toggle;
+ break;
+ case 'e': /* --proxy-digest */
+ config->proxydigest = toggle;
+ break;
+ case 'f': /* --proxy-basic */
+ config->proxybasic = toggle;
+ break;
+ case 'g': /* --retry */
+ err = str2unum(&config->req_retry, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'h': /* --retry-delay */
+ err = str2unum(&config->retry_delay, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'i': /* --retry-max-time */
+ err = str2unum(&config->retry_maxtime, nextarg);
+ if(err)
+ return err;
+ break;
+
+ case 'k': /* --proxy-negotiate */
+ if(curlinfo->features & CURL_VERSION_SPNEGO)
+ config->proxynegotiate = toggle;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+
+ case 'm': /* --ftp-account */
+ GetStr(&config->ftp_account, nextarg);
+ break;
+ case 'n': /* --proxy-anyauth */
+ config->proxyanyauth = toggle;
+ break;
+ case 'o': /* --trace-time */
+ global->tracetime = toggle;
+ break;
+ case 'p': /* --ignore-content-length */
+ config->ignorecl = toggle;
+ break;
+ case 'q': /* --ftp-skip-pasv-ip */
+ config->ftp_skip_ip = toggle;
+ break;
+ case 'r': /* --ftp-method (undocumented at this point) */
+ config->ftp_filemethod = ftpfilemethod(config, nextarg);
+ break;
+ case 's': /* --local-port */
+ rc = sscanf(nextarg, "%d - %d",
+ &config->localport,
+ &config->localportrange);
+ if(!rc)
+ return PARAM_BAD_USE;
+ else if(rc == 1)
+ config->localportrange = 1; /* default number of ports to try */
+ else {
+ config->localportrange -= config->localport;
+ if(config->localportrange < 1) {
+ warnf(config, "bad range input\n");
+ return PARAM_BAD_USE;
+ }
+ }
+ break;
+ case 'u': /* --ftp-alternative-to-user */
+ GetStr(&config->ftp_alternative_to_user, nextarg);
+ break;
+ case 'v': /* --ftp-ssl-reqd */
+ if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->ftp_ssl_reqd = toggle;
+ break;
+ case 'w': /* --no-sessionid */
+ config->disable_sessionid = (!toggle)?TRUE:FALSE;
+ break;
+ case 'x': /* --ftp-ssl-control */
+ if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->ftp_ssl_control = toggle;
+ break;
+ case 'y': /* --ftp-ssl-ccc */
+ config->ftp_ssl_ccc = toggle;
+ if(!config->ftp_ssl_ccc_mode)
+ config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
+ break;
+ case 'j': /* --ftp-ssl-ccc-mode */
+ config->ftp_ssl_ccc = TRUE;
+ config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
+ break;
+ case 'z': /* --libcurl */
+#ifdef CURL_DISABLE_LIBCURL_OPTION
+ warnf(config,
+ "--libcurl option was disabled at build-time!\n");
+ return PARAM_OPTION_UNKNOWN;
+#else
+ GetStr(&global->libcurl, nextarg);
+ break;
+#endif
+ case '#': /* --raw */
+ config->raw = toggle;
+ break;
+ case '0': /* --post301 */
+ config->post301 = toggle;
+ break;
+ case '1': /* --no-keepalive */
+ config->nokeepalive = (!toggle)?TRUE:FALSE;
+ break;
+ case '3': /* --keepalive-time */
+ err = str2unum(&config->alivetime, nextarg);
+ if(err)
+ return err;
+ break;
+ case '4': /* --post302 */
+ config->post302 = toggle;
+ break;
+ case 'I': /* --post303 */
+ config->post303 = toggle;
+ break;
+ case '5': /* --noproxy */
+ /* This specifies the noproxy list */
+ GetStr(&config->noproxy, nextarg);
+ break;
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ case '6': /* --socks5-gssapi-service */
+ GetStr(&config->socks5_gssapi_service, nextarg);
+ break;
+ case '7': /* --socks5-gssapi-nec*/
+ config->socks5_gssapi_nec = toggle;
+ break;
+#endif
+ case '8': /* --proxy1.0 */
+ /* http 1.0 proxy */
+ GetStr(&config->proxy, nextarg);
+ config->proxyver = CURLPROXY_HTTP_1_0;
+ break;
+ case '9': /* --tftp-blksize */
+ err = str2unum(&config->tftp_blksize, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'A': /* --mail-from */
+ GetStr(&config->mail_from, nextarg);
+ break;
+ case 'B': /* --mail-rcpt */
+ /* append receiver to a list */
+ err = add2list(&config->mail_rcpt, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'C': /* --ftp-pret */
+ config->ftp_pret = toggle;
+ break;
+ case 'D': /* --proto */
+ config->proto_present = TRUE;
+ if(proto2num(config, &config->proto, nextarg))
+ return PARAM_BAD_USE;
+ break;
+ case 'E': /* --proto-redir */
+ config->proto_redir_present = TRUE;
+ if(proto2num(config, &config->proto_redir, nextarg))
+ return PARAM_BAD_USE;
+ break;
+ case 'F': /* --resolve */
+ err = add2list(&config->resolve, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'G': /* --delegation LEVEL */
+ config->gssapi_delegation = delegation(config, nextarg);
+ break;
+ case 'H': /* --mail-auth */
+ GetStr(&config->mail_auth, nextarg);
+ break;
+ case 'J': /* --metalink */
+ {
+#ifdef USE_METALINK
+ int mlmaj, mlmin, mlpatch;
+ metalink_get_version(&mlmaj, &mlmin, &mlpatch);
+ if((mlmaj*10000)+(mlmin*100)+mlpatch < CURL_REQ_LIBMETALINK_VERS) {
+ warnf(config,
+ "--metalink option cannot be used because the version of "
+ "the linked libmetalink library is too old. "
+ "Required: %d.%d.%d, found %d.%d.%d\n",
+ CURL_REQ_LIBMETALINK_MAJOR,
+ CURL_REQ_LIBMETALINK_MINOR,
+ CURL_REQ_LIBMETALINK_PATCH,
+ mlmaj, mlmin, mlpatch);
+ return PARAM_BAD_USE;
+ }
+ else
+ config->use_metalink = toggle;
+#else
+ warnf(config, "--metalink option is ignored because the binary is "
+ "built without the Metalink support.\n");
+#endif
+ break;
+ }
+ case 'K': /* --sasl-ir */
+ config->sasl_ir = toggle;
+ break;
+ case 'L': /* --test-event */
+#ifdef CURLDEBUG
+ config->test_event_based = toggle;
+#else
+ warnf(config, "--test-event is ignored unless a debug build!\n");
+#endif
+ break;
+ }
+ break;
+ case '#': /* --progress-bar */
+ if(toggle)
+ global->progressmode = CURL_PROGRESS_BAR;
+ else
+ global->progressmode = CURL_PROGRESS_STATS;
+ break;
+ case ':': /* --next */
+ return PARAM_NEXT_OPERATION;
+ case '~': /* --xattr */
+ config->xattr = toggle;
+ break;
+ case '0': /* --http* options */
+ switch(subletter) {
+ case '\0':
+ /* HTTP version 1.0 */
+ config->httpversion = CURL_HTTP_VERSION_1_0;
+ break;
+ case '1':
+ /* HTTP version 1.1 */
+ config->httpversion = CURL_HTTP_VERSION_1_1;
+ break;
+ case '2':
+ /* HTTP version 2.0 */
+ config->httpversion = CURL_HTTP_VERSION_2_0;
+ break;
+ }
+ break;
+ case '1': /* --tlsv1* options */
+ switch(subletter) {
+ case '\0':
+ /* TLS version 1.x */
+ config->ssl_version = CURL_SSLVERSION_TLSv1;
+ break;
+ case '0':
+ /* TLS version 1.0 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_0;
+ break;
+ case '1':
+ /* TLS version 1.1 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_1;
+ break;
+ case '2':
+ /* TLS version 1.2 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_2;
+ break;
+ }
+ break;
+ case '2':
+ /* SSL version 2 */
+ config->ssl_version = CURL_SSLVERSION_SSLv2;
+ break;
+ case '3':
+ /* SSL version 3 */
+ config->ssl_version = CURL_SSLVERSION_SSLv3;
+ break;
+ case '4':
+ /* IPv4 */
+ config->ip_version = 4;
+ break;
+ case '6':
+ /* IPv6 */
+ config->ip_version = 6;
+ break;
+ case 'a':
+ /* This makes the FTP sessions use APPE instead of STOR */
+ config->ftp_append = toggle;
+ break;
+ case 'A':
+ /* This specifies the User-Agent name */
+ GetStr(&config->useragent, nextarg);
+ break;
+ case 'b': /* cookie string coming up: */
+ if(nextarg[0] == '@') {
+ nextarg++;
+ }
+ else if(strchr(nextarg, '=')) {
+ /* A cookie string must have a =-letter */
+ GetStr(&config->cookie, nextarg);
+ break;
+ }
+ /* We have a cookie file to read from! */
+ GetStr(&config->cookiefile, nextarg);
+ break;
+ case 'B':
+ /* use ASCII/text when transferring */
+ config->use_ascii = toggle;
+ break;
+ case 'c':
+ /* get the file name to dump all cookies in */
+ GetStr(&config->cookiejar, nextarg);
+ break;
+ case 'C':
+ /* This makes us continue an ftp transfer at given position */
+ if(!curlx_strequal(nextarg, "-")) {
+ err = str2offset(&config->resume_from, nextarg);
+ if(err)
+ return err;
+ config->resume_from_current = FALSE;
+ }
+ else {
+ config->resume_from_current = TRUE;
+ config->resume_from = 0;
+ }
+ config->use_resume=TRUE;
+ break;
+ case 'd':
+ /* postfield data */
+ {
+ char *postdata = NULL;
+ FILE *file;
+ size_t size = 0;
+
+ if(subletter == 'e') { /* --data-urlencode*/
+ /* [name]=[content], we encode the content part only
+ * [name]@[file name]
+ *
+ * Case 2: we first load the file using that name and then encode
+ * the content.
+ */
+ const char *p = strchr(nextarg, '=');
+ size_t nlen;
+ char is_file;
+ if(!p)
+ /* there was no '=' letter, check for a '@' instead */
+ p = strchr(nextarg, '@');
+ if(p) {
+ nlen = p - nextarg; /* length of the name part */
+ is_file = *p++; /* pass the separator */
+ }
+ else {
+ /* neither @ nor =, so no name and it isn't a file */
+ nlen = is_file = 0;
+ p = nextarg;
+ }
+ if('@' == is_file) {
+ /* a '@' letter, it means that a file name or - (stdin) follows */
+
+ if(curlx_strequal("-", p)) {
+ file = stdin;
+ set_binmode(stdin);
+ }
+ else {
+ file = fopen(p, "rb");
+ if(!file)
+ warnf(config,
+ "Couldn't read data from file \"%s\", this makes "
+ "an empty POST.\n", nextarg);
+ }
+
+ err = file2memory(&postdata, &size, file);
+
+ if(file && (file != stdin))
+ fclose(file);
+ if(err)
+ return err;
+ }
+ else {
+ GetStr(&postdata, p);
+ if(postdata)
+ size = strlen(postdata);
+ }
+
+ if(!postdata) {
+ /* no data from the file, point to a zero byte string to make this
+ get sent as a POST anyway */
+ postdata = strdup("");
+ if(!postdata)
+ return PARAM_NO_MEM;
+ size = 0;
+ }
+ else {
+ char *enc = curl_easy_escape(config->easy, postdata, (int)size);
+ Curl_safefree(postdata); /* no matter if it worked or not */
+ if(enc) {
+ /* now make a string with the name from above and append the
+ encoded string */
+ size_t outlen = nlen + strlen(enc) + 2;
+ char *n = malloc(outlen);
+ if(!n) {
+ curl_free(enc);
+ return PARAM_NO_MEM;
+ }
+ if(nlen > 0) { /* only append '=' if we have a name */
+ snprintf(n, outlen, "%.*s=%s", nlen, nextarg, enc);
+ size = outlen-1;
+ }
+ else {
+ strcpy(n, enc);
+ size = outlen-2; /* since no '=' was inserted */
+ }
+ curl_free(enc);
+ postdata = n;
+ }
+ else
+ return PARAM_NO_MEM;
+ }
+ }
+ else if('@' == *nextarg) {
+ /* the data begins with a '@' letter, it means that a file name
+ or - (stdin) follows */
+ nextarg++; /* pass the @ */
+
+ if(curlx_strequal("-", nextarg)) {
+ file = stdin;
+ if(subletter == 'b') /* forced data-binary */
+ set_binmode(stdin);
+ }
+ else {
+ file = fopen(nextarg, "rb");
+ if(!file)
+ warnf(config, "Couldn't read data from file \"%s\", this makes "
+ "an empty POST.\n", nextarg);
+ }
+
+ if(subletter == 'b')
+ /* forced binary */
+ err = file2memory(&postdata, &size, file);
+ else {
+ err = file2string(&postdata, file);
+ if(postdata)
+ size = strlen(postdata);
+ }
+
+ if(file && (file != stdin))
+ fclose(file);
+ if(err)
+ return err;
+
+ if(!postdata) {
+ /* no data from the file, point to a zero byte string to make this
+ get sent as a POST anyway */
+ postdata = strdup("");
+ if(!postdata)
+ return PARAM_NO_MEM;
+ }
+ }
+ else {
+ GetStr(&postdata, nextarg);
+ if(postdata)
+ size = strlen(postdata);
+ }
+
+#ifdef CURL_DOES_CONVERSIONS
+ if(subletter != 'b') {
+ /* NOT forced binary, convert to ASCII */
+ if(convert_to_network(postdata, strlen(postdata))) {
+ Curl_safefree(postdata);
+ return PARAM_NO_MEM;
+ }
+ }
+#endif
+
+ if(config->postfields) {
+ /* we already have a string, we append this one with a separating
+ &-letter */
+ char *oldpost = config->postfields;
+ curl_off_t oldlen = config->postfieldsize;
+ curl_off_t newlen = oldlen + curlx_uztoso(size) + 2;
+ config->postfields = malloc((size_t)newlen);
+ if(!config->postfields) {
+ Curl_safefree(oldpost);
+ Curl_safefree(postdata);
+ return PARAM_NO_MEM;
+ }
+ memcpy(config->postfields, oldpost, (size_t)oldlen);
+ /* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
+ config->postfields[oldlen] = '\x26';
+ memcpy(&config->postfields[oldlen+1], postdata, size);
+ config->postfields[oldlen+1+size] = '\0';
+ Curl_safefree(oldpost);
+ Curl_safefree(postdata);
+ config->postfieldsize += size+1;
+ }
+ else {
+ config->postfields = postdata;
+ config->postfieldsize = curlx_uztoso(size);
+ }
+ }
+ /*
+ We can't set the request type here, as this data might be used in
+ a simple GET if -G is used. Already or soon.
+
+ if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq)) {
+ Curl_safefree(postdata);
+ return PARAM_BAD_USE;
+ }
+ */
+ break;
+ case 'D':
+ /* dump-header to given file name */
+ GetStr(&config->headerfile, nextarg);
+ break;
+ case 'e':
+ {
+ char *ptr = strstr(nextarg, ";auto");
+ if(ptr) {
+ /* Automatic referer requested, this may be combined with a
+ set initial one */
+ config->autoreferer = TRUE;
+ *ptr = 0; /* zero terminate here */
+ }
+ else
+ config->autoreferer = FALSE;
+ GetStr(&config->referer, nextarg);
+ }
+ break;
+ case 'E':
+ switch(subletter) {
+ case 'a': /* CA info PEM file */
+ /* CA info PEM file */
+ GetStr(&config->cacert, nextarg);
+ break;
+ case 'b': /* cert file type */
+ GetStr(&config->cert_type, nextarg);
+ break;
+ case 'c': /* private key file */
+ GetStr(&config->key, nextarg);
+ break;
+ case 'd': /* private key file type */
+ GetStr(&config->key_type, nextarg);
+ break;
+ case 'e': /* private key passphrase */
+ GetStr(&config->key_passwd, nextarg);
+ cleanarg(nextarg);
+ break;
+ case 'f': /* crypto engine */
+ GetStr(&config->engine, nextarg);
+ if(config->engine && curlx_raw_equal(config->engine,"list"))
+ return PARAM_ENGINES_REQUESTED;
+ break;
+ case 'g': /* CA info PEM file */
+ /* CA cert directory */
+ GetStr(&config->capath, nextarg);
+ break;
+ case 'h': /* --pubkey public key file */
+ GetStr(&config->pubkey, nextarg);
+ break;
+ case 'i': /* --hostpubmd5 md5 of the host public key */
+ GetStr(&config->hostpubmd5, nextarg);
+ if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
+ return PARAM_BAD_USE;
+ break;
+ case 'j': /* CRL info PEM file */
+ /* CRL file */
+ GetStr(&config->crlfile, nextarg);
+ break;
+ case 'k': /* TLS username */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
+ GetStr(&config->tls_username, nextarg);
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case 'l': /* TLS password */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
+ GetStr(&config->tls_password, nextarg);
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case 'm': /* TLS authentication type */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ GetStr(&config->tls_authtype, nextarg);
+ if(!strequal(config->tls_authtype, "SRP"))
+ return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
+ }
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case 'n': /* no empty SSL fragments, --ssl-allow-beast */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->ssl_allow_beast = toggle;
+ break;
+
+ case 'o': /* --login-options */
+ GetStr(&config->login_options, nextarg);
+ break;
+
+ default: /* certificate file */
+ {
+ char *certname, *passphrase;
+ parse_cert_parameter(nextarg, &certname, &passphrase);
+ Curl_safefree(config->cert);
+ config->cert = certname;
+ if(passphrase) {
+ Curl_safefree(config->key_passwd);
+ config->key_passwd = passphrase;
+ }
+ cleanarg(nextarg);
+ }
+ }
+ break;
+ case 'f':
+ /* fail hard on errors */
+ config->failonerror = toggle;
+ break;
+ case 'F':
+ /* "form data" simulation, this is a little advanced so lets do our best
+ to sort this out slowly and carefully */
+ if(formparse(config,
+ nextarg,
+ &config->httppost,
+ &config->last_post,
+ (subletter=='s')?TRUE:FALSE)) /* 's' means literal string */
+ return PARAM_BAD_USE;
+ if(SetHTTPrequest(config, HTTPREQ_POST, &config->httpreq))
+ return PARAM_BAD_USE;
+ break;
+
+ case 'g': /* g disables URLglobbing */
+ config->globoff = toggle;
+ break;
+
+ case 'G': /* HTTP GET */
+ config->use_httpget = TRUE;
+ break;
+
+ case 'h': /* h for help */
+ if(toggle) {
+ return PARAM_HELP_REQUESTED;
+ }
+ /* we now actually support --no-help too! */
+ break;
+ case 'H':
+ /* A custom header to append to a list */
+ if(subletter == 'p') /* --proxy-header */
+ err = add2list(&config->proxyheaders, nextarg);
+ else
+ err = add2list(&config->headers, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'i':
+ config->include_headers = toggle; /* include the headers as well in the
+ general output stream */
+ break;
+ case 'j':
+ config->cookiesession = toggle;
+ break;
+ case 'I':
+ /*
+ * no_body will imply include_headers later on
+ */
+ config->no_body = toggle;
+ if(SetHTTPrequest(config,
+ (config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
+ &config->httpreq))
+ return PARAM_BAD_USE;
+ break;
+ case 'J': /* --remote-header-name */
+ if(config->include_headers) {
+ warnf(config,
+ "--include and --remote-header-name cannot be combined.\n");
+ return PARAM_BAD_USE;
+ }
+ config->content_disposition = toggle;
+ break;
+ case 'k': /* allow insecure SSL connects */
+ config->insecure_ok = toggle;
+ break;
+ case 'K': /* parse config file */
+ if(parseconfig(nextarg, global))
+ warnf(config, "error trying read config from the '%s' file\n",
+ nextarg);
+ break;
+ case 'l':
+ config->dirlistonly = toggle; /* only list the names of the FTP dir */
+ break;
+ case 'L':
+ config->followlocation = toggle; /* Follow Location: HTTP headers */
+ switch (subletter) {
+ case 't':
+ /* Continue to send authentication (user+password) when following
+ * locations, even when hostname changed */
+ config->unrestricted_auth = toggle;
+ break;
+ }
+ break;
+ case 'm':
+ /* specified max time */
+ err = str2udouble(&config->timeout, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'M': /* M for manual, huge help */
+ if(toggle) { /* --no-manual shows no manual... */
+#ifdef USE_MANUAL
+ return PARAM_MANUAL_REQUESTED;
+#else
+ warnf(config,
+ "built-in manual was disabled at build-time!\n");
+ return PARAM_OPTION_UNKNOWN;
+#endif
+ }
+ break;
+ case 'n':
+ switch(subletter) {
+ case 'o': /* CA info PEM file */
+ /* use .netrc or URL */
+ config->netrc_opt = toggle;
+ break;
+ case 'e': /* netrc-file */
+ GetStr(&config->netrc_file, nextarg);
+ break;
+ default:
+ /* pick info from .netrc, if this is used for http, curl will
+ automatically enfore user+password with the request */
+ config->netrc = toggle;
+ break;
+ }
+ break;
+ case 'N':
+ /* disable the output I/O buffering. note that the option is called
+ --buffer but is mostly used in the negative form: --no-buffer */
+ if(longopt)
+ config->nobuffer = (!toggle)?TRUE:FALSE;
+ else
+ config->nobuffer = toggle;
+ break;
+ case 'O': /* --remote-name */
+ if(subletter == 'a') { /* --remote-name-all */
+ config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
+ break;
+ }
+ /* fall-through! */
+ case 'o': /* --output */
+ /* output file */
+ {
+ struct getout *url;
+ if(config->url_out || ((config->url_out = config->url_list) != NULL)) {
+ /* there's a node here, if it already is filled-in continue to find
+ an "empty" node */
+ while(config->url_out && (config->url_out->flags & GETOUT_OUTFILE))
+ config->url_out = config->url_out->next;
+ }
+
+ /* now there might or might not be an available node to fill in! */
+
+ if(config->url_out)
+ /* existing node */
+ url = config->url_out;
+ else
+ /* there was no free node, create one! */
+ url = new_getout(config);
+
+ if(!url)
+ return PARAM_NO_MEM;
+ else {
+ /* fill in the outfile */
+ if('o' == letter) {
+ GetStr(&url->outfile, nextarg);
+ url->flags &= ~GETOUT_USEREMOTE; /* switch off */
+ }
+ else {
+ url->outfile = NULL; /* leave it */
+ if(toggle)
+ url->flags |= GETOUT_USEREMOTE; /* switch on */
+ else
+ url->flags &= ~GETOUT_USEREMOTE; /* switch off */
+ }
+ url->flags |= GETOUT_OUTFILE;
+ }
+ }
+ break;
+ case 'P':
+ /* This makes the FTP sessions use PORT instead of PASV */
+ /* use <eth0> or <192.168.10.10> style addresses. Anything except
+ this will make us try to get the "default" address.
+ NOTE: this is a changed behaviour since the released 4.1!
+ */
+ GetStr(&config->ftpport, nextarg);
+ break;
+ case 'p':
+ /* proxy tunnel for non-http protocols */
+ config->proxytunnel = toggle;
+ break;
+
+ case 'q': /* if used first, already taken care of, we do it like
+ this so we don't cause an error! */
+ break;
+ case 'Q':
+ /* QUOTE command to send to FTP server */
+ switch(nextarg[0]) {
+ case '-':
+ /* prefixed with a dash makes it a POST TRANSFER one */
+ nextarg++;
+ err = add2list(&config->postquote, nextarg);
+ break;
+ case '+':
+ /* prefixed with a plus makes it a just-before-transfer one */
+ nextarg++;
+ err = add2list(&config->prequote, nextarg);
+ break;
+ default:
+ err = add2list(&config->quote, nextarg);
+ break;
+ }
+ if(err)
+ return err;
+ break;
+ case 'r':
+ /* Specifying a range WITHOUT A DASH will create an illegal HTTP range
+ (and won't actually be range by definition). The man page previously
+ claimed that to be a good way, why this code is added to work-around
+ it. */
+ if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
+ char buffer[32];
+ curl_off_t off;
+ warnf(config,
+ "A specified range MUST include at least one dash (-). "
+ "Appending one for you!\n");
+ off = curlx_strtoofft(nextarg, NULL, 10);
+ snprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
+ Curl_safefree(config->range);
+ config->range = strdup(buffer);
+ if(!config->range)
+ return PARAM_NO_MEM;
+ }
+ {
+ /* byte range requested */
+ char *tmp_range;
+ tmp_range = nextarg;
+ while(*tmp_range != '\0') {
+ if(!ISDIGIT(*tmp_range) && *tmp_range != '-' && *tmp_range != ',') {
+ warnf(config,"Invalid character is found in given range. "
+ "A specified range MUST have only digits in "
+ "\'start\'-\'stop\'. The server's response to this "
+ "request is uncertain.\n");
+ break;
+ }
+ tmp_range++;
+ }
+ /* byte range requested */
+ GetStr(&config->range, nextarg);
+ }
+ break;
+ case 'R':
+ /* use remote file's time */
+ config->remote_time = toggle;
+ break;
+ case 's':
+ /* don't show progress meter, don't show errors : */
+ if(toggle)
+ global->mute = global->noprogress = TRUE;
+ else
+ global->mute = global->noprogress = FALSE;
+ if(global->showerror < 0)
+ /* if still on the default value, set showerror to the reverse of
+ toggle. This is to allow -S and -s to be used in an independent
+ order but still have the same effect. */
+ global->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
+ break;
+ case 'S':
+ /* show errors */
+ global->showerror = toggle?1:0; /* toggle on if used with -s */
+ break;
+ case 't':
+ /* Telnet options */
+ err = add2list(&config->telnet_options, nextarg);
+ if(err)
+ return err;
+ break;
+ case 'T':
+ /* we are uploading */
+ {
+ struct getout *url;
+ if(config->url_out || ((config->url_out = config->url_list) != NULL)) {
+ /* there's a node here, if it already is filled-in continue to find
+ an "empty" node */
+ while(config->url_out && (config->url_out->flags & GETOUT_UPLOAD))
+ config->url_out = config->url_out->next;
+ }
+
+ /* now there might or might not be an available node to fill in! */
+
+ if(config->url_out)
+ /* existing node */
+ url = config->url_out;
+ else
+ /* there was no free node, create one! */
+ url = new_getout(config);
+
+ if(!url)
+ return PARAM_NO_MEM;
+ else {
+ url->flags |= GETOUT_UPLOAD; /* mark -T used */
+ if(!*nextarg)
+ url->flags |= GETOUT_NOUPLOAD;
+ else {
+ /* "-" equals stdin, but keep the string around for now */
+ GetStr(&url->infile, nextarg);
+ }
+ }
+ }
+ break;
+ case 'u':
+ /* user:password */
+ GetStr(&config->userpwd, nextarg);
+ cleanarg(nextarg);
+ break;
+ case 'U':
+ /* Proxy user:password */
+ GetStr(&config->proxyuserpwd, nextarg);
+ cleanarg(nextarg);
+ break;
+ case 'v':
+ if(toggle) {
+ /* the '%' thing here will cause the trace get sent to stderr */
+ Curl_safefree(global->trace_dump);
+ global->trace_dump = strdup("%");
+ if(!global->trace_dump)
+ return PARAM_NO_MEM;
+ if(global->tracetype && (global->tracetype != TRACE_PLAIN))
+ warnf(config,
+ "-v, --verbose overrides an earlier trace/verbose option\n");
+ global->tracetype = TRACE_PLAIN;
+ }
+ else
+ /* verbose is disabled here */
+ global->tracetype = TRACE_NONE;
+ break;
+ case 'V':
+ if(toggle) /* --no-version yields no output! */
+ return PARAM_VERSION_INFO_REQUESTED;
+ break;
+
+ case 'w':
+ /* get the output string */
+ if('@' == *nextarg) {
+ /* the data begins with a '@' letter, it means that a file name
+ or - (stdin) follows */
+ FILE *file;
+ const char *fname;
+ nextarg++; /* pass the @ */
+ if(curlx_strequal("-", nextarg)) {
+ fname = "<stdin>";
+ file = stdin;
+ }
+ else {
+ fname = nextarg;
+ file = fopen(nextarg, "r");
+ }
+ err = file2string(&config->writeout, file);
+ if(file && (file != stdin))
+ fclose(file);
+ if(err)
+ return err;
+ if(!config->writeout)
+ warnf(config, "Failed to read %s", fname);
+ }
+ else
+ GetStr(&config->writeout, nextarg);
+ break;
+ case 'x':
+ /* proxy */
+ GetStr(&config->proxy, nextarg);
+ config->proxyver = CURLPROXY_HTTP;
+ break;
+ case 'X':
+ /* set custom request */
+ GetStr(&config->customrequest, nextarg);
+ break;
+ case 'y':
+ /* low speed time */
+ err = str2unum(&config->low_speed_time, nextarg);
+ if(err)
+ return err;
+ if(!config->low_speed_limit)
+ config->low_speed_limit = 1;
+ break;
+ case 'Y':
+ /* low speed limit */
+ err = str2unum(&config->low_speed_limit, nextarg);
+ if(err)
+ return err;
+ if(!config->low_speed_time)
+ config->low_speed_time = 30;
+ break;
+ case 'z': /* time condition coming up */
+ switch(*nextarg) {
+ case '+':
+ nextarg++;
+ default:
+ /* If-Modified-Since: (section 14.28 in RFC2068) */
+ config->timecond = CURL_TIMECOND_IFMODSINCE;
+ break;
+ case '-':
+ /* If-Unmodified-Since: (section 14.24 in RFC2068) */
+ config->timecond = CURL_TIMECOND_IFUNMODSINCE;
+ nextarg++;
+ break;
+ case '=':
+ /* Last-Modified: (section 14.29 in RFC2068) */
+ config->timecond = CURL_TIMECOND_LASTMOD;
+ nextarg++;
+ break;
+ }
+ now = time(NULL);
+ config->condtime=curl_getdate(nextarg, &now);
+ if(-1 == (int)config->condtime) {
+ /* now let's see if it is a file name to get the time from instead! */
+ struct_stat statbuf;
+ if(-1 == stat(nextarg, &statbuf)) {
+ /* failed, remove time condition */
+ config->timecond = CURL_TIMECOND_NONE;
+ warnf(config,
+ "Illegal date format for -z, --timecond (and not "
+ "a file name). Disabling time condition. "
+ "See curl_getdate(3) for valid date syntax.\n");
+ }
+ else {
+ /* pull the time out from the file */
+ config->condtime = statbuf.st_mtime;
+ }
+ }
+ break;
+ default: /* unknown flag */
+ return PARAM_OPTION_UNKNOWN;
+ }
+ hit = -1;
+
+ } while(!longopt && !singleopt && *++parse && !*usedarg);
+
+ return PARAM_OK;
+}
+
+ParameterError parse_args(struct GlobalConfig *config, int argc,
+ argv_item_t argv[])
+{
+ int i;
+ bool stillflags;
+ char *orig_opt = NULL;
+ ParameterError result = PARAM_OK;
+ struct OperationConfig *operation = config->first;
+
+ for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
+ orig_opt = argv[i];
+
+ if(stillflags && ('-' == argv[i][0])) {
+ char *nextarg;
+ bool passarg;
+ char *flag = argv[i];
+
+ if(curlx_strequal("--", argv[i]))
+ /* This indicates the end of the flags and thus enables the
+ following (URL) argument to start with -. */
+ stillflags = FALSE;
+ else {
+ nextarg = (i < (argc - 1)) ? argv[i + 1] : NULL;
+
+ result = getparameter(flag, nextarg, &passarg, config, operation);
+ if(result == PARAM_NEXT_OPERATION) {
+ /* Reset result as PARAM_NEXT_OPERATION is only used here and not
+ returned from this function */
+ result = PARAM_OK;
+
+ if(operation->url_list && operation->url_list->url) {
+ /* Allocate the next config */
+ operation->next = malloc(sizeof(struct OperationConfig));
+ if(operation->next) {
+ /* Initialise the newly created config */
+ config_init(operation->next);
+
+ /* Copy the easy handle */
+ operation->next->easy = config->easy;
+
+ /* Set the global config pointer */
+ operation->next->global = config;
+
+ /* Update the last operation pointer */
+ config->last = operation->next;
+
+ /* Move onto the new config */
+ operation->next->prev = operation;
+ operation = operation->next;
+ }
+ else
+ result = PARAM_NO_MEM;
+ }
+ }
+ else if(!result && passarg)
+ i++; /* we're supposed to skip this */
+ }
+ }
+ else {
+ bool used;
+
+ /* Just add the URL please */
+ result = getparameter((char *)"--url", argv[i], &used, config,
+ operation);
+ }
+ }
+
+ if(result && result != PARAM_HELP_REQUESTED &&
+ result != PARAM_MANUAL_REQUESTED &&
+ result != PARAM_VERSION_INFO_REQUESTED &&
+ result != PARAM_ENGINES_REQUESTED) {
+ const char *reason = param2text(result);
+
+ if(orig_opt && !curlx_strequal(":", orig_opt))
+ helpf(config->errors, "option %s: %s\n", orig_opt, reason);
+ else
+ helpf(config->errors, "%s\n", reason);
+ }
+
+ return result;
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_getparam.h b/external/libcurl_android/jni/libcurl/src/tool_getparam.h
new file mode 100755
index 00000000..ef4366b7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_getparam.h
@@ -0,0 +1,62 @@
+#ifndef HEADER_CURL_TOOL_GETPARAM_H
+#define HEADER_CURL_TOOL_GETPARAM_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+typedef enum {
+ PARAM_OK = 0,
+ PARAM_OPTION_AMBIGUOUS,
+ PARAM_OPTION_UNKNOWN,
+ PARAM_REQUIRES_PARAMETER,
+ PARAM_BAD_USE,
+ PARAM_HELP_REQUESTED,
+ PARAM_MANUAL_REQUESTED,
+ PARAM_VERSION_INFO_REQUESTED,
+ PARAM_ENGINES_REQUESTED,
+ PARAM_GOT_EXTRA_PARAMETER,
+ PARAM_BAD_NUMERIC,
+ PARAM_NEGATIVE_NUMERIC,
+ PARAM_LIBCURL_DOESNT_SUPPORT,
+ PARAM_NO_MEM,
+ PARAM_NEXT_OPERATION,
+ PARAM_LAST
+} ParameterError;
+
+struct GlobalConfig;
+struct OperationConfig;
+
+ParameterError getparameter(char *flag, char *nextarg, bool *usedarg,
+ struct GlobalConfig *global,
+ struct OperationConfig *operation);
+
+#ifdef UNITTESTS
+void parse_cert_parameter(const char *cert_parameter,
+ char **certname,
+ char **passphrase);
+#endif
+
+ParameterError parse_args(struct GlobalConfig *config, int argc,
+ argv_item_t argv[]);
+
+#endif /* HEADER_CURL_TOOL_GETPARAM_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_getpass.c b/external/libcurl_android/jni/libcurl/src/tool_getpass.c
new file mode 100755
index 00000000..4c8dcb9f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_getpass.c
@@ -0,0 +1,256 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef HAVE_GETPASS_R
+/* this file is only for systems without getpass_r() */
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#elif defined(HAVE_TERMIO_H)
+# include <termio.h>
+#endif
+
+#ifdef __VMS
+# include descrip
+# include starlet
+# include iodef
+#endif
+
+#ifdef WIN32
+# include <conio.h>
+#endif
+
+#ifdef NETWARE
+# ifdef __NOVELL_LIBC__
+# include <screen.h>
+# else
+# include <nwconio.h>
+# endif
+#endif
+
+#define _MPRINTF_REPLACE
+#include <curl/mprintf.h>
+
+#include "tool_getpass.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef __VMS
+/* VMS implementation */
+char *getpass_r(const char *prompt, char *buffer, size_t buflen)
+{
+ long sts;
+ short chan;
+
+ /* MSK, 23-JAN-2004, iosbdef.h wasn't in VAX V7.2 or CC 6.4 */
+ /* distribution so I created this. May revert back later to */
+ /* struct _iosb iosb; */
+ struct _iosb
+ {
+ short int iosb$w_status; /* status */
+ short int iosb$w_bcnt; /* byte count */
+ int unused; /* unused */
+ } iosb;
+
+ $DESCRIPTOR(ttdesc, "TT");
+
+ buffer[0] = '\0';
+ sts = sys$assign(&ttdesc, &chan, 0, 0);
+ if(sts & 1) {
+ sts = sys$qiow(0, chan,
+ IO$_READPROMPT | IO$M_NOECHO,
+ &iosb, 0, 0, buffer, buflen, 0, 0,
+ prompt, strlen(prompt));
+
+ if((sts & 1) && (iosb.iosb$w_status & 1))
+ buffer[iosb.iosb$w_bcnt] = '\0';
+
+ sts = sys$dassgn(chan);
+ }
+ return buffer; /* we always return success */
+}
+#define DONE
+#endif /* __VMS */
+
+#ifdef __SYMBIAN32__
+# define getch() getchar()
+#endif
+
+#if defined(WIN32) || defined(__SYMBIAN32__)
+
+char *getpass_r(const char *prompt, char *buffer, size_t buflen)
+{
+ size_t i;
+ fputs(prompt, stderr);
+
+ for(i = 0; i < buflen; i++) {
+ buffer[i] = (char)getch();
+ if(buffer[i] == '\r' || buffer[i] == '\n') {
+ buffer[i] = '\0';
+ break;
+ }
+ else
+ if(buffer[i] == '\b')
+ /* remove this letter and if this is not the first key, remove the
+ previous one as well */
+ i = i - (i >= 1 ? 2 : 1);
+ }
+#ifndef __SYMBIAN32__
+ /* since echo is disabled, print a newline */
+ fputs("\n", stderr);
+#endif
+ /* if user didn't hit ENTER, terminate buffer */
+ if(i == buflen)
+ buffer[buflen-1] = '\0';
+
+ return buffer; /* we always return success */
+}
+#define DONE
+#endif /* WIN32 || __SYMBIAN32__ */
+
+#ifdef NETWARE
+/* NetWare implementation */
+#ifdef __NOVELL_LIBC__
+char *getpass_r(const char *prompt, char *buffer, size_t buflen)
+{
+ return getpassword(prompt, buffer, buflen);
+}
+#else
+char *getpass_r(const char *prompt, char *buffer, size_t buflen)
+{
+ size_t i = 0;
+
+ printf("%s", prompt);
+ do {
+ buffer[i++] = getch();
+ if(buffer[i-1] == '\b') {
+ /* remove this letter and if this is not the first key,
+ remove the previous one as well */
+ if(i > 1) {
+ printf("\b \b");
+ i = i - 2;
+ }
+ else {
+ RingTheBell();
+ i = i - 1;
+ }
+ }
+ else if(buffer[i-1] != 13)
+ putchar('*');
+
+ } while((buffer[i-1] != 13) && (i < buflen));
+ buffer[i-1] = '\0';
+ printf("\r\n");
+ return buffer;
+}
+#endif /* __NOVELL_LIBC__ */
+#define DONE
+#endif /* NETWARE */
+
+#ifndef DONE /* not previously provided */
+
+#ifdef HAVE_TERMIOS_H
+# define struct_term struct termios
+#elif defined(HAVE_TERMIO_H)
+# define struct_term struct termio
+#else
+# undef struct_term
+#endif
+
+static bool ttyecho(bool enable, int fd)
+{
+#ifdef struct_term
+ static struct_term withecho;
+ static struct_term noecho;
+#endif
+ if(!enable) {
+ /* disable echo by extracting the current 'withecho' mode and remove the
+ ECHO bit and set back the struct */
+#ifdef HAVE_TERMIOS_H
+ tcgetattr(fd, &withecho);
+ noecho = withecho;
+ noecho.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSANOW, &noecho);
+#elif defined(HAVE_TERMIO_H)
+ ioctl(fd, TCGETA, &withecho);
+ noecho = withecho;
+ noecho.c_lflag &= ~ECHO;
+ ioctl(fd, TCSETA, &noecho);
+#else
+ /* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we can't disable echo! */
+ (void)fd;
+ return FALSE; /* not disabled */
+#endif
+ return TRUE; /* disabled */
+ }
+ else {
+ /* re-enable echo, assumes we disabled it before (and set the structs we
+ now use to reset the terminal status) */
+#ifdef HAVE_TERMIOS_H
+ tcsetattr(fd, TCSAFLUSH, &withecho);
+#elif defined(HAVE_TERMIO_H)
+ ioctl(fd, TCSETA, &withecho);
+#else
+ return FALSE; /* not enabled */
+#endif
+ return TRUE; /* enabled */
+ }
+}
+
+char *getpass_r(const char *prompt, /* prompt to display */
+ char *password, /* buffer to store password in */
+ size_t buflen) /* size of buffer to store password in */
+{
+ ssize_t nread;
+ bool disabled;
+ int fd = open("/dev/tty", O_RDONLY);
+ if(-1 == fd)
+ fd = 1; /* use stdin if the tty couldn't be used */
+
+ disabled = ttyecho(FALSE, fd); /* disable terminal echo */
+
+ fputs(prompt, stderr);
+ nread = read(fd, password, buflen);
+ if(nread > 0)
+ password[--nread] = '\0'; /* zero terminate where enter is stored */
+ else
+ password[0] = '\0'; /* got nothing */
+
+ if(disabled) {
+ /* if echo actually was disabled, add a newline */
+ fputs("\n", stderr);
+ (void)ttyecho(TRUE, fd); /* enable echo */
+ }
+
+ if(1 != fd)
+ close(fd);
+
+ return password; /* return pointer to buffer */
+}
+
+#endif /* DONE */
+#endif /* HAVE_GETPASS_R */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_getpass.h b/external/libcurl_android/jni/libcurl/src/tool_getpass.h
new file mode 100755
index 00000000..d4fc7e23
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_getpass.h
@@ -0,0 +1,36 @@
+#ifndef HEADER_CURL_TOOL_GETPASS_H
+#define HEADER_CURL_TOOL_GETPASS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef HAVE_GETPASS_R
+/* If there's a system-provided function named like this, we trust it is
+ also found in one of the standard headers. */
+
+/*
+ * Returning NULL will abort the continued operation!
+ */
+char* getpass_r(const char *prompt, char* buffer, size_t buflen);
+#endif
+
+#endif /* HEADER_CURL_TOOL_GETPASS_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_help.c b/external/libcurl_android/jni/libcurl/src/tool_help.c
new file mode 100755
index 00000000..c255be0b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_help.c
@@ -0,0 +1,333 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_panykey.h"
+#include "tool_help.h"
+#include "tool_libinfo.h"
+#include "tool_version.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef MSDOS
+# define USE_WATT32
+#endif
+
+/*
+ * A few of these source lines are >80 columns wide, but that's only because
+ * breaking the strings narrower makes this chunk look even worse!
+ *
+ * Starting with 7.18.0, this list of command line options is sorted based
+ * on the long option name. It is not done automatically, although a command
+ * line like the following can help out:
+ *
+ * curl --help | cut -c5- | grep "^-" | sort
+ */
+
+static const char *const helptext[] = {
+ "Usage: curl [options...] <url>",
+ "Options: (H) means HTTP/HTTPS only, (F) means FTP only",
+ " --anyauth Pick \"any\" authentication method (H)",
+ " -a, --append Append to target file when uploading (F/SFTP)",
+ " --basic Use HTTP Basic Authentication (H)",
+ " --cacert FILE CA certificate to verify peer against (SSL)",
+ " --capath DIR CA directory to verify peer against (SSL)",
+ " -E, --cert CERT[:PASSWD] Client certificate file and password (SSL)",
+ " --cert-type TYPE Certificate file type (DER/PEM/ENG) (SSL)",
+ " --ciphers LIST SSL ciphers to use (SSL)",
+ " --compressed Request compressed response (using deflate or gzip)",
+ " -K, --config FILE Read config from FILE",
+ " --connect-timeout SECONDS Maximum time allowed for connection",
+ " -C, --continue-at OFFSET Resumed transfer OFFSET",
+ " -b, --cookie STRING/FILE Read cookies from STRING/FILE (H)",
+ " -c, --cookie-jar FILE Write cookies to FILE after operation (H)",
+ " --create-dirs Create necessary local directory hierarchy",
+ " --crlf Convert LF to CRLF in upload",
+ " --crlfile FILE Get a CRL list in PEM format from the given file",
+ " -d, --data DATA HTTP POST data (H)",
+ " --data-ascii DATA HTTP POST ASCII data (H)",
+ " --data-binary DATA HTTP POST binary data (H)",
+ " --data-urlencode DATA HTTP POST data url encoded (H)",
+ " --delegation STRING GSS-API delegation permission",
+ " --digest Use HTTP Digest Authentication (H)",
+ " --disable-eprt Inhibit using EPRT or LPRT (F)",
+ " --disable-epsv Inhibit using EPSV (F)",
+ " --dns-servers DNS server addrs to use: 1.1.1.1;2.2.2.2",
+ " --dns-interface Interface to use for DNS requests",
+ " --dns-ipv4-addr IPv4 address to use for DNS requests, dot notation",
+ " --dns-ipv6-addr IPv6 address to use for DNS requests, dot notation",
+ " -D, --dump-header FILE Write the headers to FILE",
+ " --egd-file FILE EGD socket path for random data (SSL)",
+ " --engine ENGINE Crypto engine (use \"--engine list\" for list) (SSL)",
+#ifdef USE_ENVIRONMENT
+ " --environment Write results to environment variables (RISC OS)",
+#endif
+ " -f, --fail Fail silently (no output at all) on HTTP errors (H)",
+ " -F, --form CONTENT Specify HTTP multipart POST data (H)",
+ " --form-string STRING Specify HTTP multipart POST data (H)",
+ " --ftp-account DATA Account data string (F)",
+ " --ftp-alternative-to-user COMMAND "
+ "String to replace \"USER [name]\" (F)",
+ " --ftp-create-dirs Create the remote dirs if not present (F)",
+ " --ftp-method [MULTICWD/NOCWD/SINGLECWD] Control CWD usage (F)",
+ " --ftp-pasv Use PASV/EPSV instead of PORT (F)",
+ " -P, --ftp-port ADR Use PORT with given address instead of PASV (F)",
+ " --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
+ " --ftp-pret Send PRET before PASV (for drftpd) (F)",
+ " --ftp-ssl-ccc Send CCC after authenticating (F)",
+ " --ftp-ssl-ccc-mode ACTIVE/PASSIVE Set CCC mode (F)",
+ " --ftp-ssl-control Require SSL/TLS for FTP login, "
+ "clear for transfer (F)",
+ " -G, --get Send the -d data with a HTTP GET (H)",
+ " -g, --globoff Disable URL sequences and ranges using {} and []",
+ " -H, --header LINE Pass custom header LINE to server (H)",
+ " -I, --head Show document info only",
+ " -h, --help This help text",
+ " --hostpubmd5 MD5 "
+ "Hex-encoded MD5 string of the host public key. (SSH)",
+ " -0, --http1.0 Use HTTP 1.0 (H)",
+ " --http1.1 Use HTTP 1.1 (H)",
+ " --http2 Use HTTP 2 (H)",
+ " --ignore-content-length Ignore the HTTP Content-Length header",
+ " -i, --include Include protocol headers in the output (H/F)",
+ " -k, --insecure Allow connections to SSL sites without certs (H)",
+ " --interface INTERFACE Use network INTERFACE (or address)",
+ " -4, --ipv4 Resolve name to IPv4 address",
+ " -6, --ipv6 Resolve name to IPv6 address",
+ " -j, --junk-session-cookies Ignore session cookies read from file (H)",
+ " --keepalive-time SECONDS Wait SECONDS between keepalive probes",
+ " --key KEY Private key file name (SSL/SSH)",
+ " --key-type TYPE Private key file type (DER/PEM/ENG) (SSL)",
+ " --krb LEVEL Enable Kerberos with security LEVEL (F)",
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ " --libcurl FILE Dump libcurl equivalent code of this command line",
+#endif
+ " --limit-rate RATE Limit transfer speed to RATE",
+ " -l, --list-only List only mode (F/POP3)",
+ " --local-port RANGE Force use of RANGE for local port numbers",
+ " -L, --location Follow redirects (H)",
+ " --location-trusted "
+ "Like '--location', and send auth to other hosts (H)",
+ " --login-options OPTIONS Server login options (IMAP, POP3, SMTP)",
+ " -M, --manual Display the full manual",
+ " --mail-from FROM Mail from this address (SMTP)",
+ " --mail-rcpt TO Mail to this/these addresses (SMTP)",
+ " --mail-auth AUTH Originator address of the original email (SMTP)",
+ " --max-filesize BYTES Maximum file size to download (H/F)",
+ " --max-redirs NUM Maximum number of redirects allowed (H)",
+ " -m, --max-time SECONDS Maximum time allowed for the transfer",
+ " --metalink Process given URLs as metalink XML file",
+ " --negotiate Use HTTP Negotiate (SPNEGO) authentication (H)",
+ " -n, --netrc Must read .netrc for user name and password",
+ " --netrc-optional Use either .netrc or URL; overrides -n",
+ " --netrc-file FILE Specify FILE for netrc",
+ " -: --next "
+ "Allows the following URL to use a separate set of options",
+ " --no-alpn Disable the ALPN TLS extension (H)",
+ " -N, --no-buffer Disable buffering of the output stream",
+ " --no-keepalive Disable keepalive use on the connection",
+ " --no-npn Disable the NPN TLS extension (H)",
+ " --no-sessionid Disable SSL session-ID reusing (SSL)",
+ " --noproxy List of hosts which do not use proxy",
+ " --ntlm Use HTTP NTLM authentication (H)",
+ " --oauth2-bearer TOKEN OAuth 2 Bearer Token (IMAP, POP3, SMTP)",
+ " -o, --output FILE Write to FILE instead of stdout",
+ " --pass PASS Pass phrase for the private key (SSL/SSH)",
+ " --post301 "
+ "Do not switch to GET after following a 301 redirect (H)",
+ " --post302 "
+ "Do not switch to GET after following a 302 redirect (H)",
+ " --post303 "
+ "Do not switch to GET after following a 303 redirect (H)",
+ " -#, --progress-bar Display transfer progress as a progress bar",
+ " --proto PROTOCOLS Enable/disable PROTOCOLS",
+ " --proto-redir PROTOCOLS Enable/disable PROTOCOLS on redirect",
+ " -x, --proxy [PROTOCOL://]HOST[:PORT] Use proxy on given port",
+ " --proxy-anyauth Pick \"any\" proxy authentication method (H)",
+ " --proxy-basic Use Basic authentication on the proxy (H)",
+ " --proxy-digest Use Digest authentication on the proxy (H)",
+ " --proxy-negotiate "
+ "Use HTTP Negotiate (SPNEGO) authentication on the proxy (H)",
+ " --proxy-ntlm Use NTLM authentication on the proxy (H)",
+ " -U, --proxy-user USER[:PASSWORD] Proxy user and password",
+ " --proxy1.0 HOST[:PORT] Use HTTP/1.0 proxy on given port",
+ " -p, --proxytunnel Operate through a HTTP proxy tunnel (using CONNECT)",
+ " --pubkey KEY Public key file name (SSH)",
+ " -Q, --quote CMD Send command(s) to server before transfer (F/SFTP)",
+ " --random-file FILE File for reading random data from (SSL)",
+ " -r, --range RANGE Retrieve only the bytes within RANGE",
+ " --raw Do HTTP \"raw\"; no transfer decoding (H)",
+ " -e, --referer Referer URL (H)",
+ " -J, --remote-header-name Use the header-provided filename (H)",
+ " -O, --remote-name Write output to a file named as the remote file",
+ " --remote-name-all Use the remote file name for all URLs",
+ " -R, --remote-time Set the remote file's time on the local output",
+ " -X, --request COMMAND Specify request command to use",
+ " --resolve HOST:PORT:ADDRESS Force resolve of HOST:PORT to ADDRESS",
+ " --retry NUM "
+ "Retry request NUM times if transient problems occur",
+ " --retry-delay SECONDS Wait SECONDS between retries",
+ " --retry-max-time SECONDS Retry only within this period",
+ " --sasl-ir Enable initial response in SASL authentication",
+ " -S, --show-error "
+ "Show error. With -s, make curl show errors when they occur",
+ " -s, --silent Silent mode (don't output anything)",
+ " --socks4 HOST[:PORT] SOCKS4 proxy on given host + port",
+ " --socks4a HOST[:PORT] SOCKS4a proxy on given host + port",
+ " --socks5 HOST[:PORT] SOCKS5 proxy on given host + port",
+ " --socks5-hostname HOST[:PORT] "
+ "SOCKS5 proxy, pass host name to proxy",
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ " --socks5-gssapi-service NAME SOCKS5 proxy service name for GSS-API",
+ " --socks5-gssapi-nec Compatibility with NEC SOCKS5 server",
+#endif
+ " -Y, --speed-limit RATE "
+ "Stop transfers below RATE for 'speed-time' secs",
+ " -y, --speed-time SECONDS "
+ "Trigger 'speed-limit' abort after SECONDS (default: 30)",
+ " --ssl Try SSL/TLS (FTP, IMAP, POP3, SMTP)",
+ " --ssl-reqd Require SSL/TLS (FTP, IMAP, POP3, SMTP)",
+ " -2, --sslv2 Use SSLv2 (SSL)",
+ " -3, --sslv3 Use SSLv3 (SSL)",
+ " --ssl-allow-beast Allow security flaw to improve interop (SSL)",
+ " --stderr FILE Where to redirect stderr (use \"-\" for stdout)",
+ " --tcp-nodelay Use the TCP_NODELAY option",
+ " -t, --telnet-option OPT=VAL Set telnet option",
+ " --tftp-blksize VALUE Set TFTP BLKSIZE option (must be >512)",
+ " -z, --time-cond TIME Transfer based on a time condition",
+ " -1, --tlsv1 Use => TLSv1 (SSL)",
+ " --tlsv1.0 Use TLSv1.0 (SSL)",
+ " --tlsv1.1 Use TLSv1.1 (SSL)",
+ " --tlsv1.2 Use TLSv1.2 (SSL)",
+ " --trace FILE Write a debug trace to FILE",
+ " --trace-ascii FILE Like --trace, but without hex output",
+ " --trace-time Add time stamps to trace/verbose output",
+ " --tr-encoding Request compressed transfer encoding (H)",
+ " -T, --upload-file FILE Transfer FILE to destination",
+ " --url URL URL to work with",
+ " -B, --use-ascii Use ASCII/text transfer",
+ " -u, --user USER[:PASSWORD] Server user and password",
+ " --tlsuser USER TLS username",
+ " --tlspassword STRING TLS password",
+ " --tlsauthtype STRING TLS authentication type (default: SRP)",
+ " -A, --user-agent STRING Send User-Agent STRING to server (H)",
+ " -v, --verbose Make the operation more talkative",
+ " -V, --version Show version number and quit",
+#ifdef USE_WATT32
+ " --wdebug Turn on Watt-32 debugging",
+#endif
+ " -w, --write-out FORMAT Use output FORMAT after completion",
+ " --xattr Store metadata in extended file attributes",
+ " -q Disable .curlrc (must be first parameter)",
+ NULL
+};
+
+#ifdef NETWARE
+# define PRINT_LINES_PAUSE 23
+#endif
+
+#ifdef __SYMBIAN32__
+# define PRINT_LINES_PAUSE 16
+#endif
+
+struct feat {
+ const char *name;
+ int bitmask;
+};
+
+static const struct feat feats[] = {
+ {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
+ {"Debug", CURL_VERSION_DEBUG},
+ {"TrackMemory", CURL_VERSION_CURLDEBUG},
+ {"IDN", CURL_VERSION_IDN},
+ {"IPv6", CURL_VERSION_IPV6},
+ {"Largefile", CURL_VERSION_LARGEFILE},
+ {"SSPI", CURL_VERSION_SSPI},
+ {"GSS-API", CURL_VERSION_GSSAPI},
+ {"SPNEGO", CURL_VERSION_SPNEGO},
+ {"NTLM", CURL_VERSION_NTLM},
+ {"NTLM_WB", CURL_VERSION_NTLM_WB},
+ {"SSL", CURL_VERSION_SSL},
+ {"krb4", CURL_VERSION_KERBEROS4},
+ {"libz", CURL_VERSION_LIBZ},
+ {"CharConv", CURL_VERSION_CONV},
+ {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
+ {"HTTP2", CURL_VERSION_HTTP2}
+};
+
+void tool_help(void)
+{
+ int i;
+ for(i = 0; helptext[i]; i++) {
+ puts(helptext[i]);
+#ifdef PRINT_LINES_PAUSE
+ if(i && ((i % PRINT_LINES_PAUSE) == 0))
+ tool_pressanykey();
+#endif
+ }
+}
+
+void tool_version_info(void)
+{
+ const char *const *proto;
+
+ printf(CURL_ID "%s\n", curl_version());
+ if(curlinfo->protocols) {
+ printf("Protocols: ");
+ for(proto = curlinfo->protocols; *proto; ++proto) {
+ printf("%s ", *proto);
+ }
+ puts(""); /* newline */
+ }
+ if(curlinfo->features) {
+ unsigned int i;
+ printf("Features: ");
+ for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
+ if(curlinfo->features & feats[i].bitmask)
+ printf("%s ", feats[i].name);
+ }
+#ifdef USE_METALINK
+ printf("Metalink ");
+#endif
+ puts(""); /* newline */
+ }
+}
+
+void tool_list_engines(CURL *curl)
+{
+ struct curl_slist *engines = NULL;
+
+ /* Get the list of engines */
+ curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
+
+ puts("Build-time engines:");
+ if(engines) {
+ for(; engines; engines = engines->next)
+ printf(" %s\n", engines->data);
+ }
+ else {
+ puts(" <none>");
+ }
+
+ /* Cleanup the list of engines */
+ curl_slist_free_all(engines);
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_help.h b/external/libcurl_android/jni/libcurl/src/tool_help.h
new file mode 100755
index 00000000..9ef50069
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_help.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_TOOL_HELP_H
+#define HEADER_CURL_TOOL_HELP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void tool_help(void);
+void tool_list_engines(CURL *curl);
+void tool_version_info(void);
+
+#endif /* HEADER_CURL_TOOL_HELP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_helpers.c b/external/libcurl_android/jni/libcurl/src/tool_helpers.c
new file mode 100755
index 00000000..dbf32f8b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_helpers.c
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/*
+** Helper functions that are used from more tha one source file.
+*/
+
+const char *param2text(int res)
+{
+ ParameterError error = (ParameterError)res;
+ switch(error) {
+ case PARAM_GOT_EXTRA_PARAMETER:
+ return "had unsupported trailing garbage";
+ case PARAM_OPTION_UNKNOWN:
+ return "is unknown";
+ case PARAM_OPTION_AMBIGUOUS:
+ return "is ambiguous";
+ case PARAM_REQUIRES_PARAMETER:
+ return "requires parameter";
+ case PARAM_BAD_USE:
+ return "is badly used here";
+ case PARAM_BAD_NUMERIC:
+ return "expected a proper numerical parameter";
+ case PARAM_NEGATIVE_NUMERIC:
+ return "expected a positive numerical parameter";
+ case PARAM_LIBCURL_DOESNT_SUPPORT:
+ return "the installed libcurl version doesn't support this";
+ case PARAM_NO_MEM:
+ return "out of memory";
+ default:
+ return "unknown error";
+ }
+}
+
+int SetHTTPrequest(struct OperationConfig *config, HttpReq req, HttpReq *store)
+{
+ if((*store == HTTPREQ_UNSPEC) ||
+ (*store == req)) {
+ *store = req;
+ return 0;
+ }
+ warnf(config, "You can only select one HTTP request!\n");
+ return 1;
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_helpers.h b/external/libcurl_android/jni/libcurl/src/tool_helpers.h
new file mode 100755
index 00000000..73bcfc77
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_helpers.h
@@ -0,0 +1,32 @@
+#ifndef HEADER_CURL_TOOL_HELPERS_H
+#define HEADER_CURL_TOOL_HELPERS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+const char *param2text(int res);
+
+int SetHTTPrequest(struct OperationConfig *config, HttpReq req,
+ HttpReq *store);
+
+#endif /* HEADER_CURL_TOOL_HELPERS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_homedir.c b/external/libcurl_android/jni/libcurl/src/tool_homedir.c
new file mode 100755
index 00000000..11bb4ef3
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_homedir.c
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+#include "tool_homedir.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+static char *GetEnv(const char *variable, char do_expand)
+{
+ char *env = NULL;
+#ifdef WIN32
+ char buf1[1024], buf2[1024];
+ DWORD rc;
+
+ /* Don't use getenv(); it doesn't find variable added after program was
+ * started. Don't accept truncated results (i.e. rc >= sizeof(buf1)). */
+
+ rc = GetEnvironmentVariable(variable, buf1, sizeof(buf1));
+ if(rc > 0 && rc < sizeof(buf1)) {
+ env = buf1;
+ variable = buf1;
+ }
+ if(do_expand && strchr(variable,'%')) {
+ /* buf2 == variable if not expanded */
+ rc = ExpandEnvironmentStrings (variable, buf2, sizeof(buf2));
+ if(rc > 0 && rc < sizeof(buf2) &&
+ !strchr(buf2,'%')) /* no vars still unexpanded */
+ env = buf2;
+ }
+#else
+ (void)do_expand;
+ /* no length control */
+ env = getenv(variable);
+#endif
+ return (env && env[0]) ? strdup(env) : NULL;
+}
+
+/* return the home directory of the current user as an allocated string */
+char *homedir(void)
+{
+ char *home;
+
+ home = GetEnv("CURL_HOME", FALSE);
+ if(home)
+ return home;
+
+ home = GetEnv("HOME", FALSE);
+ if(home)
+ return home;
+
+#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
+ {
+ struct passwd *pw = getpwuid(geteuid());
+
+ if(pw) {
+ home = pw->pw_dir;
+ if(home && home[0])
+ home = strdup(home);
+ else
+ home = NULL;
+ }
+ }
+#endif /* PWD-stuff */
+#ifdef WIN32
+ home = GetEnv("APPDATA", TRUE);
+ if(!home)
+ home = GetEnv("%USERPROFILE%\\Application Data", TRUE); /* Normally only
+ on Win-2K/XP */
+#endif /* WIN32 */
+ return home;
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_homedir.h b/external/libcurl_android/jni/libcurl/src/tool_homedir.h
new file mode 100755
index 00000000..d5886155
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_homedir.h
@@ -0,0 +1,28 @@
+#ifndef HEADER_CURL_TOOL_HOMEDIR_H
+#define HEADER_CURL_TOOL_HOMEDIR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+char *homedir(void);
+
+#endif /* HEADER_CURL_TOOL_HOMEDIR_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_hugehelp.c b/external/libcurl_android/jni/libcurl/src/tool_hugehelp.c
new file mode 100755
index 00000000..eb6149d4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_hugehelp.c
@@ -0,0 +1,8299 @@
+#include "tool_setup.h"
+#ifndef HAVE_LIBZ
+/*
+ * NEVER EVER edit this manually, fix the mkhelp.pl script instead!
+ * Generation time: Wed Sep 10 00:40:56 2014
+ */
+#ifdef USE_MANUAL
+#include "tool_hugehelp.h"
+void hugehelp(void)
+{
+ fputs(
+" _ _ ____ _\n"
+" Project ___| | | | _ \\| |\n"
+" / __| | | | |_) | |\n"
+" | (__| |_| | _ <| |___\n"
+" \\___|\\___/|_| \\_\\_____|\n"
+"\n"
+"NAME\n"
+" curl - transfer a URL\n"
+"\n"
+"SYNOPSIS\n"
+" curl [options] [URL...]\n"
+"\n"
+"DESCRIPTION\n"
+" curl is a tool to transfer data from or to a server, using one of the\n"
+" supported protocols (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP,\n"
+, stdout);
+ fputs(
+" IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS,\n"
+" TELNET and TFTP). The command is designed to work without user inter-\n"
+" action.\n"
+"\n"
+" curl offers a busload of useful tricks like proxy support, user authen-\n"
+" tication, FTP upload, HTTP post, SSL connections, cookies, file trans-\n"
+" fer resume, Metalink, and more. As you will see below, the number of\n"
+" features will make your head spin!\n"
+"\n"
+, stdout);
+ fputs(
+" curl is powered by libcurl for all transfer-related features. See\n"
+" libcurl(3) for details.\n"
+"\n"
+"URL\n"
+" The URL syntax is protocol-dependent. You'll find a detailed descrip-\n"
+" tion in RFC 3986.\n"
+"\n"
+" You can specify multiple URLs or parts of URLs by writing part sets\n"
+" within braces as in:\n"
+"\n"
+" http://site.{one,two,three}.com\n"
+"\n"
+" or you can get sequences of alphanumeric series by using [] as in:\n"
+"\n"
+" ftp://ftp.numericals.com/file[1-100].txt\n"
+, stdout);
+ fputs(
+" ftp://ftp.numericals.com/file[001-100].txt (with leading zeros)\n"
+" ftp://ftp.letters.com/file[a-z].txt\n"
+"\n"
+" Nested sequences are not supported, but you can use several ones next\n"
+" to each other:\n"
+"\n"
+" http://any.org/archive[1996-1999]/vol[1-4]/part{a,b,c}.html\n"
+"\n"
+" You can specify any amount of URLs on the command line. They will be\n"
+" fetched in a sequential manner in the specified order.\n"
+"\n"
+, stdout);
+ fputs(
+" You can specify a step counter for the ranges to get every Nth number\n"
+" or letter:\n"
+"\n"
+" http://www.numericals.com/file[1-100:10].txt\n"
+" http://www.letters.com/file[a-z:2].txt\n"
+"\n"
+" If you specify URL without protocol:// prefix, curl will attempt to\n"
+" guess what protocol you might want. It will then default to HTTP but\n"
+" try other protocols based on often-used host name prefixes. For exam-\n"
+, stdout);
+ fputs(
+" ple, for host names starting with \"ftp.\" curl will assume you want to\n"
+" speak FTP.\n"
+"\n"
+" curl will do its best to use what you pass to it as a URL. It is not\n"
+" trying to validate it as a syntactically correct URL by any means but\n"
+" is instead very liberal with what it accepts.\n"
+"\n"
+" curl will attempt to re-use connections for multiple file transfers, so\n"
+" that getting many files from the same server will not do multiple con-\n"
+, stdout);
+ fputs(
+" nects / handshakes. This improves speed. Of course this is only done on\n"
+" files specified on a single command line and cannot be used between\n"
+" separate curl invokes.\n"
+"\n"
+"PROGRESS METER\n"
+" curl normally displays a progress meter during operations, indicating\n"
+" the amount of transferred data, transfer speeds and estimated time\n"
+" left, etc.\n"
+"\n"
+" curl displays this data to the terminal by default, so if you invoke\n"
+, stdout);
+ fputs(
+" curl to do an operation and it is about to write data to the terminal,\n"
+" it disables the progress meter as otherwise it would mess up the output\n"
+" mixing progress meter and response data.\n"
+"\n"
+" If you want a progress meter for HTTP POST or PUT requests, you need to\n"
+" redirect the response output to a file, using shell redirect (>), -o\n"
+" [file] or similar.\n"
+"\n"
+" It is not the same case for FTP upload as that operation does not spit\n"
+, stdout);
+ fputs(
+" out any response data to the terminal.\n"
+"\n"
+" If you prefer a progress \"bar\" instead of the regular meter, -# is your\n"
+" friend.\n"
+"OPTIONS\n"
+" Options start with one or two dashes. Many of the options require an\n"
+" additional value next to them.\n"
+"\n"
+" The short \"single-dash\" form of the options, -d for example, may be\n"
+" used with or without a space between it and its value, although a space\n"
+, stdout);
+ fputs(
+" is a recommended separator. The long \"double-dash\" form, --data for\n"
+" example, requires a space between it and its value.\n"
+"\n"
+" Short version options that don't need any additional values can be used\n"
+" immediately next to each other, like for example you can specify all\n"
+" the options -O, -L and -v at once as -OLv.\n"
+"\n"
+" In general, all boolean options are enabled with --option and yet again\n"
+, stdout);
+ fputs(
+" disabled with --no-option. That is, you use the exact same option name\n"
+" but prefix it with \"no-\". However, in this list we mostly only list and\n"
+" show the --option version of them. (This concept with --no options was\n"
+" added in 7.19.0. Previously most options were toggled on/off on\n"
+" repeated use of the same command line option.)\n"
+"\n"
+" -#, --progress-bar\n"
+" Make curl display progress as a simple progress bar instead of\n"
+, stdout);
+ fputs(
+" the standard, more informational, meter.\n"
+"\n"
+" -:, --next\n"
+" Tells curl to use a separate operation for the following URL and\n"
+" associated options. This allows you to send several URL\n"
+" requests, each with their own specific options, for example,\n"
+" such as different user names or custom requests for each. (Added\n"
+" in 7.36.0)\n"
+"\n"
+" -0, --http1.0\n"
+, stdout);
+ fputs(
+" (HTTP) Tells curl to use HTTP version 1.0 instead of using its\n"
+" internally preferred: HTTP 1.1.\n"
+"\n"
+" --http1.1\n"
+" (HTTP) Tells curl to use HTTP version 1.1. This is the internal\n"
+" default version. (Added in 7.33.0)\n"
+"\n"
+" --http2\n"
+" (HTTP) Tells curl to issue its requests using HTTP 2. This\n"
+" requires that the underlying libcurl was built to support it.\n"
+" (Added in 7.33.0)\n"
+"\n"
+" --no-npn\n"
+, stdout);
+ fputs(
+" Disable the NPN TLS extension. NPN is enabled by default if\n"
+" libcurl was built with an SSL library that supports NPN. NPN is\n"
+" used by a libcurl that supports HTTP 2 to negotiate HTTP 2 sup-\n"
+" port with the server during https sessions.\n"
+"\n"
+" (Added in 7.36.0)\n"
+"\n"
+" --no-alpn\n"
+" Disable the ALPN TLS extension. ALPN is enabled by default if\n"
+, stdout);
+ fputs(
+" libcurl was built with an SSL library that supports ALPN. ALPN\n"
+" is used by a libcurl that supports HTTP 2 to negotiate HTTP 2\n"
+" support with the server during https sessions.\n"
+"\n"
+" (Added in 7.36.0)\n"
+"\n"
+" -1, --tlsv1\n"
+" (SSL) Forces curl to use TLS version 1.x when negotiating with a\n"
+" remote TLS server. You can use options --tlsv1.0, --tlsv1.1,\n"
+, stdout);
+ fputs(
+" and --tlsv1.2 to control the TLS version more precisely (if the\n"
+" SSL backend in use supports such a level of control).\n"
+"\n"
+" -2, --sslv2\n"
+" (SSL) Forces curl to use SSL version 2 when negotiating with a\n"
+" remote SSL server.\n"
+"\n"
+" -3, --sslv3\n"
+" (SSL) Forces curl to use SSL version 3 when negotiating with a\n"
+" remote SSL server.\n"
+"\n"
+" -4, --ipv4\n"
+, stdout);
+ fputs(
+" If curl is capable of resolving an address to multiple IP ver-\n"
+" sions (which it is if it is IPv6-capable), this option tells\n"
+" curl to resolve names to IPv4 addresses only.\n"
+"\n"
+" -6, --ipv6\n"
+" If curl is capable of resolving an address to multiple IP ver-\n"
+" sions (which it is if it is IPv6-capable), this option tells\n"
+" curl to resolve names to IPv6 addresses only.\n"
+"\n"
+" -a, --append\n"
+, stdout);
+ fputs(
+" (FTP/SFTP) When used in an upload, this will tell curl to append\n"
+" to the target file instead of overwriting it. If the file\n"
+" doesn't exist, it will be created. Note that this flag is\n"
+" ignored by some SSH servers (including OpenSSH).\n"
+"\n"
+" -A, --user-agent <agent string>\n"
+" (HTTP) Specify the User-Agent string to send to the HTTP server.\n"
+" Some badly done CGIs fail if this field isn't set to\n"
+, stdout);
+ fputs(
+" \"Mozilla/4.0\". To encode blanks in the string, surround the\n"
+" string with single quote marks. This can also be set with the\n"
+" -H, --header option of course.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --anyauth\n"
+" (HTTP) Tells curl to figure out authentication method by itself,\n"
+" and use the most secure one the remote site claims to support.\n"
+, stdout);
+ fputs(
+" This is done by first doing a request and checking the response-\n"
+" headers, thus possibly inducing an extra network round-trip.\n"
+" This is used instead of setting a specific authentication\n"
+" method, which you can do with --basic, --digest, --ntlm, and\n"
+" --negotiate.\n"
+"\n"
+" Note that using --anyauth is not recommended if you do uploads\n"
+, stdout);
+ fputs(
+" from stdin, since it may require data to be sent twice and then\n"
+" the client must be able to rewind. If the need should arise when\n"
+" uploading from stdin, the upload operation will fail.\n"
+"\n"
+" -b, --cookie <name=data>\n"
+" (HTTP) Pass the data to the HTTP server as a cookie. It is sup-\n"
+" posedly the data previously received from the server in a \"Set-\n"
+" Cookie:\" line. The data should be in the format \"NAME1=VALUE1;\n"
+, stdout);
+ fputs(
+" NAME2=VALUE2\".\n"
+"\n"
+" If no '=' symbol is used in the line, it is treated as a file-\n"
+" name to use to read previously stored cookie lines from, which\n"
+" should be used in this session if they match. Using this method\n"
+" also activates the \"cookie parser\" which will make curl record\n"
+" incoming cookies too, which may be handy if you're using this in\n"
+, stdout);
+ fputs(
+" combination with the -L, --location option. The file format of\n"
+" the file to read cookies from should be plain HTTP headers or\n"
+" the Netscape/Mozilla cookie file format.\n"
+"\n"
+" NOTE that the file specified with -b, --cookie is only used as\n"
+" input. No cookies will be stored in the file. To store cookies,\n"
+" use the -c, --cookie-jar option or you could even save the HTTP\n"
+, stdout);
+ fputs(
+" headers to a file using -D, --dump-header!\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -B, --use-ascii\n"
+" (FTP/LDAP) Enable ASCII transfer. For FTP, this can also be\n"
+" enforced by using an URL that ends with \";type=A\". This option\n"
+" causes data sent to stdout to be in text mode for win32 systems.\n"
+"\n"
+" --basic\n"
+" (HTTP) Tells curl to use HTTP Basic authentication. This is the\n"
+, stdout);
+ fputs(
+" default and this option is usually pointless, unless you use it\n"
+" to override a previously set option that sets a different\n"
+" authentication method (such as --ntlm, --digest, or --negoti-\n"
+" ate).\n"
+"\n"
+" -c, --cookie-jar <file name>\n"
+" (HTTP) Specify to which file you want curl to write all cookies\n"
+" after a completed operation. Curl writes all cookies previously\n"
+, stdout);
+ fputs(
+" read from a specified file as well as all cookies received from\n"
+" remote server(s). If no cookies are known, no file will be writ-\n"
+" ten. The file will be written using the Netscape cookie file\n"
+" format. If you set the file name to a single dash, \"-\", the\n"
+" cookies will be written to stdout.\n"
+"\n"
+" This command line option will activate the cookie engine that\n"
+, stdout);
+ fputs(
+" makes curl record and use cookies. Another way to activate it is\n"
+" to use the -b, --cookie option.\n"
+"\n"
+" If the cookie jar can't be created or written to, the whole curl\n"
+" operation won't fail or even report an error clearly. Using -v\n"
+" will get a warning displayed, but that is the only visible feed-\n"
+" back you get about this possibly lethal situation.\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, the last specified file\n"
+" name will be used.\n"
+"\n"
+" -C, --continue-at <offset>\n"
+" Continue/Resume a previous file transfer at the given offset.\n"
+" The given offset is the exact number of bytes that will be\n"
+" skipped, counting from the beginning of the source file before\n"
+" it is transferred to the destination. If used with uploads, the\n"
+, stdout);
+ fputs(
+" FTP server command SIZE will not be used by curl.\n"
+"\n"
+" Use \"-C -\" to tell curl to automatically find out where/how to\n"
+" resume the transfer. It then uses the given output/input files\n"
+" to figure that out.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --ciphers <list of ciphers>\n"
+" (SSL) Specifies which ciphers to use in the connection. The list\n"
+, stdout);
+ fputs(
+" of ciphers must specify valid ciphers. Read up on SSL cipher\n"
+" list details on this URL:\n"
+" http://www.openssl.org/docs/apps/ciphers.html\n"
+"\n"
+" NSS ciphers are done differently than OpenSSL and GnuTLS. The\n"
+" full list of NSS ciphers is in the NSSCipherSuite entry at this\n"
+" URL: http://git.fedora-\n"
+, stdout);
+ fputs(
+" hosted.org/cgit/mod_nss.git/plain/docs/mod_nss.html#Directives\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --compressed\n"
+" (HTTP) Request a compressed response using one of the algorithms\n"
+" curl supports, and save the uncompressed document. If this\n"
+" option is used and the server sends an unsupported encoding,\n"
+" curl will report an error.\n"
+"\n"
+" --connect-timeout <seconds>\n"
+, stdout);
+ fputs(
+" Maximum time in seconds that you allow the connection to the\n"
+" server to take. This only limits the connection phase, once\n"
+" curl has connected this option is of no more use. Since 7.32.0,\n"
+" this option accepts decimal values, but the actual timeout will\n"
+" decrease in accuracy as the specified timeout increases in deci-\n"
+" mal precision. See also the -m, --max-time option.\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --create-dirs\n"
+" When used in conjunction with the -o option, curl will create\n"
+" the necessary local directory hierarchy as needed. This option\n"
+" creates the dirs mentioned with the -o option, nothing else. If\n"
+" the -o file name uses no dir or if the dirs it mentions already\n"
+" exist, no dir will be created.\n"
+"\n"
+, stdout);
+ fputs(
+" To create remote directories when using FTP or SFTP, try --ftp-\n"
+" create-dirs.\n"
+"\n"
+" --crlf (FTP) Convert LF to CRLF in upload. Useful for MVS (OS/390).\n"
+"\n"
+" --crlfile <file>\n"
+" (HTTPS/FTPS) Provide a file using PEM format with a Certificate\n"
+" Revocation List that may specify peer certificates that are to\n"
+" be considered revoked.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+, stdout);
+ fputs(
+" (Added in 7.19.7)\n"
+" -d, --data <data>\n"
+" (HTTP) Sends the specified data in a POST request to the HTTP\n"
+" server, in the same way that a browser does when a user has\n"
+" filled in an HTML form and presses the submit button. This will\n"
+" cause curl to pass the data to the server using the content-type\n"
+" application/x-www-form-urlencoded. Compare to -F, --form.\n"
+"\n"
+, stdout);
+ fputs(
+" -d, --data is the same as --data-ascii. To post data purely\n"
+" binary, you should instead use the --data-binary option. To URL-\n"
+" encode the value of a form field you may use --data-urlencode.\n"
+"\n"
+" If any of these options is used more than once on the same com-\n"
+" mand line, the data pieces specified will be merged together\n"
+" with a separating &-symbol. Thus, using '-d name=daniel -d\n"
+, stdout);
+ fputs(
+" skill=lousy' would generate a post chunk that looks like\n"
+" 'name=daniel&skill=lousy'.\n"
+"\n"
+" If you start the data with the letter @, the rest should be a\n"
+" file name to read the data from, or - if you want curl to read\n"
+" the data from stdin. Multiple files can also be specified. Post-\n"
+" ing data from a file named 'foobar' would thus be done with\n"
+, stdout);
+ fputs(
+" --data @foobar. When --data is told to read from a file like\n"
+" that, carriage returns and newlines will be stripped out.\n"
+"\n"
+" -D, --dump-header <file>\n"
+" Write the protocol headers to the specified file.\n"
+"\n"
+" This option is handy to use when you want to store the headers\n"
+" that an HTTP site sends to you. Cookies from the headers could\n"
+" then be read in a second curl invocation by using the -b,\n"
+, stdout);
+ fputs(
+" --cookie option! The -c, --cookie-jar option is however a better\n"
+" way to store cookies.\n"
+"\n"
+" When used in FTP, the FTP server response lines are considered\n"
+" being \"headers\" and thus are saved there.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --data-ascii <data>\n"
+" See -d, --data.\n"
+"\n"
+" --data-binary <data>\n"
+" (HTTP) This posts data exactly as specified with no extra pro-\n"
+, stdout);
+ fputs(
+" cessing whatsoever.\n"
+"\n"
+" If you start the data with the letter @, the rest should be a\n"
+" filename. Data is posted in a similar manner as --data-ascii\n"
+" does, except that newlines and carriage returns are preserved\n"
+" and conversions are never done.\n"
+"\n"
+" If this option is used several times, the ones following the\n"
+" first will append data as described in -d, --data.\n"
+"\n"
+" --data-urlencode <data>\n"
+, stdout);
+ fputs(
+" (HTTP) This posts data, similar to the other --data options with\n"
+" the exception that this performs URL-encoding. (Added in 7.18.0)\n"
+" To be CGI-compliant, the <data> part should begin with a name\n"
+" followed by a separator and a content specification. The <data>\n"
+" part can be passed to curl using one of the following syntaxes:\n"
+"\n"
+" content\n"
+" This will make curl URL-encode the content and pass that\n"
+, stdout);
+ fputs(
+" on. Just be careful so that the content doesn't contain\n"
+" any = or @ symbols, as that will then make the syntax\n"
+" match one of the other cases below!\n"
+"\n"
+" =content\n"
+" This will make curl URL-encode the content and pass that\n"
+" on. The preceding = symbol is not included in the data.\n"
+"\n"
+" name=content\n"
+, stdout);
+ fputs(
+" This will make curl URL-encode the content part and pass\n"
+" that on. Note that the name part is expected to be URL-\n"
+" encoded already.\n"
+"\n"
+" @filename\n"
+" This will make curl load data from the given file\n"
+" (including any newlines), URL-encode that data and pass\n"
+" it on in the POST.\n"
+"\n"
+" name@filename\n"
+, stdout);
+ fputs(
+" This will make curl load data from the given file\n"
+" (including any newlines), URL-encode that data and pass\n"
+" it on in the POST. The name part gets an equal sign\n"
+" appended, resulting in name=urlencoded-file-content. Note\n"
+" that the name is expected to be URL-encoded already.\n"
+"\n"
+" --delegation LEVEL\n"
+" Set LEVEL to tell the server what it is allowed to delegate when\n"
+, stdout);
+ fputs(
+" it comes to user credentials. Used with GSS/kerberos.\n"
+"\n"
+" none Don't allow any delegation.\n"
+"\n"
+" policy Delegates if and only if the OK-AS-DELEGATE flag is set\n"
+" in the Kerberos service ticket, which is a matter of\n"
+" realm policy.\n"
+"\n"
+" always Unconditionally allow the server to delegate.\n"
+"\n"
+" --digest\n"
+" (HTTP) Enables HTTP Digest authentication. This is an authenti-\n"
+, stdout);
+ fputs(
+" cation scheme that prevents the password from being sent over\n"
+" the wire in clear text. Use this in combination with the normal\n"
+" -u, --user option to set user name and password. See also\n"
+" --ntlm, --negotiate and --anyauth for related options.\n"
+"\n"
+" If this option is used several times, only the first one is\n"
+" used.\n"
+"\n"
+" --disable-eprt\n"
+, stdout);
+ fputs(
+" (FTP) Tell curl to disable the use of the EPRT and LPRT commands\n"
+" when doing active FTP transfers. Curl will normally always first\n"
+" attempt to use EPRT, then LPRT before using PORT, but with this\n"
+" option, it will use PORT right away. EPRT and LPRT are exten-\n"
+" sions to the original FTP protocol, and may not work on all\n"
+" servers, but they enable more functionality in a better way than\n"
+, stdout);
+ fputs(
+" the traditional PORT command.\n"
+"\n"
+" --eprt can be used to explicitly enable EPRT again and --no-eprt\n"
+" is an alias for --disable-eprt.\n"
+"\n"
+" Disabling EPRT only changes the active behavior. If you want to\n"
+" switch to passive mode you need to not use -P, --ftp-port or\n"
+" force it with --ftp-pasv.\n"
+"\n"
+" --disable-epsv\n"
+" (FTP) Tell curl to disable the use of the EPSV command when\n"
+, stdout);
+ fputs(
+" doing passive FTP transfers. Curl will normally always first\n"
+" attempt to use EPSV before PASV, but with this option, it will\n"
+" not try using EPSV.\n"
+"\n"
+" --epsv can be used to explicitly enable EPSV again and --no-epsv\n"
+" is an alias for --disable-epsv.\n"
+"\n"
+" Disabling EPSV only changes the passive behavior. If you want to\n"
+" switch to active mode you need to use -P, --ftp-port.\n"
+"\n"
+, stdout);
+ fputs(
+" --dns-interface <interface>\n"
+" Tell curl to send outgoing DNS requests through <interface>.\n"
+" This option is a counterpart to --interface (which does not\n"
+" affect DNS). The supplied string must be an interface name (not\n"
+" an address).\n"
+"\n"
+" This option requires that libcurl was built with a resolver\n"
+" backend that supports this operation. The c-ares backend is the\n"
+, stdout);
+ fputs(
+" only such one. (Added in 7.33.0)\n"
+"\n"
+" --dns-ipv4-addr <ip-address>\n"
+" Tell curl to bind to <ip-address> when making IPv4 DNS requests,\n"
+" so that the DNS requests originate from this address. The argu-\n"
+" ment should be a single IPv4 address.\n"
+"\n"
+" This option requires that libcurl was built with a resolver\n"
+" backend that supports this operation. The c-ares backend is the\n"
+, stdout);
+ fputs(
+" only such one. (Added in 7.33.0)\n"
+"\n"
+" --dns-ipv6-addr <ip-address>\n"
+" Tell curl to bind to <ip-address> when making IPv6 DNS requests,\n"
+" so that the DNS requests originate from this address. The argu-\n"
+" ment should be a single IPv6 address.\n"
+"\n"
+" This option requires that libcurl was built with a resolver\n"
+" backend that supports this operation. The c-ares backend is the\n"
+, stdout);
+ fputs(
+" only such one. (Added in 7.33.0)\n"
+"\n"
+" --dns-servers <ip-address,ip-address>\n"
+" Set the list of DNS servers to be used instead of the system\n"
+" default. The list of IP addresses should be separated with com-\n"
+" mas. Port numbers may also optionally be given as :<port-number>\n"
+" after each IP address.\n"
+"\n"
+" This option requires that libcurl was built with a resolver\n"
+, stdout);
+ fputs(
+" backend that supports this operation. The c-ares backend is the\n"
+" only such one. (Added in 7.33.0)\n"
+"\n"
+" -e, --referer <URL>\n"
+" (HTTP) Sends the \"Referrer Page\" information to the HTTP server.\n"
+" This can also be set with the -H, --header flag of course. When\n"
+" used with -L, --location you can append \";auto\" to the --referer\n"
+" URL to make curl automatically set the previous URL when it fol-\n"
+, stdout);
+ fputs(
+" lows a Location: header. The \";auto\" string can be used alone,\n"
+" even if you don't set an initial --referer.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -E, --cert <certificate[:password]>\n"
+" (SSL) Tells curl to use the specified client certificate file\n"
+" when getting a file with HTTPS, FTPS or another SSL-based proto-\n"
+" col. The certificate must be in PKCS#12 format if using Secure\n"
+, stdout);
+ fputs(
+" Transport, or PEM format if using any other engine. If the\n"
+" optional password isn't specified, it will be queried for on the\n"
+" terminal. Note that this option assumes a \"certificate\" file\n"
+" that is the private key and the private certificate concate-\n"
+" nated! See --cert and --key to specify them independently.\n"
+"\n"
+" If curl is built against the NSS SSL library then this option\n"
+, stdout);
+ fputs(
+" can tell curl the nickname of the certificate to use within the\n"
+" NSS database defined by the environment variable SSL_DIR (or by\n"
+" default /etc/pki/nssdb). If the NSS PEM PKCS#11 module (lib-\n"
+" nsspem.so) is available then PEM files may be loaded. If you\n"
+" want to use a file from the current directory, please precede it\n"
+" with \"./\" prefix, in order to avoid confusion with a nickname.\n"
+, stdout);
+ fputs(
+" If the nickname contains \":\", it needs to be preceded by \"\\\" so\n"
+" that it is not recognized as password delimiter. If the nick-\n"
+" name contains \"\\\", it needs to be escaped as \"\\\\\" so that it is\n"
+" not recognized as an escape character.\n"
+"\n"
+" (iOS and Mac OS X only) If curl is built against Secure Trans-\n"
+" port, then the certificate string can either be the name of a\n"
+, stdout);
+ fputs(
+" certificate/private key in the system or user keychain, or the\n"
+" path to a PKCS#12-encoded certificate and private key. If you\n"
+" want to use a file from the current directory, please precede it\n"
+" with \"./\" prefix, in order to avoid confusion with a nickname.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --engine <name>\n"
+" Select the OpenSSL crypto engine to use for cipher operations.\n"
+, stdout);
+ fputs(
+" Use --engine list to print a list of build-time supported\n"
+" engines. Note that not all (or none) of the engines may be\n"
+" available at run-time.\n"
+"\n"
+" --environment\n"
+" (RISC OS ONLY) Sets a range of environment variables, using the\n"
+" names the -w option supports, to allow easier extraction of use-\n"
+" ful information after having run curl.\n"
+"\n"
+" --egd-file <file>\n"
+, stdout);
+ fputs(
+" (SSL) Specify the path name to the Entropy Gathering Daemon\n"
+" socket. The socket is used to seed the random engine for SSL\n"
+" connections. See also the --random-file option.\n"
+"\n"
+" --cert-type <type>\n"
+" (SSL) Tells curl what certificate type the provided certificate\n"
+" is in. PEM, DER and ENG are recognized types. If not specified,\n"
+" PEM is assumed.\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --cacert <CA certificate>\n"
+" (SSL) Tells curl to use the specified certificate file to verify\n"
+" the peer. The file may contain multiple CA certificates. The\n"
+" certificate(s) must be in PEM format. Normally curl is built to\n"
+" use a default file for this, so this option is typically used to\n"
+" alter that default file.\n"
+"\n"
+, stdout);
+ fputs(
+" curl recognizes the environment variable named 'CURL_CA_BUNDLE'\n"
+" if it is set, and uses the given path as a path to a CA cert\n"
+" bundle. This option overrides that variable.\n"
+"\n"
+" The windows version of curl will automatically look for a CA\n"
+" certs file named 'curl-ca-bundle.crt', either in the same direc-\n"
+" tory as curl.exe, or in the Current Working Directory, or in any\n"
+" folder along your PATH.\n"
+"\n"
+, stdout);
+ fputs(
+" If curl is built against the NSS SSL library, the NSS PEM\n"
+" PKCS#11 module (libnsspem.so) needs to be available for this\n"
+" option to work properly.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --capath <CA certificate directory>\n"
+" (SSL) Tells curl to use the specified certificate directory to\n"
+" verify the peer. Multiple paths can be provided by separating\n"
+, stdout);
+ fputs(
+" them with \":\" (e.g. \"path1:path2:path3\"). The certificates must\n"
+" be in PEM format, and if curl is built against OpenSSL, the\n"
+" directory must have been processed using the c_rehash utility\n"
+" supplied with OpenSSL. Using --capath can allow OpenSSL-powered\n"
+" curl to make SSL-connections much more efficiently than using\n"
+" --cacert if the --cacert file contains many CA certificates.\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is set, the default capath value will be ignored,\n"
+" and if it is used several times, the last one will be used.\n"
+"\n"
+" -f, --fail\n"
+" (HTTP) Fail silently (no output at all) on server errors. This\n"
+" is mostly done to better enable scripts etc to better deal with\n"
+" failed attempts. In normal cases when an HTTP server fails to\n"
+" deliver a document, it returns an HTML document stating so\n"
+, stdout);
+ fputs(
+" (which often also describes why and more). This flag will pre-\n"
+" vent curl from outputting that and return error 22.\n"
+"\n"
+" This method is not fail-safe and there are occasions where non-\n"
+" successful response codes will slip through, especially when\n"
+" authentication is involved (response codes 401 and 407).\n"
+"\n"
+" -F, --form <name=content>\n"
+" (HTTP) This lets curl emulate a filled-in form in which a user\n"
+, stdout);
+ fputs(
+" has pressed the submit button. This causes curl to POST data\n"
+" using the Content-Type multipart/form-data according to RFC\n"
+" 2388. This enables uploading of binary files etc. To force the\n"
+" 'content' part to be a file, prefix the file name with an @\n"
+" sign. To just get the content part from a file, prefix the file\n"
+" name with the symbol <. The difference between @ and < is then\n"
+, stdout);
+ fputs(
+" that @ makes a file get attached in the post as a file upload,\n"
+" while the < makes a text field and just get the contents for\n"
+" that text field from a file.\n"
+"\n"
+" Example, to send your password file to the server, where 'pass-\n"
+" word' is the name of the form-field to which /etc/passwd will be\n"
+" the input:\n"
+"\n"
+" curl -F password=@/etc/passwd www.mypasswords.com\n"
+"\n"
+, stdout);
+ fputs(
+" To read content from stdin instead of a file, use - as the file-\n"
+" name. This goes for both @ and < constructs.\n"
+"\n"
+" You can also tell curl what Content-Type to use by using\n"
+" 'type=', in a manner similar to:\n"
+"\n"
+" curl -F \"web=@index.html;type=text/html\" url.com\n"
+"\n"
+" or\n"
+"\n"
+" curl -F \"name=daniel;type=text/foo\" url.com\n"
+"\n"
+" You can also explicitly change the name field of a file upload\n"
+, stdout);
+ fputs(
+" part by setting filename=, like this:\n"
+"\n"
+" curl -F \"file=@localfile;filename=nameinpost\" url.com\n"
+"\n"
+" If filename/path contains ',' or ';', it must be quoted by dou-\n"
+" ble-quotes like:\n"
+"\n"
+" curl -F \"file=@\\\"localfile\\\";filename=\\\"nameinpost\\\"\" url.com\n"
+"\n"
+" or\n"
+"\n"
+" curl -F 'file=@\"localfile\";filename=\"nameinpost\"' url.com\n"
+"\n"
+" Note that if a filename/path is quoted by double-quotes, any\n"
+, stdout);
+ fputs(
+" double-quote or backslash within the filename must be escaped by\n"
+" backslash.\n"
+"\n"
+" See further examples and details in the MANUAL.\n"
+"\n"
+" This option can be used multiple times.\n"
+"\n"
+" --ftp-account [data]\n"
+" (FTP) When an FTP server asks for \"account data\" after user name\n"
+" and password has been provided, this data is sent off using the\n"
+" ACCT command. (Added in 7.13.0)\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --ftp-alternative-to-user <command>\n"
+" (FTP) If authenticating with the USER and PASS commands fails,\n"
+" send this command. When connecting to Tumbleweed's Secure\n"
+" Transport server over FTPS using a client certificate, using\n"
+" \"SITE AUTH\" will tell the server to retrieve the username from\n"
+" the certificate. (Added in 7.15.5)\n"
+"\n"
+, stdout);
+ fputs(
+" --ftp-create-dirs\n"
+" (FTP/SFTP) When an FTP or SFTP URL/operation uses a path that\n"
+" doesn't currently exist on the server, the standard behavior of\n"
+" curl is to fail. Using this option, curl will instead attempt to\n"
+" create missing directories.\n"
+"\n"
+" --ftp-method [method]\n"
+" (FTP) Control what method curl should use to reach a file on an\n"
+" FTP(S) server. The method argument should be one of the follow-\n"
+, stdout);
+ fputs(
+" ing alternatives:\n"
+"\n"
+" multicwd\n"
+" curl does a single CWD operation for each path part in\n"
+" the given URL. For deep hierarchies this means very many\n"
+" commands. This is how RFC 1738 says it should be done.\n"
+" This is the default but the slowest behavior.\n"
+"\n"
+" nocwd curl does no CWD at all. curl will do SIZE, RETR, STOR\n"
+, stdout);
+ fputs(
+" etc and give a full path to the server for all these com-\n"
+" mands. This is the fastest behavior.\n"
+"\n"
+" singlecwd\n"
+" curl does one CWD with the full target directory and then\n"
+" operates on the file \"normally\" (like in the multicwd\n"
+" case). This is somewhat more standards compliant than\n"
+" 'nocwd' but without the full penalty of 'multicwd'.\n"
+" (Added in 7.15.1)\n"
+"\n"
+, stdout);
+ fputs(
+" --ftp-pasv\n"
+" (FTP) Use passive mode for the data connection. Passive is the\n"
+" internal default behavior, but using this option can be used to\n"
+" override a previous -P/-ftp-port option. (Added in 7.11.0)\n"
+"\n"
+" If this option is used several times, only the first one is\n"
+" used. Undoing an enforced passive really isn't doable but you\n"
+" must then instead enforce the correct -P, --ftp-port again.\n"
+"\n"
+, stdout);
+ fputs(
+" Passive mode means that curl will try the EPSV command first and\n"
+" then PASV, unless --disable-epsv is used.\n"
+"\n"
+" --ftp-skip-pasv-ip\n"
+" (FTP) Tell curl to not use the IP address the server suggests in\n"
+" its response to curl's PASV command when curl connects the data\n"
+" connection. Instead curl will re-use the same IP address it\n"
+" already uses for the control connection. (Added in 7.14.2)\n"
+"\n"
+, stdout);
+ fputs(
+" This option has no effect if PORT, EPRT or EPSV is used instead\n"
+" of PASV.\n"
+"\n"
+" --ftp-pret\n"
+" (FTP) Tell curl to send a PRET command before PASV (and EPSV).\n"
+" Certain FTP servers, mainly drftpd, require this non-standard\n"
+" command for directory listings as well as up and downloads in\n"
+" PASV mode. (Added in 7.20.x)\n"
+"\n"
+" --ftp-ssl-ccc\n"
+, stdout);
+ fputs(
+" (FTP) Use CCC (Clear Command Channel) Shuts down the SSL/TLS\n"
+" layer after authenticating. The rest of the control channel com-\n"
+" munication will be unencrypted. This allows NAT routers to fol-\n"
+" low the FTP transaction. The default mode is passive. See --ftp-\n"
+" ssl-ccc-mode for other modes. (Added in 7.16.1)\n"
+"\n"
+" --ftp-ssl-ccc-mode [active/passive]\n"
+, stdout);
+ fputs(
+" (FTP) Use CCC (Clear Command Channel) Sets the CCC mode. The\n"
+" passive mode will not initiate the shutdown, but instead wait\n"
+" for the server to do it, and will not reply to the shutdown from\n"
+" the server. The active mode initiates the shutdown and waits for\n"
+" a reply from the server. (Added in 7.16.2)\n"
+"\n"
+" --ftp-ssl-control\n"
+" (FTP) Require SSL/TLS for the FTP login, clear for transfer.\n"
+, stdout);
+ fputs(
+" Allows secure authentication, but non-encrypted data transfers\n"
+" for efficiency. Fails the transfer if the server doesn't sup-\n"
+" port SSL/TLS. (Added in 7.16.0) that can still be used but will\n"
+" be removed in a future version.\n"
+"\n"
+" --form-string <name=string>\n"
+" (HTTP) Similar to --form except that the value string for the\n"
+" named parameter is used literally. Leading '@' and '<' charac-\n"
+, stdout);
+ fputs(
+" ters, and the ';type=' string in the value have no special mean-\n"
+" ing. Use this in preference to --form if there's any possibility\n"
+" that the string value may accidentally trigger the '@' or '<'\n"
+" features of --form.\n"
+"\n"
+" -g, --globoff\n"
+" This option switches off the \"URL globbing parser\". When you set\n"
+" this option, you can specify URLs that contain the letters {}[]\n"
+, stdout);
+ fputs(
+" without having them being interpreted by curl itself. Note that\n"
+" these letters are not normal legal URL contents but they should\n"
+" be encoded according to the URI standard.\n"
+"\n"
+" -G, --get\n"
+" When used, this option will make all data specified with -d,\n"
+" --data, --data-binary or --data-urlencode to be used in an HTTP\n"
+" GET request instead of the POST request that otherwise would be\n"
+, stdout);
+ fputs(
+" used. The data will be appended to the URL with a '?' separator.\n"
+" If used in combination with -I, the POST data will instead be\n"
+" appended to the URL with a HEAD request.\n"
+"\n"
+" If this option is used several times, only the first one is\n"
+" used. This is because undoing a GET doesn't make sense, but you\n"
+" should then instead enforce the alternative method you prefer.\n"
+"\n"
+" -H, --header <header>\n"
+, stdout);
+ fputs(
+" (HTTP) Extra header to include in the request when sending HTTP\n"
+" to a server. You may specify any number of extra headers. Note\n"
+" that if you should add a custom header that has the same name as\n"
+" one of the internal ones curl would use, your externally set\n"
+" header will be used instead of the internal one. This allows you\n"
+" to make even trickier stuff than curl would normally do. You\n"
+, stdout);
+ fputs(
+" should not replace internally set headers without knowing per-\n"
+" fectly well what you're doing. Remove an internal header by giv-\n"
+" ing a replacement without content on the right side of the\n"
+" colon, as in: -H \"Host:\". If you send the custom header with no-\n"
+" value then its header must be terminated with a semicolon, such\n"
+" as -H \"X-Custom-Header;\" to send \"X-Custom-Header:\".\n"
+"\n"
+, stdout);
+ fputs(
+" curl will make sure that each header you add/replace is sent\n"
+" with the proper end-of-line marker, you should thus not add that\n"
+" as a part of the header content: do not add newlines or carriage\n"
+" returns, they will only mess things up for you.\n"
+"\n"
+" See also the -A, --user-agent and -e, --referer options.\n"
+"\n"
+" Starting in 7.37.0, you need --proxy-header to send custom head-\n"
+" ers intended for a proxy.\n"
+"\n"
+, stdout);
+ fputs(
+" Example:\n"
+"\n"
+" # curl -H \"X-First-Name: Joe\" http://192.168.0.1/\n"
+"\n"
+" This option can be used multiple times to add/replace/remove\n"
+" multiple headers.\n"
+"\n"
+" --hostpubmd5 <md5>\n"
+" (SCP/SFTP) Pass a string containing 32 hexadecimal digits. The\n"
+" string should be the 128 bit MD5 checksum of the remote host's\n"
+" public key, curl will refuse the connection with the host unless\n"
+, stdout);
+ fputs(
+" the md5sums match. (Added in 7.17.1)\n"
+"\n"
+" --ignore-content-length\n"
+" (HTTP) Ignore the Content-Length header. This is particularly\n"
+" useful for servers running Apache 1.x, which will report incor-\n"
+" rect Content-Length for files larger than 2 gigabytes.\n"
+"\n"
+" -i, --include\n"
+" (HTTP) Include the HTTP-header in the output. The HTTP-header\n"
+" includes things like server-name, date of the document, HTTP-\n"
+, stdout);
+ fputs(
+" version and more...\n"
+"\n"
+" -I, --head\n"
+" (HTTP/FTP/FILE) Fetch the HTTP-header only! HTTP-servers feature\n"
+" the command HEAD which this uses to get nothing but the header\n"
+" of a document. When used on an FTP or FILE file, curl displays\n"
+" the file size and last modification time only.\n"
+"\n"
+" --interface <name>\n"
+" Perform an operation using a specified interface. You can enter\n"
+, stdout);
+ fputs(
+" interface name, IP address or host name. An example could look\n"
+" like:\n"
+"\n"
+" curl --interface eth0:1 http://www.netscape.com/\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -j, --junk-session-cookies\n"
+" (HTTP) When curl is told to read cookies from a given file, this\n"
+" option will make it discard all \"session cookies\". This will\n"
+, stdout);
+ fputs(
+" basically have the same effect as if a new session is started.\n"
+" Typical browsers always discard session cookies when they're\n"
+" closed down.\n"
+"\n"
+" -J, --remote-header-name\n"
+" (HTTP) This option tells the -O, --remote-name option to use the\n"
+" server-specified Content-Disposition filename instead of\n"
+" extracting a filename from the URL.\n"
+"\n"
+, stdout);
+ fputs(
+" There's no attempt to decode %-sequences (yet) in the provided\n"
+" file name, so this option may provide you with rather unexpected\n"
+" file names.\n"
+"\n"
+" -k, --insecure\n"
+" (SSL) This option explicitly allows curl to perform \"insecure\"\n"
+" SSL connections and transfers. All SSL connections are attempted\n"
+" to be made secure by using the CA certificate bundle installed\n"
+, stdout);
+ fputs(
+" by default. This makes all connections considered \"insecure\"\n"
+" fail unless -k, --insecure is used.\n"
+"\n"
+" See this online resource for further details:\n"
+" http://curl.haxx.se/docs/sslcerts.html\n"
+"\n"
+" -K, --config <config file>\n"
+" Specify which config file to read curl arguments from. The con-\n"
+" fig file is a text file in which command line arguments can be\n"
+, stdout);
+ fputs(
+" written which then will be used as if they were written on the\n"
+" actual command line.\n"
+"\n"
+" Options and their parameters must be specified on the same con-\n"
+" fig file line, separated by whitespace, colon, or the equals\n"
+" sign. Long option names can optionally be given in the config\n"
+" file without the initial double dashes and if so, the colon or\n"
+, stdout);
+ fputs(
+" equals characters can be used as separators. If the option is\n"
+" specified with one or two dashes, there can be no colon or\n"
+" equals character between the option and its parameter.\n"
+"\n"
+" If the parameter is to contain whitespace, the parameter must be\n"
+" enclosed within quotes. Within double quotes, the following\n"
+" escape sequences are available: \\\\, \\\", \\t, \\n, \\r and \\v. A\n"
+, stdout);
+ fputs(
+" backslash preceding any other letter is ignored. If the first\n"
+" column of a config line is a '#' character, the rest of the line\n"
+" will be treated as a comment. Only write one option per physical\n"
+" line in the config file.\n"
+"\n"
+" Specify the filename to -K, --config as '-' to make curl read\n"
+" the file from stdin.\n"
+"\n"
+" Note that to be able to specify a URL in the config file, you\n"
+, stdout);
+ fputs(
+" need to specify it using the --url option, and not by simply\n"
+" writing the URL on its own line. So, it could look similar to\n"
+" this:\n"
+"\n"
+" url = \"http://curl.haxx.se/docs/\"\n"
+"\n"
+" When curl is invoked, it always (unless -q is used) checks for a\n"
+" default config file and uses it if found. The default config\n"
+" file is checked for in the following places in this order:\n"
+"\n"
+, stdout);
+ fputs(
+" 1) curl tries to find the \"home dir\": It first checks for the\n"
+" CURL_HOME and then the HOME environment variables. Failing that,\n"
+" it uses getpwuid() on UNIX-like systems (which returns the home\n"
+" dir given the current user in your system). On Windows, it then\n"
+" checks for the APPDATA variable, or as a last resort the '%USER-\n"
+" PROFILE%\\Application Data'.\n"
+"\n"
+, stdout);
+ fputs(
+" 2) On windows, if there is no _curlrc file in the home dir, it\n"
+" checks for one in the same dir the curl executable is placed. On\n"
+" UNIX-like systems, it will simply try to load .curlrc from the\n"
+" determined home dir.\n"
+"\n"
+" # --- Example file ---\n"
+" # this is a comment\n"
+" url = \"curl.haxx.se\"\n"
+" output = \"curlhere.html\"\n"
+" user-agent = \"superagent/1.0\"\n"
+"\n"
+, stdout);
+ fputs(
+" # and fetch another URL too\n"
+" url = \"curl.haxx.se/docs/manpage.html\"\n"
+" -O\n"
+" referer = \"http://nowhereatall.com/\"\n"
+" # --- End of example file ---\n"
+"\n"
+" This option can be used multiple times to load multiple config\n"
+" files.\n"
+"\n"
+" --keepalive-time <seconds>\n"
+" This option sets the time a connection needs to remain idle\n"
+, stdout);
+ fputs(
+" before sending keepalive probes and the time between individual\n"
+" keepalive probes. It is currently effective on operating systems\n"
+" offering the TCP_KEEPIDLE and TCP_KEEPINTVL socket options\n"
+" (meaning Linux, recent AIX, HP-UX and more). This option has no\n"
+" effect if --no-keepalive is used. (Added in 7.18.0)\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+, stdout);
+ fputs(
+" If unspecified, the option defaults to 60 seconds.\n"
+"\n"
+" --key <key>\n"
+" (SSL/SSH) Private key file name. Allows you to provide your pri-\n"
+" vate key in this separate file.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --key-type <type>\n"
+" (SSL) Private key file type. Specify which type your --key pro-\n"
+" vided private key is. DER, PEM, and ENG are supported. If not\n"
+, stdout);
+ fputs(
+" specified, PEM is assumed.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --krb <level>\n"
+" (FTP) Enable Kerberos authentication and use. The level must be\n"
+" entered and should be one of 'clear', 'safe', 'confidential', or\n"
+" 'private'. Should you use a level that is not one of these,\n"
+" 'private' will instead be used.\n"
+"\n"
+, stdout);
+ fputs(
+" This option requires a library built with kerberos4 support.\n"
+" This is not very common. Use -V, --version to see if your curl\n"
+" supports it.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -l, --list-only\n"
+" (FTP) When listing an FTP directory, this switch forces a name-\n"
+" only view. This is especially useful if the user wants to\n"
+, stdout);
+ fputs(
+" machine-parse the contents of an FTP directory since the normal\n"
+" directory view doesn't use a standard look or format. When used\n"
+" like this, the option causes a NLST command to be sent to the\n"
+" server instead of LIST.\n"
+"\n"
+" Note: Some FTP servers list only files in their response to\n"
+" NLST; they do not include sub-directories and symbolic links.\n"
+"\n"
+, stdout);
+ fputs(
+" (POP3) When retrieving a specific email from POP3, this switch\n"
+" forces a LIST command to be performed instead of RETR. This is\n"
+" particularly useful if the user wants to see if a specific mes-\n"
+" sage id exists on the server and what size it is.\n"
+"\n"
+" Note: When combined with -X, --request <command>, this option\n"
+" can be used to send an UIDL command instead, so the user may use\n"
+, stdout);
+ fputs(
+" the email's unique identifier rather than it's message id to\n"
+" make the request. (Added in 7.21.5)\n"
+"\n"
+" -L, --location\n"
+" (HTTP/HTTPS) If the server reports that the requested page has\n"
+" moved to a different location (indicated with a Location: header\n"
+" and a 3XX response code), this option will make curl redo the\n"
+" request on the new place. If used together with -i, --include or\n"
+, stdout);
+ fputs(
+" -I, --head, headers from all requested pages will be shown. When\n"
+" authentication is used, curl only sends its credentials to the\n"
+" initial host. If a redirect takes curl to a different host, it\n"
+" won't be able to intercept the user+password. See also --loca-\n"
+" tion-trusted on how to change this. You can limit the amount of\n"
+" redirects to follow by using the --max-redirs option.\n"
+"\n"
+, stdout);
+ fputs(
+" When curl follows a redirect and the request is not a plain GET\n"
+" (for example POST or PUT), it will do the following request with\n"
+" a GET if the HTTP response was 301, 302, or 303. If the response\n"
+" code was any other 3xx code, curl will re-send the following\n"
+" request using the same unmodified method.\n"
+"\n"
+" You can tell curl to not change the non-GET request method to\n"
+, stdout);
+ fputs(
+" GET after a 30x response by using the dedicated options for\n"
+" that: --post301, --post302 and -post303.\n"
+"\n"
+" --libcurl <file>\n"
+" Append this option to any ordinary curl command line, and you\n"
+" will get a libcurl-using C source code written to the file that\n"
+" does the equivalent of what your command-line operation does!\n"
+"\n"
+" If this option is used several times, the last given file name\n"
+, stdout);
+ fputs(
+" will be used. (Added in 7.16.1)\n"
+"\n"
+" --limit-rate <speed>\n"
+" Specify the maximum transfer rate you want curl to use - for\n"
+" both downloads and uploads. This feature is useful if you have a\n"
+" limited pipe and you'd like your transfer not to use your entire\n"
+" bandwidth. To make it slower than it otherwise would be.\n"
+"\n"
+" The given speed is measured in bytes/second, unless a suffix is\n"
+, stdout);
+ fputs(
+" appended. Appending 'k' or 'K' will count the number as kilo-\n"
+" bytes, 'm' or M' makes it megabytes, while 'g' or 'G' makes it\n"
+" gigabytes. Examples: 200K, 3m and 1G.\n"
+"\n"
+" The given rate is the average speed counted during the entire\n"
+" transfer. It means that curl might use higher transfer speeds in\n"
+" short bursts, but over time it uses no more than the given rate.\n"
+, stdout);
+ fputs(
+" If you also use the -Y, --speed-limit option, that option will\n"
+" take precedence and might cripple the rate-limiting slightly, to\n"
+" help keeping the speed-limit logic working.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --local-port <num>[-num]\n"
+" Set a preferred number or range of local port numbers to use for\n"
+" the connection(s). Note that port numbers by nature are a\n"
+, stdout);
+ fputs(
+" scarce resource that will be busy at times so setting this range\n"
+" to something too narrow might cause unnecessary connection setup\n"
+" failures. (Added in 7.15.2)\n"
+"\n"
+" --location-trusted\n"
+" (HTTP/HTTPS) Like -L, --location, but will allow sending the\n"
+" name + password to all hosts that the site may redirect to. This\n"
+" may or may not introduce a security breach if the site redirects\n"
+, stdout);
+ fputs(
+" you to a site to which you'll send your authentication info\n"
+" (which is plaintext in the case of HTTP Basic authentication).\n"
+"\n"
+" -m, --max-time <seconds>\n"
+" Maximum time in seconds that you allow the whole operation to\n"
+" take. This is useful for preventing your batch jobs from hang-\n"
+" ing for hours due to slow networks or links going down. Since\n"
+, stdout);
+ fputs(
+" 7.32.0, this option accepts decimal values, but the actual time-\n"
+" out will decrease in accuracy as the specified timeout increases\n"
+" in decimal precision. See also the --connect-timeout option.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --login-options <options>\n"
+" Specify the login options to use during server authentication.\n"
+"\n"
+, stdout);
+ fputs(
+" You can use the login options to specify protocol specific\n"
+" options that may be used during authentication. At present only\n"
+" IMAP, POP3 and SMTP support login options. For more information\n"
+" about the login options please see RFC 2384, RFC 5092 and IETF\n"
+" draft draft-earhart-url-smtp-00.txt (Added in 7.34.0).\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --mail-auth <address>\n"
+, stdout);
+ fputs(
+" (SMTP) Specify a single address. This will be used to specify\n"
+" the authentication address (identity) of a submitted message\n"
+" that is being relayed to another server.\n"
+"\n"
+" (Added in 7.25.0)\n"
+"\n"
+" --mail-from <address>\n"
+" (SMTP) Specify a single address that the given mail should get\n"
+" sent from.\n"
+"\n"
+" (Added in 7.20.0)\n"
+"\n"
+" --max-filesize <bytes>\n"
+, stdout);
+ fputs(
+" Specify the maximum size (in bytes) of a file to download. If\n"
+" the file requested is larger than this value, the transfer will\n"
+" not start and curl will return with exit code 63.\n"
+"\n"
+" NOTE: The file size is not always known prior to download, and\n"
+" for such files this option has no effect even if the file trans-\n"
+" fer ends up being larger than this given limit. This concerns\n"
+, stdout);
+ fputs(
+" both FTP and HTTP transfers.\n"
+"\n"
+" --mail-rcpt <address>\n"
+" (SMTP) Specify a single address, user name or mailing list name.\n"
+" When performing a mail transfer, the recipient should specify a\n"
+" valid email address to send the mail to. (Added in 7.20.0)\n"
+"\n"
+" When performing an address verification (VRFY command), the\n"
+" recipient should be specified as the user name or user name and\n"
+, stdout);
+ fputs(
+" domain (as per Section 3.5 of RFC5321). (Added in 7.34.0)\n"
+"\n"
+" When performing a mailing list expand (EXPN command), the recip-\n"
+" ient should be specified using the mailing list name, such as\n"
+" \"Friends\" or \"London-Office\". (Added in 7.34.0)\n"
+"\n"
+" --max-redirs <num>\n"
+" Set maximum number of redirection-followings allowed. If -L,\n"
+" --location is used, this option can be used to prevent curl from\n"
+, stdout);
+ fputs(
+" following redirections \"in absurdum\". By default, the limit is\n"
+" set to 50 redirections. Set this option to -1 to make it limit-\n"
+" less.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --metalink\n"
+" This option can tell curl to parse and process a given URI as\n"
+" Metalink file (both version 3 and 4 (RFC 5854) are supported)\n"
+, stdout);
+ fputs(
+" and make use of the mirrors listed within for failover if there\n"
+" are errors (such as the file or server not being available). It\n"
+" will also verify the hash of the file after the download com-\n"
+" pletes. The Metalink file itself is downloaded and processed in\n"
+" memory and not stored in the local file system.\n"
+"\n"
+" Example to use a remote Metalink file:\n"
+"\n"
+, stdout);
+ fputs(
+" curl --metalink http://www.example.com/example.metalink\n"
+"\n"
+" To use a Metalink file in the local file system, use FILE proto-\n"
+" col (file://):\n"
+"\n"
+" curl --metalink file://example.metalink\n"
+"\n"
+" Please note that if FILE protocol is disabled, there is no way\n"
+" to use a local Metalink file at the time of this writing. Also\n"
+" note that if --metalink and --include are used together,\n"
+, stdout);
+ fputs(
+" --include will be ignored. This is because including headers in\n"
+" the response will break Metalink parser and if the headers are\n"
+" included in the file described in Metalink file, hash check will\n"
+" fail.\n"
+"\n"
+" (Added in 7.27.0, if built against the libmetalink library.)\n"
+"\n"
+" -n, --netrc\n"
+" Makes curl scan the .netrc (_netrc on Windows) file in the\n"
+, stdout);
+ fputs(
+" user's home directory for login name and password. This is typi-\n"
+" cally used for FTP on UNIX. If used with HTTP, curl will enable\n"
+" user authentication. See netrc(4) or ftp(1) for details on the\n"
+" file format. Curl will not complain if that file doesn't have\n"
+" the right permissions (it should not be either world- or group-\n"
+" readable). The environment variable \"HOME\" is used to find the\n"
+, stdout);
+ fputs(
+" home directory.\n"
+"\n"
+" A quick and very simple example of how to setup a .netrc to\n"
+" allow curl to FTP to the machine host.domain.com with user name\n"
+" 'myself' and password 'secret' should look similar to:\n"
+"\n"
+" machine host.domain.com login myself password secret\n"
+"\n"
+" -N, --no-buffer\n"
+" Disables the buffering of the output stream. In normal work sit-\n"
+, stdout);
+ fputs(
+" uations, curl will use a standard buffered output stream that\n"
+" will have the effect that it will output the data in chunks, not\n"
+" necessarily exactly when the data arrives. Using this option\n"
+" will disable that buffering.\n"
+"\n"
+" Note that this is the negated option name documented. You can\n"
+" thus use --buffer to enforce the buffering.\n"
+"\n"
+" --netrc-file\n"
+, stdout);
+ fputs(
+" This option is similar to --netrc, except that you provide the\n"
+" path (absolute or relative) to the netrc file that Curl should\n"
+" use. You can only specify one netrc file per invocation. If\n"
+" several --netrc-file options are provided, only the last one\n"
+" will be used. (Added in 7.21.5)\n"
+"\n"
+" This option overrides any use of --netrc as they are mutually\n"
+, stdout);
+ fputs(
+" exclusive. It will also abide by --netrc-optional if specified.\n"
+"\n"
+" --netrc-optional\n"
+" Very similar to --netrc, but this option makes the .netrc usage\n"
+" optional and not mandatory as the --netrc option does.\n"
+"\n"
+" --negotiate\n"
+" (HTTP) Enables Negotiate (SPNEGO) authentication.\n"
+"\n"
+" If you want to enable Negotiate (SPNEGO) for proxy authentica-\n"
+" tion, then use --proxy-negotiate.\n"
+"\n"
+, stdout);
+ fputs(
+" This option requires a library built with GSS-API or SSPI sup-\n"
+" port. Use -V, --version to see if your curl supports GSS-\n"
+" API/SSPI and SPNEGO.\n"
+"\n"
+" When using this option, you must also provide a fake -u, --user\n"
+" option to activate the authentication code properly. Sending a\n"
+" '-u :' is enough as the user name and password from the -u\n"
+" option aren't actually used.\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, only the first one is\n"
+" used.\n"
+"\n"
+" --no-keepalive\n"
+" Disables the use of keepalive messages on the TCP connection, as\n"
+" by default curl enables them.\n"
+"\n"
+" Note that this is the negated option name documented. You can\n"
+" thus use --keepalive to enforce keepalive.\n"
+"\n"
+" --no-sessionid\n"
+" (SSL) Disable curl's use of SSL session-ID caching. By default\n"
+, stdout);
+ fputs(
+" all transfers are done using the cache. Note that while nothing\n"
+" should ever get hurt by attempting to reuse SSL session-IDs,\n"
+" there seem to be broken SSL implementations in the wild that may\n"
+" require you to disable this in order for you to succeed. (Added\n"
+" in 7.16.0)\n"
+"\n"
+" Note that this is the negated option name documented. You can\n"
+" thus use --sessionid to enforce session-ID caching.\n"
+"\n"
+, stdout);
+ fputs(
+" --noproxy <no-proxy-list>\n"
+" Comma-separated list of hosts which do not use a proxy, if one\n"
+" is specified. The only wildcard is a single * character, which\n"
+" matches all hosts, and effectively disables the proxy. Each name\n"
+" in this list is matched as either a domain which contains the\n"
+" hostname, or the hostname itself. For example, local.com would\n"
+, stdout);
+ fputs(
+" match local.com, local.com:80, and www.local.com, but not\n"
+" www.notlocal.com. (Added in 7.19.4).\n"
+"\n"
+" --ntlm (HTTP) Enables NTLM authentication. The NTLM authentication\n"
+" method was designed by Microsoft and is used by IIS web servers.\n"
+" It is a proprietary protocol, reverse-engineered by clever peo-\n"
+" ple and implemented in curl based on their efforts. This kind of\n"
+, stdout);
+ fputs(
+" behavior should not be endorsed, you should encourage everyone\n"
+" who uses NTLM to switch to a public and documented authentica-\n"
+" tion method instead, such as Digest.\n"
+"\n"
+" If you want to enable NTLM for your proxy authentication, then\n"
+" use --proxy-ntlm.\n"
+"\n"
+" This option requires a library built with SSL support. Use -V,\n"
+" --version to see if your curl supports NTLM.\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, only the first one is\n"
+" used.\n"
+"\n"
+" -o, --output <file>\n"
+" Write output to <file> instead of stdout. If you are using {} or\n"
+" [] to fetch multiple documents, you can use '#' followed by a\n"
+" number in the <file> specifier. That variable will be replaced\n"
+" with the current string for the URL being fetched. Like in:\n"
+"\n"
+, stdout);
+ fputs(
+" curl http://{one,two}.site.com -o \"file_#1.txt\"\n"
+"\n"
+" or use several variables like:\n"
+"\n"
+" curl http://{site,host}.host[1-5].com -o \"#1_#2\"\n"
+"\n"
+" You may use this option as many times as the number of URLs you\n"
+" have.\n"
+"\n"
+" See also the --create-dirs option to create the local directo-\n"
+" ries dynamically. Specifying the output as '-' (a single dash)\n"
+" will force the output to be done to stdout.\n"
+"\n"
+, stdout);
+ fputs(
+" -O, --remote-name\n"
+" Write output to a local file named like the remote file we get.\n"
+" (Only the file part of the remote file is used, the path is cut\n"
+" off.)\n"
+"\n"
+" The remote file name to use for saving is extracted from the\n"
+" given URL, nothing else.\n"
+"\n"
+" Consequentially, the file will be saved in the current working\n"
+" directory. If you want the file saved in a different directory,\n"
+, stdout);
+ fputs(
+" make sure you change current working directory before you invoke\n"
+" curl with the -O, --remote-name flag!\n"
+"\n"
+" There is no URL decoding done on the file name. If it has %20 or\n"
+" other URL encoded parts of the name, they will end up as-is as\n"
+" file name.\n"
+"\n"
+" You may use this option as many times as the number of URLs you\n"
+" have.\n"
+"\n"
+" --oauth2-bearer\n"
+, stdout);
+ fputs(
+" (IMAP, POP3, SMTP) Specify the Bearer Token for OAUTH 2.0 server\n"
+" authentication. The Bearer Token is used in conjunction with the\n"
+" user name which can be specified as part of the --url or -u,\n"
+" --user options.\n"
+"\n"
+" The Bearer Token and user name are formatted according to RFC\n"
+" 6750.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --proxy-header <header>\n"
+, stdout);
+ fputs(
+" (HTTP) Extra header to include in the request when sending HTTP\n"
+" to a proxy. You may specify any number of extra headers. This is\n"
+" the equivalent option to -H, --header but is for proxy communi-\n"
+" cation only like in CONNECT requests when you want a separate\n"
+" header sent to the proxy to what is sent to the actual remote\n"
+" host.\n"
+"\n"
+" curl will make sure that each header you add/replace is sent\n"
+, stdout);
+ fputs(
+" with the proper end-of-line marker, you should thus not add that\n"
+" as a part of the header content: do not add newlines or carriage\n"
+" returns, they will only mess things up for you.\n"
+"\n"
+" Headers specified with this option will not be included in\n"
+" requests that curl knows will not be sent to a proxy.\n"
+"\n"
+" This option can be used multiple times to add/replace/remove\n"
+" multiple headers.\n"
+, stdout);
+ fputs(
+" (Added in 7.37.0)\n"
+" -p, --proxytunnel\n"
+" When an HTTP proxy is used (-x, --proxy), this option will cause\n"
+" non-HTTP protocols to attempt to tunnel through the proxy\n"
+" instead of merely using it to do HTTP-like operations. The tun-\n"
+" nel approach is made with the HTTP proxy CONNECT request and\n"
+" requires that the proxy allows direct connect to the remote port\n"
+, stdout);
+ fputs(
+" number curl wants to tunnel through to.\n"
+"\n"
+" -P, --ftp-port <address>\n"
+" (FTP) Reverses the default initiator/listener roles when con-\n"
+" necting with FTP. This switch makes curl use active mode. In\n"
+" practice, curl then tells the server to connect back to the\n"
+" client's specified address and port, while passive mode asks the\n"
+" server to setup an IP address and port for it to connect to.\n"
+, stdout);
+ fputs(
+" <address> should be one of:\n"
+"\n"
+" interface\n"
+" i.e \"eth0\" to specify which interface's IP address you\n"
+" want to use (Unix only)\n"
+"\n"
+" IP address\n"
+" i.e \"192.168.10.1\" to specify the exact IP address\n"
+"\n"
+" host name\n"
+" i.e \"my.host.domain\" to specify the machine\n"
+"\n"
+" - make curl pick the same IP address that is already used\n"
+, stdout);
+ fputs(
+" for the control connection\n"
+"\n"
+" If this option is used several times, the last one will be used. Dis-\n"
+" able the use of PORT with --ftp-pasv. Disable the attempt to use the\n"
+" EPRT command instead of PORT by using --disable-eprt. EPRT is really\n"
+" PORT++.\n"
+"\n"
+" Starting in 7.19.5, you can append \":[start]-[end]\" to the right of the\n"
+" address, to tell curl what TCP port range to use. That means you spec-\n"
+, stdout);
+ fputs(
+" ify a port range, from a lower to a higher number. A single number\n"
+" works as well, but do note that it increases the risk of failure since\n"
+" the port may not be available.\n"
+"\n"
+" --pass <phrase>\n"
+" (SSL/SSH) Passphrase for the private key\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --post301\n"
+" (HTTP) Tells curl to respect RFC 2616/10.3.2 and not convert\n"
+, stdout);
+ fputs(
+" POST requests into GET requests when following a 301 redirect-\n"
+" ion. The non-RFC behaviour is ubiquitous in web browsers, so\n"
+" curl does the conversion by default to maintain consistency.\n"
+" However, a server may require a POST to remain a POST after such\n"
+" a redirection. This option is meaningful only when using -L,\n"
+" --location (Added in 7.17.1)\n"
+"\n"
+" --post302\n"
+, stdout);
+ fputs(
+" (HTTP) Tells curl to respect RFC 2616/10.3.2 and not convert\n"
+" POST requests into GET requests when following a 302 redirect-\n"
+" ion. The non-RFC behaviour is ubiquitous in web browsers, so\n"
+" curl does the conversion by default to maintain consistency.\n"
+" However, a server may require a POST to remain a POST after such\n"
+" a redirection. This option is meaningful only when using -L,\n"
+, stdout);
+ fputs(
+" --location (Added in 7.19.1)\n"
+"\n"
+" --post303\n"
+" (HTTP) Tells curl to respect RFC 2616/10.3.2 and not convert\n"
+" POST requests into GET requests when following a 303 redirect-\n"
+" ion. The non-RFC behaviour is ubiquitous in web browsers, so\n"
+" curl does the conversion by default to maintain consistency.\n"
+" However, a server may require a POST to remain a POST after such\n"
+, stdout);
+ fputs(
+" a redirection. This option is meaningful only when using -L,\n"
+" --location (Added in 7.26.0)\n"
+"\n"
+" --proto <protocols>\n"
+" Tells curl to use the listed protocols for its initial\n"
+" retrieval. Protocols are evaluated left to right, are comma sep-\n"
+" arated, and are each a protocol name or 'all', optionally pre-\n"
+" fixed by zero or more modifiers. Available modifiers are:\n"
+"\n"
+, stdout);
+ fputs(
+" + Permit this protocol in addition to protocols already permit-\n"
+" ted (this is the default if no modifier is used).\n"
+"\n"
+" - Deny this protocol, removing it from the list of protocols\n"
+" already permitted.\n"
+"\n"
+" = Permit only this protocol (ignoring the list already permit-\n"
+" ted), though subject to later modification by subsequent\n"
+" entries in the comma separated list.\n"
+"\n"
+, stdout);
+ fputs(
+" For example:\n"
+"\n"
+" --proto -ftps uses the default protocols, but disables ftps\n"
+"\n"
+" --proto -all,https,+http\n"
+" only enables http and https\n"
+"\n"
+" --proto =http,https\n"
+" also only enables http and https\n"
+"\n"
+" Unknown protocols produce a warning. This allows scripts to\n"
+" safely rely on being able to disable potentially dangerous pro-\n"
+, stdout);
+ fputs(
+" tocols, without relying upon support for that protocol being\n"
+" built into curl to avoid an error.\n"
+"\n"
+" This option can be used multiple times, in which case the effect\n"
+" is the same as concatenating the protocols into one instance of\n"
+" the option.\n"
+"\n"
+" (Added in 7.20.2)\n"
+"\n"
+" --proto-redir <protocols>\n"
+" Tells curl to use the listed protocols after a redirect. See\n"
+, stdout);
+ fputs(
+" --proto for how protocols are represented.\n"
+"\n"
+" (Added in 7.20.2)\n"
+"\n"
+" --proxy-anyauth\n"
+" Tells curl to pick a suitable authentication method when commu-\n"
+" nicating with the given proxy. This might cause an extra\n"
+" request/response round-trip. (Added in 7.13.2)\n"
+"\n"
+" --proxy-basic\n"
+" Tells curl to use HTTP Basic authentication when communicating\n"
+, stdout);
+ fputs(
+" with the given proxy. Use --basic for enabling HTTP Basic with a\n"
+" remote host. Basic is the default authentication method curl\n"
+" uses with proxies.\n"
+"\n"
+" --proxy-digest\n"
+" Tells curl to use HTTP Digest authentication when communicating\n"
+" with the given proxy. Use --digest for enabling HTTP Digest with\n"
+" a remote host.\n"
+"\n"
+" --proxy-negotiate\n"
+, stdout);
+ fputs(
+" Tells curl to use HTTP Negotiate (SPNEGO) authentication when\n"
+" communicating with the given proxy. Use --negotiate for enabling\n"
+" HTTP Negotiate (SPNEGO) with a remote host. (Added in 7.17.1)\n"
+"\n"
+" --proxy-ntlm\n"
+" Tells curl to use HTTP NTLM authentication when communicating\n"
+" with the given proxy. Use --ntlm for enabling NTLM with a remote\n"
+" host.\n"
+"\n"
+" --proxy1.0 <proxyhost[:port]>\n"
+, stdout);
+ fputs(
+" Use the specified HTTP 1.0 proxy. If the port number is not\n"
+" specified, it is assumed at port 1080.\n"
+"\n"
+" The only difference between this and the HTTP proxy option (-x,\n"
+" --proxy), is that attempts to use CONNECT through the proxy will\n"
+" specify an HTTP 1.0 protocol instead of the default HTTP 1.1.\n"
+"\n"
+" --pubkey <key>\n"
+" (SSH) Public key file name. Allows you to provide your public\n"
+, stdout);
+ fputs(
+" key in this separate file.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -q If used as the first parameter on the command line, the curlrc\n"
+" config file will not be read and used. See the -K, --config for\n"
+" details on the default config file search path.\n"
+"\n"
+" -Q, --quote <command>\n"
+" (FTP/SFTP) Send an arbitrary command to the remote FTP or SFTP\n"
+, stdout);
+ fputs(
+" server. Quote commands are sent BEFORE the transfer takes place\n"
+" (just after the initial PWD command in an FTP transfer, to be\n"
+" exact). To make commands take place after a successful transfer,\n"
+" prefix them with a dash '-'. To make commands be sent after\n"
+" curl has changed the working directory, just before the transfer\n"
+" command(s), prefix the command with a '+' (this is only sup-\n"
+, stdout);
+ fputs(
+" ported for FTP). You may specify any number of commands. If the\n"
+" server returns failure for one of the commands, the entire oper-\n"
+" ation will be aborted. You must send syntactically correct FTP\n"
+" commands as RFC 959 defines to FTP servers, or one of the com-\n"
+" mands listed below to SFTP servers. This option can be used\n"
+" multiple times. When speaking to an FTP server, prefix the com-\n"
+, stdout);
+ fputs(
+" mand with an asterisk (*) to make curl continue even if the com-\n"
+" mand fails as by default curl will stop at first failure.\n"
+"\n"
+" SFTP is a binary protocol. Unlike for FTP, curl interprets SFTP\n"
+" quote commands itself before sending them to the server. File\n"
+" names may be quoted shell-style to embed spaces or special char-\n"
+" acters. Following is the list of all supported SFTP quote com-\n"
+" mands:\n"
+"\n"
+, stdout);
+ fputs(
+" chgrp group file\n"
+" The chgrp command sets the group ID of the file named by\n"
+" the file operand to the group ID specified by the group\n"
+" operand. The group operand is a decimal integer group ID.\n"
+"\n"
+" chmod mode file\n"
+" The chmod command modifies the file mode bits of the\n"
+" specified file. The mode operand is an octal integer mode\n"
+" number.\n"
+"\n"
+, stdout);
+ fputs(
+" chown user file\n"
+" The chown command sets the owner of the file named by the\n"
+" file operand to the user ID specified by the user oper-\n"
+" and. The user operand is a decimal integer user ID.\n"
+"\n"
+" ln source_file target_file\n"
+" The ln and symlink commands create a symbolic link at the\n"
+" target_file location pointing to the source_file loca-\n"
+" tion.\n"
+"\n"
+, stdout);
+ fputs(
+" mkdir directory_name\n"
+" The mkdir command creates the directory named by the\n"
+" directory_name operand.\n"
+"\n"
+" pwd The pwd command returns the absolute pathname of the cur-\n"
+" rent working directory.\n"
+"\n"
+" rename source target\n"
+" The rename command renames the file or directory named by\n"
+" the source operand to the destination path named by the\n"
+, stdout);
+ fputs(
+" target operand.\n"
+"\n"
+" rm file\n"
+" The rm command removes the file specified by the file op-\n"
+" erand.\n"
+"\n"
+" rmdir directory\n"
+" The rmdir command removes the directory entry specified\n"
+" by the directory operand, provided it is empty.\n"
+"\n"
+" symlink source_file target_file\n"
+" See ln.\n"
+"\n"
+" -r, --range <range>\n"
+, stdout);
+ fputs(
+" (HTTP/FTP/SFTP/FILE) Retrieve a byte range (i.e a partial docu-\n"
+" ment) from a HTTP/1.1, FTP or SFTP server or a local FILE.\n"
+" Ranges can be specified in a number of ways.\n"
+"\n"
+" 0-499 specifies the first 500 bytes\n"
+"\n"
+" 500-999 specifies the second 500 bytes\n"
+"\n"
+" -500 specifies the last 500 bytes\n"
+"\n"
+" 9500- specifies the bytes from offset 9500 and forward\n"
+"\n"
+, stdout);
+ fputs(
+" 0-0,-1 specifies the first and last byte only(*)(H)\n"
+"\n"
+" 500-700,600-799\n"
+" specifies 300 bytes from offset 500(H)\n"
+"\n"
+" 100-199,500-599\n"
+" specifies two separate 100-byte ranges(*)(H)\n"
+"\n"
+" (*) = NOTE that this will cause the server to reply with a multipart\n"
+" response!\n"
+"\n"
+" Only digit characters (0-9) are valid in the 'start' and 'stop' fields\n"
+, stdout);
+ fputs(
+" of the 'start-stop' range syntax. If a non-digit character is given in\n"
+" the range, the server's response will be unspecified, depending on the\n"
+" server's configuration.\n"
+"\n"
+" You should also be aware that many HTTP/1.1 servers do not have this\n"
+" feature enabled, so that when you attempt to get a range, you'll\n"
+" instead get the whole document.\n"
+"\n"
+" FTP and SFTP range downloads only support the simple 'start-stop' syn-\n"
+, stdout);
+ fputs(
+" tax (optionally with one of the numbers omitted). FTP use depends on\n"
+" the extended FTP command SIZE.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -R, --remote-time\n"
+" When used, this will make curl attempt to figure out the time-\n"
+" stamp of the remote file, and if that is available make the\n"
+" local file get that same timestamp.\n"
+"\n"
+" --random-file <file>\n"
+, stdout);
+ fputs(
+" (SSL) Specify the path name to file containing what will be con-\n"
+" sidered as random data. The data is used to seed the random\n"
+" engine for SSL connections. See also the --egd-file option.\n"
+"\n"
+" --raw (HTTP) When used, it disables all internal HTTP decoding of con-\n"
+" tent or transfer encodings and instead makes them passed on\n"
+" unaltered, raw. (Added in 7.16.2)\n"
+"\n"
+" --remote-name-all\n"
+, stdout);
+ fputs(
+" This option changes the default action for all given URLs to be\n"
+" dealt with as if -O, --remote-name were used for each one. So if\n"
+" you want to disable that for a specific URL after --remote-name-\n"
+" all has been used, you must use \"-o -\" or --no-remote-name.\n"
+" (Added in 7.19.0)\n"
+"\n"
+" --resolve <host:port:address>\n"
+" Provide a custom address for a specific host and port pair.\n"
+, stdout);
+ fputs(
+" Using this, you can make the curl requests(s) use a specified\n"
+" address and prevent the otherwise normally resolved address to\n"
+" be used. Consider it a sort of /etc/hosts alternative provided\n"
+" on the command line. The port number should be the number used\n"
+" for the specific protocol the host will be used for. It means\n"
+" you need several entries if you want to provide address for the\n"
+, stdout);
+ fputs(
+" same host but different ports.\n"
+"\n"
+" This option can be used many times to add many host names to\n"
+" resolve.\n"
+"\n"
+" (Added in 7.21.3)\n"
+"\n"
+" --retry <num>\n"
+" If a transient error is returned when curl tries to perform a\n"
+" transfer, it will retry this number of times before giving up.\n"
+" Setting the number to 0 makes curl do no retries (which is the\n"
+, stdout);
+ fputs(
+" default). Transient error means either: a timeout, an FTP 4xx\n"
+" response code or an HTTP 5xx response code.\n"
+"\n"
+" When curl is about to retry a transfer, it will first wait one\n"
+" second and then for all forthcoming retries it will double the\n"
+" waiting time until it reaches 10 minutes which then will be the\n"
+" delay between the rest of the retries. By using --retry-delay\n"
+, stdout);
+ fputs(
+" you disable this exponential backoff algorithm. See also\n"
+" --retry-max-time to limit the total time allowed for retries.\n"
+" (Added in 7.12.3)\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --retry-delay <seconds>\n"
+" Make curl sleep this amount of time before each retry when a\n"
+" transfer has failed with a transient error (it changes the\n"
+, stdout);
+ fputs(
+" default backoff time algorithm between retries). This option is\n"
+" only interesting if --retry is also used. Setting this delay to\n"
+" zero will make curl use the default backoff time. (Added in\n"
+" 7.12.3)\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --retry-max-time <seconds>\n"
+" The retry timer is reset before the first transfer attempt.\n"
+, stdout);
+ fputs(
+" Retries will be done as usual (see --retry) as long as the timer\n"
+" hasn't reached this given limit. Notice that if the timer hasn't\n"
+" reached the limit, the request will be made and while perform-\n"
+" ing, it may take longer than this given time period. To limit a\n"
+" single request's maximum time, use -m, --max-time. Set this\n"
+" option to zero to not timeout retries. (Added in 7.12.3)\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -s, --silent\n"
+" Silent or quiet mode. Don't show progress meter or error mes-\n"
+" sages. Makes Curl mute. It will still output the data you ask\n"
+" for, potentially even to the terminal/stdout unless you redirect\n"
+" it.\n"
+"\n"
+" --sasl-ir\n"
+" Enable initial response in SASL authentication. (Added in\n"
+" 7.31.0)\n"
+"\n"
+" -S, --show-error\n"
+, stdout);
+ fputs(
+" When used with -s it makes curl show an error message if it\n"
+" fails.\n"
+"\n"
+" --ssl (FTP, POP3, IMAP, SMTP) Try to use SSL/TLS for the connection.\n"
+" Reverts to a non-secure connection if the server doesn't support\n"
+" SSL/TLS. See also --ftp-ssl-control and --ssl-reqd for differ-\n"
+" ent levels of encryption required. (Added in 7.20.0)\n"
+"\n"
+" This option was formerly known as --ftp-ssl (Added in 7.11.0).\n"
+, stdout);
+ fputs(
+" That option name can still be used but will be removed in a\n"
+" future version.\n"
+"\n"
+" --ssl-reqd\n"
+" (FTP, POP3, IMAP, SMTP) Require SSL/TLS for the connection.\n"
+" Terminates the connection if the server doesn't support SSL/TLS.\n"
+" (Added in 7.20.0)\n"
+"\n"
+" This option was formerly known as --ftp-ssl-reqd (added in\n"
+" 7.15.5). That option name can still be used but will be removed\n"
+, stdout);
+ fputs(
+" in a future version.\n"
+"\n"
+" --ssl-allow-beast\n"
+" (SSL) This option tells curl to not work around a security flaw\n"
+" in the SSL3 and TLS1.0 protocols known as BEAST. If this option\n"
+" isn't used, the SSL layer may use workarounds known to cause\n"
+" interoperability problems with some older SSL implementations.\n"
+" WARNING: this option loosens the SSL security, and by using this\n"
+, stdout);
+ fputs(
+" flag you ask for exactly that. (Added in 7.25.0)\n"
+"\n"
+" --socks4 <host[:port]>\n"
+" Use the specified SOCKS4 proxy. If the port number is not speci-\n"
+" fied, it is assumed at port 1080. (Added in 7.15.2)\n"
+"\n"
+" This option overrides any previous use of -x, --proxy, as they\n"
+" are mutually exclusive.\n"
+"\n"
+" Since 7.21.7, this option is superfluous since you can specify a\n"
+, stdout);
+ fputs(
+" socks4 proxy with -x, --proxy using a socks4:// protocol prefix.\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --socks4a <host[:port]>\n"
+" Use the specified SOCKS4a proxy. If the port number is not spec-\n"
+" ified, it is assumed at port 1080. (Added in 7.18.0)\n"
+"\n"
+" This option overrides any previous use of -x, --proxy, as they\n"
+" are mutually exclusive.\n"
+"\n"
+, stdout);
+ fputs(
+" Since 7.21.7, this option is superfluous since you can specify a\n"
+" socks4a proxy with -x, --proxy using a socks4a:// protocol pre-\n"
+" fix.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --socks5-hostname <host[:port]>\n"
+" Use the specified SOCKS5 proxy (and let the proxy resolve the\n"
+" host name). If the port number is not specified, it is assumed\n"
+, stdout);
+ fputs(
+" at port 1080. (Added in 7.18.0)\n"
+"\n"
+" This option overrides any previous use of -x, --proxy, as they\n"
+" are mutually exclusive.\n"
+"\n"
+" Since 7.21.7, this option is superfluous since you can specify a\n"
+" socks5 hostname proxy with -x, --proxy using a socks5h:// proto-\n"
+" col prefix.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+, stdout);
+ fputs(
+" (This option was previously wrongly documented and used as\n"
+" --socks without the number appended.)\n"
+"\n"
+" --socks5 <host[:port]>\n"
+" Use the specified SOCKS5 proxy - but resolve the host name\n"
+" locally. If the port number is not specified, it is assumed at\n"
+" port 1080.\n"
+"\n"
+" This option overrides any previous use of -x, --proxy, as they\n"
+" are mutually exclusive.\n"
+"\n"
+, stdout);
+ fputs(
+" Since 7.21.7, this option is superfluous since you can specify a\n"
+" socks5 proxy with -x, --proxy using a socks5:// protocol prefix.\n"
+" If this option is used several times, the last one will be used.\n"
+" (This option was previously wrongly documented and used as\n"
+" --socks without the number appended.)\n"
+"\n"
+" This option (as well as --socks4) does not work with IPV6, FTPS\n"
+" or LDAP.\n"
+"\n"
+, stdout);
+ fputs(
+" --socks5-gssapi-service <servicename>\n"
+" The default service name for a socks server is rcmd/server-fqdn.\n"
+" This option allows you to change it.\n"
+"\n"
+" Examples: --socks5 proxy-name --socks5-gssapi-service sockd\n"
+" would use sockd/proxy-name --socks5 proxy-name --socks5-gssapi-\n"
+" service sockd/real-name would use sockd/real-name for cases\n"
+" where the proxy-name does not match the principal name. (Added\n"
+, stdout);
+ fputs(
+" in 7.19.4).\n"
+"\n"
+" --socks5-gssapi-nec\n"
+" As part of the GSS-API negotiation a protection mode is negoti-\n"
+" ated. RFC 1961 says in section 4.3/4.4 it should be protected,\n"
+" but the NEC reference implementation does not. The option\n"
+" --socks5-gssapi-nec allows the unprotected exchange of the pro-\n"
+" tection mode negotiation. (Added in 7.19.4).\n"
+"\n"
+" --stderr <file>\n"
+, stdout);
+ fputs(
+" Redirect all writes to stderr to the specified file instead. If\n"
+" the file name is a plain '-', it is instead written to stdout.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -t, --telnet-option <OPT=val>\n"
+" Pass options to the telnet protocol. Supported options are:\n"
+"\n"
+" TTYPE=<term> Sets the terminal type.\n"
+"\n"
+" XDISPLOC=<X display> Sets the X display location.\n"
+"\n"
+, stdout);
+ fputs(
+" NEW_ENV=<var,val> Sets an environment variable.\n"
+"\n"
+" -T, --upload-file <file>\n"
+" This transfers the specified local file to the remote URL. If\n"
+" there is no file part in the specified URL, Curl will append the\n"
+" local file name. NOTE that you must use a trailing / on the last\n"
+" directory to really prove to Curl that there is no file name or\n"
+" curl will think that your last directory name is the remote file\n"
+, stdout);
+ fputs(
+" name to use. That will most likely cause the upload operation to\n"
+" fail. If this is used on an HTTP(S) server, the PUT command will\n"
+" be used.\n"
+"\n"
+" Use the file name \"-\" (a single dash) to use stdin instead of a\n"
+" given file. Alternately, the file name \".\" (a single period)\n"
+" may be specified instead of \"-\" to use stdin in non-blocking\n"
+" mode to allow reading server output while stdin is being\n"
+, stdout);
+ fputs(
+" uploaded.\n"
+"\n"
+" You can specify one -T for each URL on the command line. Each -T\n"
+" + URL pair specifies what to upload and to where. curl also sup-\n"
+" ports \"globbing\" of the -T argument, meaning that you can upload\n"
+" multiple files to a single URL by using the same URL globbing\n"
+" style supported in the URL, like this:\n"
+"\n"
+" curl -T \"{file1,file2}\" http://www.uploadtothissite.com\n"
+"\n"
+" or even\n"
+"\n"
+, stdout);
+ fputs(
+" curl -T \"img[1-1000].png\" ftp://ftp.picturemania.com/upload/\n"
+"\n"
+" --tcp-nodelay\n"
+" Turn on the TCP_NODELAY option. See the curl_easy_setopt(3) man\n"
+" page for details about this option. (Added in 7.11.2)\n"
+"\n"
+" --tftp-blksize <value>\n"
+" (TFTP) Set TFTP BLKSIZE option (must be >512). This is the block\n"
+" size that curl will try to use when transferring data to or from\n"
+" a TFTP server. By default 512 bytes will be used.\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" (Added in 7.20.0)\n"
+"\n"
+" --tlsauthtype <authtype>\n"
+" Set TLS authentication type. Currently, the only supported\n"
+" option is \"SRP\", for TLS-SRP (RFC 5054). If --tlsuser and\n"
+" --tlspassword are specified but --tlsauthtype is not, then this\n"
+" option defaults to \"SRP\". (Added in 7.21.4)\n"
+"\n"
+" --tlspassword <password>\n"
+, stdout);
+ fputs(
+" Set password for use with the TLS authentication method speci-\n"
+" fied with --tlsauthtype. Requires that --tlsuser also be set.\n"
+" (Added in 7.21.4)\n"
+"\n"
+" --tlsuser <user>\n"
+" Set username for use with the TLS authentication method speci-\n"
+" fied with --tlsauthtype. Requires that --tlspassword also be\n"
+" set. (Added in 7.21.4)\n"
+"\n"
+" --tlsv1.0\n"
+, stdout);
+ fputs(
+" (SSL) Forces curl to use TLS version 1.0 when negotiating with a\n"
+" remote TLS server. (Added in 7.34.0)\n"
+"\n"
+" --tlsv1.1\n"
+" (SSL) Forces curl to use TLS version 1.1 when negotiating with a\n"
+" remote TLS server. (Added in 7.34.0)\n"
+"\n"
+" --tlsv1.2\n"
+" (SSL) Forces curl to use TLS version 1.2 when negotiating with a\n"
+" remote TLS server. (Added in 7.34.0)\n"
+"\n"
+" --tr-encoding\n"
+, stdout);
+ fputs(
+" (HTTP) Request a compressed Transfer-Encoding response using one\n"
+" of the algorithms curl supports, and uncompress the data while\n"
+" receiving it.\n"
+"\n"
+" (Added in 7.21.6)\n"
+"\n"
+" --trace <file>\n"
+" Enables a full trace dump of all incoming and outgoing data,\n"
+" including descriptive information, to the given output file. Use\n"
+" \"-\" as filename to have the output sent to stdout.\n"
+"\n"
+, stdout);
+ fputs(
+" This option overrides previous uses of -v, --verbose or --trace-\n"
+" ascii.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --trace-ascii <file>\n"
+" Enables a full trace dump of all incoming and outgoing data,\n"
+" including descriptive information, to the given output file. Use\n"
+" \"-\" as filename to have the output sent to stdout.\n"
+"\n"
+, stdout);
+ fputs(
+" This is very similar to --trace, but leaves out the hex part and\n"
+" only shows the ASCII part of the dump. It makes smaller output\n"
+" that might be easier to read for untrained humans.\n"
+"\n"
+" This option overrides previous uses of -v, --verbose or --trace.\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --trace-time\n"
+" Prepends a time stamp to each trace or verbose line that curl\n"
+, stdout);
+ fputs(
+" displays. (Added in 7.14.0)\n"
+"\n"
+" -u, --user <user:password>\n"
+" Specify the user name and password to use for server authentica-\n"
+" tion. Overrides -n, --netrc and --netrc-optional.\n"
+"\n"
+" If you simply specify the user name, curl will prompt for a\n"
+" password.\n"
+"\n"
+" The user name and passwords are split up on the first colon,\n"
+" which makes it impossible to use a colon in the user name with\n"
+, stdout);
+ fputs(
+" this option. The password can, still.\n"
+"\n"
+" When using Kerberos V5 with a Windows based server you should\n"
+" include the Windows domain name in the user name, in order for\n"
+" the server to succesfully obtain a Kerberos Ticket. If you don't\n"
+" then the initial authentication handshake may fail.\n"
+"\n"
+" When using NTLM, the user name can be specified simply as the\n"
+, stdout);
+ fputs(
+" user name, without the domain, if there is a single domain and\n"
+" forest in your setup for example.\n"
+"\n"
+" To specify the domain name use either Down-Level Logon Name or\n"
+" UPN (User Principal Name) formats. For example, EXAMPLE\\user and\n"
+" user@example.com respectively.\n"
+"\n"
+" If you use a Windows SSPI-enabled curl binary and perform Ker-\n"
+" beros V5, Negotiate or NTLM authentication then you can tell\n"
+, stdout);
+ fputs(
+" curl to select the user name and password from your environment\n"
+" by specifying a single colon with this option: \"-u :\".\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -U, --proxy-user <user:password>\n"
+" Specify the user name and password to use for proxy authentica-\n"
+" tion.\n"
+"\n"
+" If you use a Windows SSPI-enabled curl binary and do either\n"
+, stdout);
+ fputs(
+" Negotiate or NTLM authentication then you can tell curl to\n"
+" select the user name and password from your environment by spec-\n"
+" ifying a single colon with this option: \"-U :\".\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --url <URL>\n"
+" Specify a URL to fetch. This option is mostly handy when you\n"
+" want to specify URL(s) in a config file.\n"
+"\n"
+, stdout);
+ fputs(
+" This option may be used any number of times. To control where\n"
+" this URL is written, use the -o, --output or the -O, --remote-\n"
+" name options.\n"
+" -v, --verbose\n"
+" Makes the fetching more verbose/talkative. Mostly useful for\n"
+" debugging. A line starting with '>' means \"header data\" sent by\n"
+" curl, '<' means \"header data\" received by curl that is hidden in\n"
+, stdout);
+ fputs(
+" normal cases, and a line starting with '*' means additional info\n"
+" provided by curl.\n"
+"\n"
+" Note that if you only want HTTP headers in the output, -i,\n"
+" --include might be the option you're looking for.\n"
+"\n"
+" If you think this option still doesn't give you enough details,\n"
+" consider using --trace or --trace-ascii instead.\n"
+"\n"
+" This option overrides previous uses of --trace-ascii or --trace.\n"
+"\n"
+, stdout);
+ fputs(
+" Use -s, --silent to make curl quiet.\n"
+"\n"
+" -w, --write-out <format>\n"
+" Defines what to display on stdout after a completed and success-\n"
+" ful operation. The format is a string that may contain plain\n"
+" text mixed with any number of variables. The string can be spec-\n"
+" ified as \"string\", to get read from a particular file you spec-\n"
+" ify it \"@filename\" and to tell curl to read the format from\n"
+, stdout);
+ fputs(
+" stdin you write \"@-\".\n"
+"\n"
+" The variables present in the output format will be substituted\n"
+" by the value or text that curl thinks fit, as described below.\n"
+" All variables are specified as %{variable_name} and to output a\n"
+" normal % you just write them as %%. You can output a newline by\n"
+" using \\n, a carriage return with \\r and a tab space with \\t.\n"
+"\n"
+, stdout);
+ fputs(
+" NOTE: The %-symbol is a special symbol in the win32-environment,\n"
+" where all occurrences of % must be doubled when using this\n"
+" option.\n"
+"\n"
+" The variables available are:\n"
+"\n"
+" content_type The Content-Type of the requested document, if\n"
+" there was any.\n"
+"\n"
+" filename_effective\n"
+" The ultimate filename that curl writes out to.\n"
+, stdout);
+ fputs(
+" This is only meaningful if curl is told to write\n"
+" to a file with the --remote-name or --output\n"
+" option. It's most useful in combination with the\n"
+" --remote-header-name option. (Added in 7.25.1)\n"
+"\n"
+" ftp_entry_path The initial path curl ended up in when logging on\n"
+" to the remote FTP server. (Added in 7.15.4)\n"
+"\n"
+, stdout);
+ fputs(
+" http_code The numerical response code that was found in the\n"
+" last retrieved HTTP(S) or FTP(s) transfer. In\n"
+" 7.18.2 the alias response_code was added to show\n"
+" the same info.\n"
+"\n"
+" http_connect The numerical code that was found in the last\n"
+" response (from a proxy) to a curl CONNECT\n"
+" request. (Added in 7.12.4)\n"
+"\n"
+, stdout);
+ fputs(
+" local_ip The IP address of the local end of the most\n"
+" recently done connection - can be either IPv4 or\n"
+" IPv6 (Added in 7.29.0)\n"
+"\n"
+" local_port The local port number of the most recently done\n"
+" connection (Added in 7.29.0)\n"
+"\n"
+" num_connects Number of new connects made in the recent trans-\n"
+" fer. (Added in 7.12.3)\n"
+"\n"
+, stdout);
+ fputs(
+" num_redirects Number of redirects that were followed in the\n"
+" request. (Added in 7.12.3)\n"
+"\n"
+" redirect_url When an HTTP request was made without -L to fol-\n"
+" low redirects, this variable will show the actual\n"
+" URL a redirect would take you to. (Added in\n"
+" 7.18.2)\n"
+"\n"
+" remote_ip The remote IP address of the most recently done\n"
+, stdout);
+ fputs(
+" connection - can be either IPv4 or IPv6 (Added in\n"
+" 7.29.0)\n"
+"\n"
+" remote_port The remote port number of the most recently done\n"
+" connection (Added in 7.29.0)\n"
+"\n"
+" size_download The total amount of bytes that were downloaded.\n"
+"\n"
+" size_header The total amount of bytes of the downloaded head-\n"
+" ers.\n"
+"\n"
+, stdout);
+ fputs(
+" size_request The total amount of bytes that were sent in the\n"
+" HTTP request.\n"
+"\n"
+" size_upload The total amount of bytes that were uploaded.\n"
+"\n"
+" speed_download The average download speed that curl measured for\n"
+" the complete download. Bytes per second.\n"
+"\n"
+" speed_upload The average upload speed that curl measured for\n"
+" the complete upload. Bytes per second.\n"
+"\n"
+, stdout);
+ fputs(
+" ssl_verify_result\n"
+" The result of the SSL peer certificate verifica-\n"
+" tion that was requested. 0 means the verification\n"
+" was successful. (Added in 7.19.0)\n"
+"\n"
+" time_appconnect\n"
+" The time, in seconds, it took from the start\n"
+" until the SSL/SSH/etc connect/handshake to the\n"
+, stdout);
+ fputs(
+" remote host was completed. (Added in 7.19.0)\n"
+"\n"
+" time_connect The time, in seconds, it took from the start\n"
+" until the TCP connect to the remote host (or\n"
+" proxy) was completed.\n"
+"\n"
+" time_namelookup\n"
+" The time, in seconds, it took from the start\n"
+" until the name resolving was completed.\n"
+"\n"
+" time_pretransfer\n"
+, stdout);
+ fputs(
+" The time, in seconds, it took from the start\n"
+" until the file transfer was just about to begin.\n"
+" This includes all pre-transfer commands and nego-\n"
+" tiations that are specific to the particular pro-\n"
+" tocol(s) involved.\n"
+"\n"
+" time_redirect The time, in seconds, it took for all redirection\n"
+, stdout);
+ fputs(
+" steps include name lookup, connect, pretransfer\n"
+" and transfer before the final transaction was\n"
+" started. time_redirect shows the complete execu-\n"
+" tion time for multiple redirections. (Added in\n"
+" 7.12.3)\n"
+"\n"
+" time_starttransfer\n"
+" The time, in seconds, it took from the start\n"
+, stdout);
+ fputs(
+" until the first byte was just about to be trans-\n"
+" ferred. This includes time_pretransfer and also\n"
+" the time the server needed to calculate the\n"
+" result.\n"
+"\n"
+" time_total The total time, in seconds, that the full opera-\n"
+" tion lasted. The time will be displayed with mil-\n"
+" lisecond resolution.\n"
+"\n"
+, stdout);
+ fputs(
+" url_effective The URL that was fetched last. This is most mean-\n"
+" ingful if you've told curl to follow location:\n"
+" headers.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -x, --proxy <[protocol://][user:password@]proxyhost[:port]>\n"
+" Use the specified proxy.\n"
+"\n"
+" The proxy string can be specified with a protocol:// prefix to\n"
+, stdout);
+ fputs(
+" specify alternative proxy protocols. Use socks4://, socks4a://,\n"
+" socks5:// or socks5h:// to request the specific SOCKS version to\n"
+" be used. No protocol specified, http:// and all others will be\n"
+" treated as HTTP proxies. (The protocol support was added in curl\n"
+" 7.21.7)\n"
+"\n"
+" If the port number is not specified in the proxy string, it is\n"
+" assumed to be 1080.\n"
+"\n"
+, stdout);
+ fputs(
+" This option overrides existing environment variables that set\n"
+" the proxy to use. If there's an environment variable setting a\n"
+" proxy, you can set proxy to \"\" to override it.\n"
+"\n"
+" All operations that are performed over an HTTP proxy will trans-\n"
+" parently be converted to HTTP. It means that certain protocol\n"
+" specific operations might not be available. This is not the case\n"
+, stdout);
+ fputs(
+" if you can tunnel through the proxy, as one with the -p, --prox-\n"
+" ytunnel option.\n"
+"\n"
+" User and password that might be provided in the proxy string are\n"
+" URL decoded by curl. This allows you to pass in special charac-\n"
+" ters such as @ by using %40 or pass in a colon with %3a.\n"
+"\n"
+" The proxy host can be specified the exact same way as the proxy\n"
+" environment variables, including the protocol prefix (http://)\n"
+, stdout);
+ fputs(
+" and the embedded user + password.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -X, --request <command>\n"
+" (HTTP) Specifies a custom request method to use when communicat-\n"
+" ing with the HTTP server. The specified request will be used\n"
+" instead of the method otherwise used (which defaults to GET).\n"
+" Read the HTTP 1.1 specification for details and explanations.\n"
+, stdout);
+ fputs(
+" Common additional HTTP requests include PUT and DELETE, but\n"
+" related technologies like WebDAV offers PROPFIND, COPY, MOVE and\n"
+" more.\n"
+"\n"
+" Normally you don't need this option. All sorts of GET, HEAD,\n"
+" POST and PUT requests are rather invoked by using dedicated com-\n"
+" mand line options.\n"
+"\n"
+" This option only changes the actual word used in the HTTP\n"
+, stdout);
+ fputs(
+" request, it does not alter the way curl behaves. So for example\n"
+" if you want to make a proper HEAD request, using -X HEAD will\n"
+" not suffice. You need to use the -I, --head option.\n"
+"\n"
+" (FTP) Specifies a custom FTP command to use instead of LIST when\n"
+" doing file lists with FTP.\n"
+"\n"
+" (POP3) Specifies a custom POP3 command to use instead of LIST or\n"
+" RETR. (Added in 7.26.0)\n"
+"\n"
+, stdout);
+ fputs(
+" (IMAP) Specifies a custom IMAP command to use instead of LIST.\n"
+" (Added in 7.30.0)\n"
+"\n"
+" (SMTP) Specifies a custom SMTP command to use instead of HELP or\n"
+" VRFY. (Added in 7.34.0)\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" --xattr\n"
+" When saving output to a file, this option tells curl to store\n"
+" certain file metadata in extended file attributes. Currently,\n"
+, stdout);
+ fputs(
+" the URL is stored in the xdg.origin.url attribute and, for HTTP,\n"
+" the content type is stored in the mime_type attribute. If the\n"
+" file system does not support extended attributes, a warning is\n"
+" issued.\n"
+"\n"
+" -y, --speed-time <time>\n"
+" If a download is slower than speed-limit bytes per second during\n"
+" a speed-time period, the download gets aborted. If speed-time is\n"
+, stdout);
+ fputs(
+" used, the default speed-limit will be 1 unless set with -Y.\n"
+"\n"
+" This option controls transfers and thus will not affect slow\n"
+" connects etc. If this is a concern for you, try the --connect-\n"
+" timeout option.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -Y, --speed-limit <speed>\n"
+" If a download is slower than this given speed (in bytes per sec-\n"
+, stdout);
+ fputs(
+" ond) for speed-time seconds it gets aborted. speed-time is set\n"
+" with -y and is 30 if not set.\n"
+"\n"
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -z, --time-cond <date expression>|<file>\n"
+" (HTTP/FTP) Request a file that has been modified later than the\n"
+" given time and date, or one that has been modified before that\n"
+" time. The <date expression> can be all sorts of date strings or\n"
+, stdout);
+ fputs(
+" if it doesn't match any internal ones, it is taken as a filename\n"
+" and tries to get the modification date (mtime) from <file>\n"
+" instead. See the curl_getdate(3) man pages for date expression\n"
+" details.\n"
+"\n"
+" Start the date expression with a dash (-) to make it request for\n"
+" a document that is older than the given date/time, default is a\n"
+" document that is newer than the specified date/time.\n"
+"\n"
+, stdout);
+ fputs(
+" If this option is used several times, the last one will be used.\n"
+"\n"
+" -h, --help\n"
+" Usage help.\n"
+"\n"
+" -M, --manual\n"
+" Manual. Display the huge help text.\n"
+"\n"
+" -V, --version\n"
+" Displays information about curl and the libcurl version it uses.\n"
+" The first line includes the full version of curl, libcurl and\n"
+" other 3rd party libraries linked with the executable.\n"
+"\n"
+, stdout);
+ fputs(
+" The second line (starts with \"Protocols:\") shows all protocols\n"
+" that libcurl reports to support.\n"
+"\n"
+" The third line (starts with \"Features:\") shows specific features\n"
+" libcurl reports to offer. Available features include:\n"
+"\n"
+" IPv6 You can use IPv6 with this.\n"
+"\n"
+" krb4 Krb4 for FTP is supported.\n"
+"\n"
+" SSL HTTPS and FTPS are supported.\n"
+"\n"
+, stdout);
+ fputs(
+" libz Automatic decompression of compressed files over HTTP is\n"
+" supported.\n"
+"\n"
+" NTLM NTLM authentication is supported.\n"
+"\n"
+" Debug This curl uses a libcurl built with Debug. This enables\n"
+" more error-tracking and memory debugging etc. For curl-\n"
+" developers only!\n"
+"\n"
+" AsynchDNS\n"
+" This curl uses asynchronous name resolves.\n"
+, stdout);
+ fputs(
+" SPNEGO SPNEGO authentication is supported.\n"
+"\n"
+" Largefile\n"
+" This curl supports transfers of large files, files larger\n"
+" than 2GB.\n"
+"\n"
+" IDN This curl supports IDN - international domain names.\n"
+"\n"
+" GSS-API\n"
+" GSS-API is supported.\n"
+"\n"
+" SSPI SSPI is supported.\n"
+"\n"
+" TLS-SRP\n"
+" SRP (Secure Remote Password) authentication is supported\n"
+, stdout);
+ fputs(
+" for TLS.\n"
+" Metalink\n"
+" This curl supports Metalink (both version 3 and 4 (RFC\n"
+" 5854)), which describes mirrors and hashes. curl will\n"
+" use mirrors for failover if there are errors (such as the\n"
+" file or server not being available).\n"
+"\n"
+"FILES\n"
+" ~/.curlrc\n"
+" Default config file, see -K, --config for details.\n"
+"\n"
+"ENVIRONMENT\n"
+, stdout);
+ fputs(
+" The environment variables can be specified in lower case or upper case.\n"
+" The lower case version has precedence. http_proxy is an exception as it\n"
+" is only available in lower case.\n"
+"\n"
+" Using an environment variable to set the proxy has the same effect as\n"
+" using the --proxy option.\n"
+"\n"
+" http_proxy [protocol://]<host>[:port]\n"
+" Sets the proxy server to use for HTTP.\n"
+" HTTPS_PROXY [protocol://]<host>[:port]\n"
+, stdout);
+ fputs(
+" Sets the proxy server to use for HTTPS.\n"
+"\n"
+" [url-protocol]_PROXY [protocol://]<host>[:port]\n"
+" Sets the proxy server to use for [url-protocol], where the pro-\n"
+" tocol is a protocol that curl supports and as specified in a\n"
+" URL. FTP, FTPS, POP3, IMAP, SMTP, LDAP etc.\n"
+"\n"
+" ALL_PROXY [protocol://]<host>[:port]\n"
+" Sets the proxy server to use if no protocol-specific proxy is\n"
+" set.\n"
+"\n"
+, stdout);
+ fputs(
+" NO_PROXY <comma-separated list of hosts>\n"
+" list of host names that shouldn't go through any proxy. If set\n"
+" to a asterisk '*' only, it matches all hosts.\n"
+"\n"
+"PROXY PROTOCOL PREFIXES\n"
+" Since curl version 7.21.7, the proxy string may be specified with a\n"
+" protocol:// prefix to specify alternative proxy protocols.\n"
+"\n"
+" If no protocol is specified in the proxy string or if the string\n"
+, stdout);
+ fputs(
+" doesn't match a supported one, the proxy will be treated as an HTTP\n"
+" proxy.\n"
+"\n"
+" The supported proxy protocol prefixes are as follows:\n"
+"\n"
+" socks4://\n"
+" Makes it the equivalent of --socks4\n"
+"\n"
+" socks4a://\n"
+" Makes it the equivalent of --socks4a\n"
+"\n"
+" socks5://\n"
+" Makes it the equivalent of --socks5\n"
+"\n"
+" socks5h://\n"
+" Makes it the equivalent of --socks5-hostname\n"
+"\n"
+"EXIT CODES\n"
+, stdout);
+ fputs(
+" There are a bunch of different error codes and their corresponding\n"
+" error messages that may appear during bad conditions. At the time of\n"
+" this writing, the exit codes are:\n"
+"\n"
+" 1 Unsupported protocol. This build of curl has no support for this\n"
+" protocol.\n"
+"\n"
+" 2 Failed to initialize.\n"
+"\n"
+" 3 URL malformed. The syntax was not correct.\n"
+"\n"
+" 4 A feature or option that was needed to perform the desired\n"
+, stdout);
+ fputs(
+" request was not enabled or was explicitly disabled at build-\n"
+" time. To make curl able to do this, you probably need another\n"
+" build of libcurl!\n"
+"\n"
+" 5 Couldn't resolve proxy. The given proxy host could not be\n"
+" resolved.\n"
+"\n"
+" 6 Couldn't resolve host. The given remote host was not resolved.\n"
+"\n"
+" 7 Failed to connect to host.\n"
+"\n"
+" 8 FTP weird server reply. The server sent data curl couldn't\n"
+, stdout);
+ fputs(
+" parse.\n"
+"\n"
+" 9 FTP access denied. The server denied login or denied access to\n"
+" the particular resource or directory you wanted to reach. Most\n"
+" often you tried to change to a directory that doesn't exist on\n"
+" the server.\n"
+"\n"
+" 11 FTP weird PASS reply. Curl couldn't parse the reply sent to the\n"
+" PASS request.\n"
+"\n"
+" 13 FTP weird PASV reply, Curl couldn't parse the reply sent to the\n"
+, stdout);
+ fputs(
+" PASV request.\n"
+"\n"
+" 14 FTP weird 227 format. Curl couldn't parse the 227-line the\n"
+" server sent.\n"
+"\n"
+" 15 FTP can't get host. Couldn't resolve the host IP we got in the\n"
+" 227-line.\n"
+"\n"
+" 17 FTP couldn't set binary. Couldn't change transfer method to\n"
+" binary.\n"
+"\n"
+" 18 Partial file. Only a part of the file was transferred.\n"
+"\n"
+" 19 FTP couldn't download/access the given file, the RETR (or simi-\n"
+, stdout);
+ fputs(
+" lar) command failed.\n"
+"\n"
+" 21 FTP quote error. A quote command returned error from the server.\n"
+" 22 HTTP page not retrieved. The requested url was not found or\n"
+" returned another error with the HTTP error code being 400 or\n"
+" above. This return code only appears if -f, --fail is used.\n"
+"\n"
+" 23 Write error. Curl couldn't write data to a local filesystem or\n"
+" similar.\n"
+"\n"
+, stdout);
+ fputs(
+" 25 FTP couldn't STOR file. The server denied the STOR operation,\n"
+" used for FTP uploading.\n"
+"\n"
+" 26 Read error. Various reading problems.\n"
+"\n"
+" 27 Out of memory. A memory allocation request failed.\n"
+"\n"
+" 28 Operation timeout. The specified time-out period was reached\n"
+" according to the conditions.\n"
+"\n"
+" 30 FTP PORT failed. The PORT command failed. Not all FTP servers\n"
+, stdout);
+ fputs(
+" support the PORT command, try doing a transfer using PASV\n"
+" instead!\n"
+"\n"
+" 31 FTP couldn't use REST. The REST command failed. This command is\n"
+" used for resumed FTP transfers.\n"
+"\n"
+" 33 HTTP range error. The range \"command\" didn't work.\n"
+"\n"
+" 34 HTTP post error. Internal post-request generation error.\n"
+"\n"
+" 35 SSL connect error. The SSL handshaking failed.\n"
+"\n"
+, stdout);
+ fputs(
+" 36 FTP bad download resume. Couldn't continue an earlier aborted\n"
+" download.\n"
+"\n"
+" 37 FILE couldn't read file. Failed to open the file. Permissions?\n"
+"\n"
+" 38 LDAP cannot bind. LDAP bind operation failed.\n"
+"\n"
+" 39 LDAP search failed.\n"
+"\n"
+" 41 Function not found. A required LDAP function was not found.\n"
+"\n"
+" 42 Aborted by callback. An application told curl to abort the oper-\n"
+" ation.\n"
+"\n"
+, stdout);
+ fputs(
+" 43 Internal error. A function was called with a bad parameter.\n"
+"\n"
+" 45 Interface error. A specified outgoing interface could not be\n"
+" used.\n"
+"\n"
+" 47 Too many redirects. When following redirects, curl hit the maxi-\n"
+" mum amount.\n"
+"\n"
+" 48 Unknown option specified to libcurl. This indicates that you\n"
+" passed a weird option to curl that was passed on to libcurl and\n"
+" rejected. Read up in the manual!\n"
+"\n"
+, stdout);
+ fputs(
+" 49 Malformed telnet option.\n"
+"\n"
+" 51 The peer's SSL certificate or SSH MD5 fingerprint was not OK.\n"
+"\n"
+" 52 The server didn't reply anything, which here is considered an\n"
+" error.\n"
+"\n"
+" 53 SSL crypto engine not found.\n"
+"\n"
+" 54 Cannot set SSL crypto engine as default.\n"
+"\n"
+" 55 Failed sending network data.\n"
+"\n"
+" 56 Failure in receiving network data.\n"
+"\n"
+" 58 Problem with the local certificate.\n"
+"\n"
+, stdout);
+ fputs(
+" 59 Couldn't use specified SSL cipher.\n"
+"\n"
+" 60 Peer certificate cannot be authenticated with known CA certifi-\n"
+" cates.\n"
+"\n"
+" 61 Unrecognized transfer encoding.\n"
+"\n"
+" 62 Invalid LDAP URL.\n"
+"\n"
+" 63 Maximum file size exceeded.\n"
+"\n"
+" 64 Requested FTP SSL level failed.\n"
+"\n"
+" 65 Sending the data requires a rewind that failed.\n"
+"\n"
+" 66 Failed to initialise SSL Engine.\n"
+"\n"
+, stdout);
+ fputs(
+" 67 The user name, password, or similar was not accepted and curl\n"
+" failed to log in.\n"
+"\n"
+" 68 File not found on TFTP server.\n"
+"\n"
+" 69 Permission problem on TFTP server.\n"
+"\n"
+" 70 Out of disk space on TFTP server.\n"
+"\n"
+" 71 Illegal TFTP operation.\n"
+"\n"
+" 72 Unknown TFTP transfer ID.\n"
+"\n"
+" 73 File already exists (TFTP).\n"
+"\n"
+" 74 No such user (TFTP).\n"
+"\n"
+" 75 Character conversion failed.\n"
+"\n"
+, stdout);
+ fputs(
+" 76 Character conversion functions required.\n"
+"\n"
+" 77 Problem with reading the SSL CA cert (path? access rights?).\n"
+"\n"
+" 78 The resource referenced in the URL does not exist.\n"
+"\n"
+" 79 An unspecified error occurred during the SSH session.\n"
+"\n"
+" 80 Failed to shut down the SSL connection.\n"
+"\n"
+" 82 Could not load CRL file, missing or wrong format (added in\n"
+" 7.19.0).\n"
+"\n"
+" 83 Issuer check failed (added in 7.19.0).\n"
+"\n"
+, stdout);
+ fputs(
+" 84 The FTP PRET command failed\n"
+"\n"
+" 85 RTSP: mismatch of CSeq numbers\n"
+"\n"
+" 86 RTSP: mismatch of Session Identifiers\n"
+"\n"
+" 87 unable to parse FTP file list\n"
+"\n"
+" 88 FTP chunk callback reported error\n"
+"\n"
+" 89 No connection available, the session will be queued\n"
+"\n"
+" XX More error codes will appear here in future releases. The exist-\n"
+" ing ones are meant to never change.\n"
+"\n"
+"AUTHORS / CONTRIBUTORS\n"
+, stdout);
+ fputs(
+" Daniel Stenberg is the main author, but the whole list of contributors\n"
+" is found in the separate THANKS file.\n"
+"\n"
+"WWW\n"
+" http://curl.haxx.se\n"
+"\n"
+"FTP\n"
+" ftp://ftp.sunet.se/pub/www/utilities/curl/\n"
+"\n"
+"SEE ALSO\n"
+" ftp(1), wget(1)\n"
+"\n"
+"LATEST VERSION\n"
+"\n"
+" You always find news about what's going on as well as the latest versions\n"
+" from the curl web pages, located at:\n"
+"\n"
+" http://curl.haxx.se\n"
+"\n"
+"SIMPLE USAGE\n"
+"\n"
+" Get the main page from Netscape's web-server:\n"
+"\n"
+, stdout);
+ fputs(
+" curl http://www.netscape.com/\n"
+"\n"
+" Get the README file the user's home directory at funet's ftp-server:\n"
+"\n"
+" curl ftp://ftp.funet.fi/README\n"
+"\n"
+" Get a web page from a server using port 8000:\n"
+"\n"
+" curl http://www.weirdserver.com:8000/\n"
+"\n"
+" Get a directory listing of an FTP site:\n"
+"\n"
+" curl ftp://cool.haxx.se/\n"
+"\n"
+" Get the definition of curl from a dictionary:\n"
+"\n"
+" curl dict://dict.org/m:curl\n"
+"\n"
+" Fetch two documents at once:\n"
+"\n"
+, stdout);
+ fputs(
+" curl ftp://cool.haxx.se/ http://www.weirdserver.com:8000/\n"
+"\n"
+" Get a file off an FTPS server:\n"
+"\n"
+" curl ftps://files.are.secure.com/secrets.txt\n"
+"\n"
+" or use the more appropriate FTPS way to get the same file:\n"
+"\n"
+" curl --ftp-ssl ftp://files.are.secure.com/secrets.txt\n"
+"\n"
+" Get a file from an SSH server using SFTP:\n"
+"\n"
+" curl -u username sftp://shell.example.com/etc/issue\n"
+"\n"
+" Get a file from an SSH server using SCP using a private key to authenticate:\n"
+"\n"
+, stdout);
+ fputs(
+" curl -u username: --key ~/.ssh/id_dsa --pubkey ~/.ssh/id_dsa.pub \\\n"
+" scp://shell.example.com/~/personal.txt\n"
+"\n"
+" Get the main page from an IPv6 web server:\n"
+"\n"
+" curl \"http://[2001:1890:1112:1::20]/\"\n"
+"\n"
+"DOWNLOAD TO A FILE\n"
+"\n"
+" Get a web page and store in a local file with a specific name:\n"
+"\n"
+" curl -o thatpage.html http://www.netscape.com/\n"
+"\n"
+" Get a web page and store in a local file, make the local file get the name\n"
+, stdout);
+ fputs(
+" of the remote document (if no file name part is specified in the URL, this\n"
+" will fail):\n"
+"\n"
+" curl -O http://www.netscape.com/index.html\n"
+"\n"
+" Fetch two files and store them with their remote names:\n"
+"\n"
+" curl -O www.haxx.se/index.html -O curl.haxx.se/download.html\n"
+"\n"
+"USING PASSWORDS\n"
+"\n"
+" FTP\n"
+"\n"
+" To ftp files using name+passwd, include them in the URL like:\n"
+"\n"
+" curl ftp://name:passwd@machine.domain:port/full/path/to/file\n"
+"\n"
+" or specify them with the -u flag like\n"
+"\n"
+, stdout);
+ fputs(
+" curl -u name:passwd ftp://machine.domain:port/full/path/to/file\n"
+"\n"
+" FTPS\n"
+"\n"
+" It is just like for FTP, but you may also want to specify and use\n"
+" SSL-specific options for certificates etc.\n"
+"\n"
+" Note that using FTPS:// as prefix is the \"implicit\" way as described in the\n"
+" standards while the recommended \"explicit\" way is done by using FTP:// and\n"
+" the --ftp-ssl option.\n"
+"\n"
+" SFTP / SCP\n"
+"\n"
+" This is similar to FTP, but you can specify a private key to use instead of\n"
+, stdout);
+ fputs(
+" a password. Note that the private key may itself be protected by a password\n"
+" that is unrelated to the login password of the remote system. If you\n"
+" provide a private key file you must also provide a public key file.\n"
+"\n"
+" HTTP\n"
+"\n"
+" Curl also supports user and password in HTTP URLs, thus you can pick a file\n"
+" like:\n"
+"\n"
+" curl http://name:passwd@machine.domain/full/path/to/file\n"
+"\n"
+" or specify user and password separately like in\n"
+"\n"
+, stdout);
+ fputs(
+" curl -u name:passwd http://machine.domain/full/path/to/file\n"
+"\n"
+" HTTP offers many different methods of authentication and curl supports\n"
+" several: Basic, Digest, NTLM and Negotiate (SPNEGO). Without telling which\n"
+" method to use, curl defaults to Basic. You can also ask curl to pick the\n"
+" most secure ones out of the ones that the server accepts for the given URL,\n"
+" by using --anyauth.\n"
+"\n"
+" NOTE! According to the URL specification, HTTP URLs can not contain a user\n"
+, stdout);
+ fputs(
+" and password, so that style will not work when using curl via a proxy, even\n"
+" though curl allows it at other times. When using a proxy, you _must_ use\n"
+" the -u style for user and password.\n"
+"\n"
+" HTTPS\n"
+"\n"
+" Probably most commonly used with private certificates, as explained below.\n"
+"\n"
+"PROXY\n"
+"\n"
+" curl supports both HTTP and SOCKS proxy servers, with optional authentication.\n"
+" It does not have special support for FTP proxy servers since there are no\n"
+, stdout);
+ fputs(
+" standards for those, but it can still be made to work with many of them. You\n"
+" can also use both HTTP and SOCKS proxies to transfer files to and from FTP\n"
+" servers.\n"
+"\n"
+" Get an ftp file using an HTTP proxy named my-proxy that uses port 888:\n"
+"\n"
+" curl -x my-proxy:888 ftp://ftp.leachsite.com/README\n"
+"\n"
+" Get a file from an HTTP server that requires user and password, using the\n"
+" same proxy as above:\n"
+"\n"
+" curl -u user:passwd -x my-proxy:888 http://www.get.this/\n"
+"\n"
+, stdout);
+ fputs(
+" Some proxies require special authentication. Specify by using -U as above:\n"
+"\n"
+" curl -U user:passwd -x my-proxy:888 http://www.get.this/\n"
+"\n"
+" A comma-separated list of hosts and domains which do not use the proxy can\n"
+" be specified as:\n"
+"\n"
+" curl --noproxy localhost,get.this -x my-proxy:888 http://www.get.this/\n"
+"\n"
+" If the proxy is specified with --proxy1.0 instead of --proxy or -x, then\n"
+" curl will use HTTP/1.0 instead of HTTP/1.1 for any CONNECT attempts.\n"
+"\n"
+, stdout);
+ fputs(
+" curl also supports SOCKS4 and SOCKS5 proxies with --socks4 and --socks5.\n"
+"\n"
+" See also the environment variables Curl supports that offer further proxy\n"
+" control.\n"
+"\n"
+" Most FTP proxy servers are set up to appear as a normal FTP server from the\n"
+" client's perspective, with special commands to select the remote FTP server.\n"
+" curl supports the -u, -Q and --ftp-account options that can be used to\n"
+" set up transfers through many FTP proxies. For example, a file can be\n"
+, stdout);
+ fputs(
+" uploaded to a remote FTP server using a Blue Coat FTP proxy with the\n"
+" options:\n"
+"\n"
+" curl -u \"Remote-FTP-Username@remote.ftp.server Proxy-Username:Remote-Pass\" \\\n"
+" --ftp-account Proxy-Password --upload-file local-file \\\n"
+" ftp://my-ftp.proxy.server:21/remote/upload/path/\n"
+"\n"
+" See the manual for your FTP proxy to determine the form it expects to set up\n"
+" transfers, and curl's -v option to see exactly what curl is sending.\n"
+"\n"
+"RANGES\n"
+"\n"
+" HTTP 1.1 introduced byte-ranges. Using this, a client can request\n"
+, stdout);
+ fputs(
+" to get only one or more subparts of a specified document. Curl supports\n"
+" this with the -r flag.\n"
+"\n"
+" Get the first 100 bytes of a document:\n"
+"\n"
+" curl -r 0-99 http://www.get.this/\n"
+"\n"
+" Get the last 500 bytes of a document:\n"
+"\n"
+" curl -r -500 http://www.get.this/\n"
+"\n"
+" Curl also supports simple ranges for FTP files as well. Then you can only\n"
+" specify start and stop position.\n"
+"\n"
+" Get the first 100 bytes of a document using FTP:\n"
+"\n"
+" curl -r 0-99 ftp://www.get.this/README\n"
+"\n"
+"UPLOADING\n"
+"\n"
+, stdout);
+ fputs(
+" FTP / FTPS / SFTP / SCP\n"
+"\n"
+" Upload all data on stdin to a specified server:\n"
+"\n"
+" curl -T - ftp://ftp.upload.com/myfile\n"
+"\n"
+" Upload data from a specified file, login with user and password:\n"
+"\n"
+" curl -T uploadfile -u user:passwd ftp://ftp.upload.com/myfile\n"
+"\n"
+" Upload a local file to the remote site, and use the local file name at the remote\n"
+" site too:\n"
+"\n"
+" curl -T uploadfile -u user:passwd ftp://ftp.upload.com/\n"
+"\n"
+" Upload a local file to get appended to the remote file:\n"
+"\n"
+, stdout);
+ fputs(
+" curl -T localfile -a ftp://ftp.upload.com/remotefile\n"
+"\n"
+" Curl also supports ftp upload through a proxy, but only if the proxy is\n"
+" configured to allow that kind of tunneling. If it does, you can run curl in\n"
+" a fashion similar to:\n"
+"\n"
+" curl --proxytunnel -x proxy:port -T localfile ftp.upload.com\n"
+"\n"
+" HTTP\n"
+"\n"
+" Upload all data on stdin to a specified HTTP site:\n"
+"\n"
+" curl -T - http://www.upload.com/myfile\n"
+"\n"
+" Note that the HTTP server must have been configured to accept PUT before\n"
+, stdout);
+ fputs(
+" this can be done successfully.\n"
+"\n"
+" For other ways to do HTTP data upload, see the POST section below.\n"
+"\n"
+"VERBOSE / DEBUG\n"
+"\n"
+" If curl fails where it isn't supposed to, if the servers don't let you in,\n"
+" if you can't understand the responses: use the -v flag to get verbose\n"
+" fetching. Curl will output lots of info and what it sends and receives in\n"
+" order to let the user see all client-server interaction (but it won't show\n"
+" you the actual data).\n"
+"\n"
+" curl -v ftp://ftp.upload.com/\n"
+"\n"
+, stdout);
+ fputs(
+" To get even more details and information on what curl does, try using the\n"
+" --trace or --trace-ascii options with a given file name to log to, like\n"
+" this:\n"
+"\n"
+" curl --trace trace.txt www.haxx.se\n"
+"\n"
+"\n"
+"DETAILED INFORMATION\n"
+"\n"
+" Different protocols provide different ways of getting detailed information\n"
+" about specific files/documents. To get curl to show detailed information\n"
+" about a single file, you should use -I/--head option. It displays all\n"
+, stdout);
+ fputs(
+" available info on a single file for HTTP and FTP. The HTTP information is a\n"
+" lot more extensive.\n"
+"\n"
+" For HTTP, you can get the header information (the same as -I would show)\n"
+" shown before the data by using -i/--include. Curl understands the\n"
+" -D/--dump-header option when getting files from both FTP and HTTP, and it\n"
+" will then store the headers in the specified file.\n"
+"\n"
+" Store the HTTP headers in a separate file (headers.txt in the example):\n"
+"\n"
+, stdout);
+ fputs(
+" curl --dump-header headers.txt curl.haxx.se\n"
+"\n"
+" Note that headers stored in a separate file can be very useful at a later\n"
+" time if you want curl to use cookies sent by the server. More about that in\n"
+" the cookies section.\n"
+"\n"
+"POST (HTTP)\n"
+"\n"
+" It's easy to post data using curl. This is done using the -d <data>\n"
+" option. The post data must be urlencoded.\n"
+"\n"
+" Post a simple \"name\" and \"phone\" guestbook.\n"
+"\n"
+" curl -d \"name=Rafael%20Sagula&phone=3320780\" \\\n"
+, stdout);
+ fputs(
+" http://www.where.com/guest.cgi\n"
+"\n"
+" How to post a form with curl, lesson #1:\n"
+"\n"
+" Dig out all the <input> tags in the form that you want to fill in. (There's\n"
+" a perl program called formfind.pl on the curl site that helps with this).\n"
+"\n"
+" If there's a \"normal\" post, you use -d to post. -d takes a full \"post\n"
+" string\", which is in the format\n"
+"\n"
+" <variable1>=<data1>&<variable2>=<data2>&...\n"
+"\n"
+" The 'variable' names are the names set with \"name=\" in the <input> tags, and\n"
+, stdout);
+ fputs(
+" the data is the contents you want to fill in for the inputs. The data *must*\n"
+" be properly URL encoded. That means you replace space with + and that you\n"
+" replace weird letters with %XX where XX is the hexadecimal representation of\n"
+" the letter's ASCII code.\n"
+"\n"
+" Example:\n"
+"\n"
+" (page located at http://www.formpost.com/getthis/\n"
+"\n"
+" <form action=\"post.cgi\" method=\"post\">\n"
+" <input name=user size=10>\n"
+" <input name=pass type=password size=10>\n"
+, stdout);
+ fputs(
+" <input name=id type=hidden value=\"blablabla\">\n"
+" <input name=ding value=\"submit\">\n"
+" </form>\n"
+"\n"
+" We want to enter user 'foobar' with password '12345'.\n"
+"\n"
+" To post to this, you enter a curl command line like:\n"
+"\n"
+" curl -d \"user=foobar&pass=12345&id=blablabla&ding=submit\" (continues)\n"
+" http://www.formpost.com/getthis/post.cgi\n"
+"\n"
+"\n"
+" While -d uses the application/x-www-form-urlencoded mime-type, generally\n"
+, stdout);
+ fputs(
+" understood by CGI's and similar, curl also supports the more capable\n"
+" multipart/form-data type. This latter type supports things like file upload.\n"
+"\n"
+" -F accepts parameters like -F \"name=contents\". If you want the contents to\n"
+" be read from a file, use <@filename> as contents. When specifying a file,\n"
+" you can also specify the file content type by appending ';type=<mime type>'\n"
+" to the file name. You can also post the contents of several files in one\n"
+, stdout);
+ fputs(
+" field. For example, the field name 'coolfiles' is used to send three files,\n"
+" with different content types using the following syntax:\n"
+"\n"
+" curl -F \"coolfiles=@fil1.gif;type=image/gif,fil2.txt,fil3.html\" \\\n"
+" http://www.post.com/postit.cgi\n"
+"\n"
+" If the content-type is not specified, curl will try to guess from the file\n"
+" extension (it only knows a few), or use the previously specified type (from\n"
+" an earlier file if several files are specified in a list) or else it will\n"
+, stdout);
+ fputs(
+" use the default type 'application/octet-stream'.\n"
+"\n"
+" Emulate a fill-in form with -F. Let's say you fill in three fields in a\n"
+" form. One field is a file name which to post, one field is your name and one\n"
+" field is a file description. We want to post the file we have written named\n"
+" \"cooltext.txt\". To let curl do the posting of this data instead of your\n"
+" favourite browser, you have to read the HTML source of the form page and\n"
+, stdout);
+ fputs(
+" find the names of the input fields. In our example, the input field names\n"
+" are 'file', 'yourname' and 'filedescription'.\n"
+"\n"
+" curl -F \"file=@cooltext.txt\" -F \"yourname=Daniel\" \\\n"
+" -F \"filedescription=Cool text file with cool text inside\" \\\n"
+" http://www.post.com/postit.cgi\n"
+"\n"
+" To send two files in one post you can do it in two ways:\n"
+"\n"
+" 1. Send multiple files in a single \"field\" with a single field name:\n"
+"\n"
+" curl -F \"pictures=@dog.gif,cat.gif\"\n"
+"\n"
+, stdout);
+ fputs(
+" 2. Send two fields with two field names:\n"
+"\n"
+" curl -F \"docpicture=@dog.gif\" -F \"catpicture=@cat.gif\"\n"
+"\n"
+" To send a field value literally without interpreting a leading '@'\n"
+" or '<', or an embedded ';type=', use --form-string instead of\n"
+" -F. This is recommended when the value is obtained from a user or\n"
+" some other unpredictable source. Under these circumstances, using\n"
+" -F instead of --form-string would allow a user to trick curl into\n"
+" uploading a file.\n"
+"\n"
+"REFERRER\n"
+"\n"
+, stdout);
+ fputs(
+" An HTTP request has the option to include information about which address\n"
+" referred it to the actual page. Curl allows you to specify the\n"
+" referrer to be used on the command line. It is especially useful to\n"
+" fool or trick stupid servers or CGI scripts that rely on that information\n"
+" being available or contain certain data.\n"
+"\n"
+" curl -e www.coolsite.com http://www.showme.com/\n"
+"\n"
+" NOTE: The Referer: [sic] field is defined in the HTTP spec to be a full URL.\n"
+"\n"
+"USER AGENT\n"
+"\n"
+, stdout);
+ fputs(
+" An HTTP request has the option to include information about the browser\n"
+" that generated the request. Curl allows it to be specified on the command\n"
+" line. It is especially useful to fool or trick stupid servers or CGI\n"
+" scripts that only accept certain browsers.\n"
+"\n"
+" Example:\n"
+"\n"
+" curl -A 'Mozilla/3.0 (Win95; I)' http://www.nationsbank.com/\n"
+"\n"
+" Other common strings:\n"
+" 'Mozilla/3.0 (Win95; I)' Netscape Version 3 for Windows 95\n"
+, stdout);
+ fputs(
+" 'Mozilla/3.04 (Win95; U)' Netscape Version 3 for Windows 95\n"
+" 'Mozilla/2.02 (OS/2; U)' Netscape Version 2 for OS/2\n"
+" 'Mozilla/4.04 [en] (X11; U; AIX 4.2; Nav)' NS for AIX\n"
+" 'Mozilla/4.05 [en] (X11; U; Linux 2.0.32 i586)' NS for Linux\n"
+"\n"
+" Note that Internet Explorer tries hard to be compatible in every way:\n"
+" 'Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)' MSIE for W95\n"
+"\n"
+" Mozilla is not the only possible User-Agent name:\n"
+, stdout);
+ fputs(
+" 'Konqueror/1.0' KDE File Manager desktop client\n"
+" 'Lynx/2.7.1 libwww-FM/2.14' Lynx command line browser\n"
+"\n"
+"COOKIES\n"
+"\n"
+" Cookies are generally used by web servers to keep state information at the\n"
+" client's side. The server sets cookies by sending a response line in the\n"
+" headers that looks like 'Set-Cookie: <data>' where the data part then\n"
+" typically contains a set of NAME=VALUE pairs (separated by semicolons ';'\n"
+, stdout);
+ fputs(
+" like \"NAME1=VALUE1; NAME2=VALUE2;\"). The server can also specify for what\n"
+" path the \"cookie\" should be used for (by specifying \"path=value\"), when the\n"
+" cookie should expire (\"expire=DATE\"), for what domain to use it\n"
+" (\"domain=NAME\") and if it should be used on secure connections only\n"
+" (\"secure\").\n"
+"\n"
+" If you've received a page from a server that contains a header like:\n"
+" Set-Cookie: sessionid=boo123; path=\"/foo\";\n"
+"\n"
+, stdout);
+ fputs(
+" it means the server wants that first pair passed on when we get anything in\n"
+" a path beginning with \"/foo\".\n"
+"\n"
+" Example, get a page that wants my name passed in a cookie:\n"
+"\n"
+" curl -b \"name=Daniel\" www.sillypage.com\n"
+"\n"
+" Curl also has the ability to use previously received cookies in following\n"
+" sessions. If you get cookies from a server and store them in a file in a\n"
+" manner similar to:\n"
+"\n"
+" curl --dump-header headers www.example.com\n"
+"\n"
+, stdout);
+ fputs(
+" ... you can then in a second connect to that (or another) site, use the\n"
+" cookies from the 'headers' file like:\n"
+"\n"
+" curl -b headers www.example.com\n"
+"\n"
+" While saving headers to a file is a working way to store cookies, it is\n"
+" however error-prone and not the preferred way to do this. Instead, make curl\n"
+" save the incoming cookies using the well-known netscape cookie format like\n"
+" this:\n"
+"\n"
+" curl -c cookies.txt www.example.com\n"
+"\n"
+, stdout);
+ fputs(
+" Note that by specifying -b you enable the \"cookie awareness\" and with -L\n"
+" you can make curl follow a location: (which often is used in combination\n"
+" with cookies). So that if a site sends cookies and a location, you can\n"
+" use a non-existing file to trigger the cookie awareness like:\n"
+"\n"
+" curl -L -b empty.txt www.example.com\n"
+"\n"
+" The file to read cookies from must be formatted using plain HTTP headers OR\n"
+" as netscape's cookie file. Curl will determine what kind it is based on the\n"
+, stdout);
+ fputs(
+" file contents. In the above command, curl will parse the header and store\n"
+" the cookies received from www.example.com. curl will send to the server the\n"
+" stored cookies which match the request as it follows the location. The\n"
+" file \"empty.txt\" may be a nonexistent file.\n"
+"\n"
+" Alas, to both read and write cookies from a netscape cookie file, you can\n"
+" set both -b and -c to use the same file:\n"
+"\n"
+" curl -b cookies.txt -c cookies.txt www.example.com\n"
+"\n"
+"PROGRESS METER\n"
+"\n"
+, stdout);
+ fputs(
+" The progress meter exists to show a user that something actually is\n"
+" happening. The different fields in the output have the following meaning:\n"
+"\n"
+" % Total % Received % Xferd Average Speed Time Curr.\n"
+" Dload Upload Total Current Left Speed\n"
+" 0 151M 0 38608 0 0 9406 0 4:41:43 0:00:04 4:41:39 9287\n"
+"\n"
+" From left-to-right:\n"
+" % - percentage completed of the whole transfer\n"
+, stdout);
+ fputs(
+" Total - total size of the whole expected transfer\n"
+" % - percentage completed of the download\n"
+" Received - currently downloaded amount of bytes\n"
+" % - percentage completed of the upload\n"
+" Xferd - currently uploaded amount of bytes\n"
+" Average Speed\n"
+" Dload - the average transfer speed of the download\n"
+" Average Speed\n"
+" Upload - the average transfer speed of the upload\n"
+" Time Total - expected time to complete the operation\n"
+, stdout);
+ fputs(
+" Time Current - time passed since the invoke\n"
+" Time Left - expected time left to completion\n"
+" Curr.Speed - the average transfer speed the last 5 seconds (the first\n"
+" 5 seconds of a transfer is based on less time of course.)\n"
+"\n"
+" The -# option will display a totally different progress bar that doesn't\n"
+" need much explanation!\n"
+"\n"
+"SPEED LIMIT\n"
+"\n"
+" Curl allows the user to set the transfer speed conditions that must be met\n"
+, stdout);
+ fputs(
+" to let the transfer keep going. By using the switch -y and -Y you\n"
+" can make curl abort transfers if the transfer speed is below the specified\n"
+" lowest limit for a specified time.\n"
+"\n"
+" To have curl abort the download if the speed is slower than 3000 bytes per\n"
+" second for 1 minute, run:\n"
+"\n"
+" curl -Y 3000 -y 60 www.far-away-site.com\n"
+"\n"
+" This can very well be used in combination with the overall time limit, so\n"
+" that the above operation must be completed in whole within 30 minutes:\n"
+"\n"
+, stdout);
+ fputs(
+" curl -m 1800 -Y 3000 -y 60 www.far-away-site.com\n"
+"\n"
+" Forcing curl not to transfer data faster than a given rate is also possible,\n"
+" which might be useful if you're using a limited bandwidth connection and you\n"
+" don't want your transfer to use all of it (sometimes referred to as\n"
+" \"bandwidth throttle\").\n"
+"\n"
+" Make curl transfer data no faster than 10 kilobytes per second:\n"
+"\n"
+" curl --limit-rate 10K www.far-away-site.com\n"
+"\n"
+" or\n"
+"\n"
+" curl --limit-rate 10240 www.far-away-site.com\n"
+"\n"
+, stdout);
+ fputs(
+" Or prevent curl from uploading data faster than 1 megabyte per second:\n"
+"\n"
+" curl -T upload --limit-rate 1M ftp://uploadshereplease.com\n"
+"\n"
+" When using the --limit-rate option, the transfer rate is regulated on a\n"
+" per-second basis, which will cause the total transfer speed to become lower\n"
+" than the given number. Sometimes of course substantially lower, if your\n"
+" transfer stalls during periods.\n"
+"\n"
+"CONFIG FILE\n"
+"\n"
+" Curl automatically tries to read the .curlrc file (or _curlrc file on win32\n"
+, stdout);
+ fputs(
+" systems) from the user's home dir on startup.\n"
+"\n"
+" The config file could be made up with normal command line switches, but you\n"
+" can also specify the long options without the dashes to make it more\n"
+" readable. You can separate the options and the parameter with spaces, or\n"
+" with = or :. Comments can be used within the file. If the first letter on a\n"
+" line is a '#'-symbol the rest of the line is treated as a comment.\n"
+"\n"
+" If you want the parameter to contain spaces, you must enclose the entire\n"
+, stdout);
+ fputs(
+" parameter within double quotes (\"). Within those quotes, you specify a\n"
+" quote as \\\".\n"
+"\n"
+" NOTE: You must specify options and their arguments on the same line.\n"
+"\n"
+" Example, set default time out and proxy in a config file:\n"
+"\n"
+" # We want a 30 minute timeout:\n"
+" -m 1800\n"
+" # ... and we use a proxy for all accesses:\n"
+" proxy = proxy.our.domain.com:8080\n"
+"\n"
+" White spaces ARE significant at the end of lines, but all white spaces\n"
+, stdout);
+ fputs(
+" leading up to the first characters of each line are ignored.\n"
+"\n"
+" Prevent curl from reading the default file by using -q as the first command\n"
+" line parameter, like:\n"
+"\n"
+" curl -q www.thatsite.com\n"
+"\n"
+" Force curl to get and display a local help page in case it is invoked\n"
+" without URL by making a config file similar to:\n"
+"\n"
+" # default url to get\n"
+" url = \"http://help.with.curl.com/curlhelp.html\"\n"
+"\n"
+" You can specify another config file to be read by using the -K/--config\n"
+, stdout);
+ fputs(
+" flag. If you set config file name to \"-\" it'll read the config from stdin,\n"
+" which can be handy if you want to hide options from being visible in process\n"
+" tables etc:\n"
+"\n"
+" echo \"user = user:passwd\" | curl -K - http://that.secret.site.com\n"
+"\n"
+"EXTRA HEADERS\n"
+"\n"
+" When using curl in your own very special programs, you may end up needing\n"
+" to pass on your own custom headers when getting a web page. You can do\n"
+" this by using the -H flag.\n"
+"\n"
+, stdout);
+ fputs(
+" Example, send the header \"X-you-and-me: yes\" to the server when getting a\n"
+" page:\n"
+"\n"
+" curl -H \"X-you-and-me: yes\" www.love.com\n"
+"\n"
+" This can also be useful in case you want curl to send a different text in a\n"
+" header than it normally does. The -H header you specify then replaces the\n"
+" header curl would normally send. If you replace an internal header with an\n"
+" empty one, you prevent that header from being sent. To prevent the Host:\n"
+" header from being used:\n"
+"\n"
+, stdout);
+ fputs(
+" curl -H \"Host:\" www.server.com\n"
+"\n"
+"FTP and PATH NAMES\n"
+"\n"
+" Do note that when getting files with the ftp:// URL, the given path is\n"
+" relative the directory you enter. To get the file 'README' from your home\n"
+" directory at your ftp site, do:\n"
+"\n"
+" curl ftp://user:passwd@my.site.com/README\n"
+"\n"
+" But if you want the README file from the root directory of that very same\n"
+" site, you need to specify the absolute file name:\n"
+"\n"
+" curl ftp://user:passwd@my.site.com//README\n"
+"\n"
+, stdout);
+ fputs(
+" (I.e with an extra slash in front of the file name.)\n"
+"\n"
+"SFTP and SCP and PATH NAMES\n"
+"\n"
+" With sftp: and scp: URLs, the path name given is the absolute name on the\n"
+" server. To access a file relative to the remote user's home directory,\n"
+" prefix the file with /~/ , such as:\n"
+"\n"
+" curl -u $USER sftp://home.example.com/~/.bashrc\n"
+"\n"
+"FTP and firewalls\n"
+"\n"
+" The FTP protocol requires one of the involved parties to open a second\n"
+, stdout);
+ fputs(
+" connection as soon as data is about to get transferred. There are two ways to\n"
+" do this.\n"
+"\n"
+" The default way for curl is to issue the PASV command which causes the\n"
+" server to open another port and await another connection performed by the\n"
+" client. This is good if the client is behind a firewall that doesn't allow\n"
+" incoming connections.\n"
+"\n"
+" curl ftp.download.com\n"
+"\n"
+" If the server, for example, is behind a firewall that doesn't allow connections\n"
+, stdout);
+ fputs(
+" on ports other than 21 (or if it just doesn't support the PASV command), the\n"
+" other way to do it is to use the PORT command and instruct the server to\n"
+" connect to the client on the given IP number and port (as parameters to the\n"
+" PORT command).\n"
+"\n"
+" The -P flag to curl supports a few different options. Your machine may have\n"
+" several IP-addresses and/or network interfaces and curl allows you to select\n"
+" which of them to use. Default address can also be used:\n"
+"\n"
+, stdout);
+ fputs(
+" curl -P - ftp.download.com\n"
+"\n"
+" Download with PORT but use the IP address of our 'le0' interface (this does\n"
+" not work on windows):\n"
+"\n"
+" curl -P le0 ftp.download.com\n"
+"\n"
+" Download with PORT but use 192.168.0.10 as our IP address to use:\n"
+"\n"
+" curl -P 192.168.0.10 ftp.download.com\n"
+"\n"
+"NETWORK INTERFACE\n"
+"\n"
+" Get a web page from a server using a specified port for the interface:\n"
+"\n"
+" curl --interface eth0:1 http://www.netscape.com/\n"
+"\n"
+" or\n"
+"\n"
+, stdout);
+ fputs(
+" curl --interface 192.168.1.10 http://www.netscape.com/\n"
+"\n"
+"HTTPS\n"
+"\n"
+" Secure HTTP requires SSL libraries to be installed and used when curl is\n"
+" built. If that is done, curl is capable of retrieving and posting documents\n"
+" using the HTTPS protocol.\n"
+"\n"
+" Example:\n"
+"\n"
+" curl https://www.secure-site.com\n"
+"\n"
+" Curl is also capable of using your personal certificates to get/post files\n"
+" from sites that require valid certificates. The only drawback is that the\n"
+, stdout);
+ fputs(
+" certificate needs to be in PEM-format. PEM is a standard and open format to\n"
+" store certificates with, but it is not used by the most commonly used\n"
+" browsers (Netscape and MSIE both use the so called PKCS#12 format). If you\n"
+" want curl to use the certificates you use with your (favourite) browser, you\n"
+" may need to download/compile a converter that can convert your browser's\n"
+" formatted certificates to PEM formatted ones. This kind of converter is\n"
+, stdout);
+ fputs(
+" included in recent versions of OpenSSL, and for older versions Dr Stephen\n"
+" N. Henson has written a patch for SSLeay that adds this functionality. You\n"
+" can get his patch (that requires an SSLeay installation) from his site at:\n"
+" http://www.drh-consultancy.demon.co.uk/\n"
+"\n"
+" Example on how to automatically retrieve a document using a certificate with\n"
+" a personal password:\n"
+"\n"
+" curl -E /path/to/cert.pem:password https://secure.site.com/\n"
+"\n"
+, stdout);
+ fputs(
+" If you neglect to specify the password on the command line, you will be\n"
+" prompted for the correct password before any data can be received.\n"
+"\n"
+" Many older SSL-servers have problems with SSLv3 or TLS, which newer versions\n"
+" of OpenSSL etc use, therefore it is sometimes useful to specify what\n"
+" SSL-version curl should use. Use -3, -2 or -1 to specify that exact SSL\n"
+" version to use (for SSLv3, SSLv2 or TLSv1 respectively):\n"
+"\n"
+" curl -2 https://secure.site.com/\n"
+"\n"
+, stdout);
+ fputs(
+" Otherwise, curl will first attempt to use v3 and then v2.\n"
+"\n"
+" To use OpenSSL to convert your favourite browser's certificate into a PEM\n"
+" formatted one that curl can use, do something like this:\n"
+"\n"
+" In Netscape, you start with hitting the 'Security' menu button.\n"
+"\n"
+" Select 'certificates->yours' and then pick a certificate in the list\n"
+"\n"
+" Press the 'Export' button\n"
+"\n"
+" enter your PIN code for the certs\n"
+"\n"
+" select a proper place to save it\n"
+"\n"
+, stdout);
+ fputs(
+" Run the 'openssl' application to convert the certificate. If you cd to the\n"
+" openssl installation, you can do it like:\n"
+"\n"
+" # ./apps/openssl pkcs12 -in [file you saved] -clcerts -out [PEMfile]\n"
+"\n"
+" In Firefox, select Options, then Advanced, then the Encryption tab,\n"
+" View Certificates. This opens the Certificate Manager, where you can\n"
+" Export. Be sure to select PEM for the Save as type.\n"
+"\n"
+" In Internet Explorer, select Internet Options, then the Content tab, then\n"
+, stdout);
+ fputs(
+" Certificates. Then you can Export, and depending on the format you may\n"
+" need to convert to PEM.\n"
+"\n"
+" In Chrome, select Settings, then Show Advanced Settings. Under HTTPS/SSL\n"
+" select Manage Certificates.\n"
+"\n"
+"RESUMING FILE TRANSFERS\n"
+"\n"
+" To continue a file transfer where it was previously aborted, curl supports\n"
+" resume on HTTP(S) downloads as well as FTP uploads and downloads.\n"
+"\n"
+" Continue downloading a document:\n"
+"\n"
+" curl -C - -o file ftp://ftp.server.com/path/file\n"
+"\n"
+, stdout);
+ fputs(
+" Continue uploading a document(*1):\n"
+"\n"
+" curl -C - -T file ftp://ftp.server.com/path/file\n"
+"\n"
+" Continue downloading a document from a web server(*2):\n"
+"\n"
+" curl -C - -o file http://www.server.com/\n"
+"\n"
+" (*1) = This requires that the FTP server supports the non-standard command\n"
+" SIZE. If it doesn't, curl will say so.\n"
+"\n"
+" (*2) = This requires that the web server supports at least HTTP/1.1. If it\n"
+" doesn't, curl will say so.\n"
+"\n"
+"TIME CONDITIONS\n"
+"\n"
+, stdout);
+ fputs(
+" HTTP allows a client to specify a time condition for the document it\n"
+" requests. It is If-Modified-Since or If-Unmodified-Since. Curl allows you to\n"
+" specify them with the -z/--time-cond flag.\n"
+"\n"
+" For example, you can easily make a download that only gets performed if the\n"
+" remote file is newer than a local copy. It would be made like:\n"
+"\n"
+" curl -z local.html http://remote.server.com/remote.html\n"
+"\n"
+" Or you can download a file only if the local file is newer than the remote\n"
+, stdout);
+ fputs(
+" one. Do this by prepending the date string with a '-', as in:\n"
+"\n"
+" curl -z -local.html http://remote.server.com/remote.html\n"
+"\n"
+" You can specify a \"free text\" date as condition. Tell curl to only download\n"
+" the file if it was updated since January 12, 2012:\n"
+"\n"
+" curl -z \"Jan 12 2012\" http://remote.server.com/remote.html\n"
+"\n"
+" Curl will then accept a wide range of date formats. You always make the date\n"
+" check the other way around by prepending it with a dash '-'.\n"
+"\n"
+"DICT\n"
+"\n"
+" For fun try\n"
+"\n"
+, stdout);
+ fputs(
+" curl dict://dict.org/m:curl\n"
+" curl dict://dict.org/d:heisenbug:jargon\n"
+" curl dict://dict.org/d:daniel:web1913\n"
+"\n"
+" Aliases for 'm' are 'match' and 'find', and aliases for 'd' are 'define'\n"
+" and 'lookup'. For example,\n"
+"\n"
+" curl dict://dict.org/find:curl\n"
+"\n"
+" Commands that break the URL description of the RFC (but not the DICT\n"
+" protocol) are\n"
+"\n"
+" curl dict://dict.org/show:db\n"
+" curl dict://dict.org/show:strat\n"
+"\n"
+, stdout);
+ fputs(
+" Authentication is still missing (but this is not required by the RFC)\n"
+"\n"
+"LDAP\n"
+"\n"
+" If you have installed the OpenLDAP library, curl can take advantage of it\n"
+" and offer ldap:// support.\n"
+"\n"
+" LDAP is a complex thing and writing an LDAP query is not an easy task. I do\n"
+" advise you to dig up the syntax description for that elsewhere. Two places\n"
+" that might suit you are:\n"
+"\n"
+" Netscape's \"Netscape Directory SDK 3.0 for C Programmer's Guide Chapter 10:\n"
+" Working with LDAP URLs\":\n"
+, stdout);
+ fputs(
+" http://developer.netscape.com/docs/manuals/dirsdk/csdk30/url.htm\n"
+"\n"
+" RFC 2255, \"The LDAP URL Format\" http://curl.haxx.se/rfc/rfc2255.txt\n"
+"\n"
+" To show you an example, this is how I can get all people from my local LDAP\n"
+" server that has a certain sub-domain in their email address:\n"
+"\n"
+" curl -B \"ldap://ldap.frontec.se/o=frontec??sub?mail=*sth.frontec.se\"\n"
+"\n"
+" If I want the same info in HTML format, I can get it by not using the -B\n"
+" (enforce ASCII) flag.\n"
+"\n"
+"ENVIRONMENT VARIABLES\n"
+"\n"
+, stdout);
+ fputs(
+" Curl reads and understands the following environment variables:\n"
+"\n"
+" http_proxy, HTTPS_PROXY, FTP_PROXY\n"
+"\n"
+" They should be set for protocol-specific proxies. General proxy should be\n"
+" set with\n"
+"\n"
+" ALL_PROXY\n"
+"\n"
+" A comma-separated list of host names that shouldn't go through any proxy is\n"
+" set in (only an asterisk, '*' matches all hosts)\n"
+"\n"
+" NO_PROXY\n"
+"\n"
+" If the host name matches one of these strings, or the host is within the\n"
+, stdout);
+ fputs(
+" domain of one of these strings, transactions with that node will not be\n"
+" proxied.\n"
+"\n"
+"\n"
+" The usage of the -x/--proxy flag overrides the environment variables.\n"
+"\n"
+"NETRC\n"
+"\n"
+" Unix introduced the .netrc concept a long time ago. It is a way for a user\n"
+" to specify name and password for commonly visited FTP sites in a file so\n"
+" that you don't have to type them in each time you visit those sites. You\n"
+" realize this is a big security risk if someone else gets hold of your\n"
+, stdout);
+ fputs(
+" passwords, so therefore most unix programs won't read this file unless it is\n"
+" only readable by yourself (curl doesn't care though).\n"
+"\n"
+" Curl supports .netrc files if told to (using the -n/--netrc and\n"
+" --netrc-optional options). This is not restricted to just FTP,\n"
+" so curl can use it for all protocols where authentication is used.\n"
+"\n"
+" A very simple .netrc file could look something like:\n"
+"\n"
+" machine curl.haxx.se login iamdaniel password mysecret\n"
+"\n"
+"CUSTOM OUTPUT\n"
+"\n"
+, stdout);
+ fputs(
+" To better allow script programmers to get to know about the progress of\n"
+" curl, the -w/--write-out option was introduced. Using this, you can specify\n"
+" what information from the previous transfer you want to extract.\n"
+"\n"
+" To display the amount of bytes downloaded together with some text and an\n"
+" ending newline:\n"
+"\n"
+" curl -w 'We downloaded %{size_download} bytes\\n' www.download.com\n"
+"\n"
+"KERBEROS FTP TRANSFER\n"
+"\n"
+" Curl supports kerberos4 and kerberos5/GSSAPI for FTP transfers. You need\n"
+, stdout);
+ fputs(
+" the kerberos package installed and used at curl build time for it to be\n"
+" available.\n"
+"\n"
+" First, get the krb-ticket the normal way, like with the kinit/kauth tool.\n"
+" Then use curl in way similar to:\n"
+"\n"
+" curl --krb private ftp://krb4site.com -u username:fakepwd\n"
+"\n"
+" There's no use for a password on the -u switch, but a blank one will make\n"
+" curl ask for one and you already entered the real password to kinit/kauth.\n"
+"\n"
+"TELNET\n"
+"\n"
+, stdout);
+ fputs(
+" The curl telnet support is basic and very easy to use. Curl passes all data\n"
+" passed to it on stdin to the remote server. Connect to a remote telnet\n"
+" server using a command line similar to:\n"
+"\n"
+" curl telnet://remote.server.com\n"
+"\n"
+" And enter the data to pass to the server on stdin. The result will be sent\n"
+" to stdout or to the file you specify with -o.\n"
+"\n"
+" You might want the -N/--no-buffer option to switch off the buffered output\n"
+" for slow connections or similar.\n"
+"\n"
+, stdout);
+ fputs(
+" Pass options to the telnet protocol negotiation, by using the -t option. To\n"
+" tell the server we use a vt100 terminal, try something like:\n"
+"\n"
+" curl -tTTYPE=vt100 telnet://remote.server.com\n"
+"\n"
+" Other interesting options for it -t include:\n"
+"\n"
+" - XDISPLOC=<X display> Sets the X display location.\n"
+"\n"
+" - NEW_ENV=<var,val> Sets an environment variable.\n"
+"\n"
+" NOTE: The telnet protocol does not specify any way to login with a specified\n"
+, stdout);
+ fputs(
+" user and password so curl can't do that automatically. To do that, you need\n"
+" to track when the login prompt is received and send the username and\n"
+" password accordingly.\n"
+"\n"
+"PERSISTENT CONNECTIONS\n"
+"\n"
+" Specifying multiple files on a single command line will make curl transfer\n"
+" all of them, one after the other in the specified order.\n"
+"\n"
+" libcurl will attempt to use persistent connections for the transfers so that\n"
+" the second transfer to the same host can use the same connection that was\n"
+, stdout);
+ fputs(
+" already initiated and was left open in the previous transfer. This greatly\n"
+" decreases connection time for all but the first transfer and it makes a far\n"
+" better use of the network.\n"
+"\n"
+" Note that curl cannot use persistent connections for transfers that are used\n"
+" in subsequence curl invokes. Try to stuff as many URLs as possible on the\n"
+" same command line if they are using the same host, as that'll make the\n"
+" transfers faster. If you use an HTTP proxy for file transfers, practically\n"
+, stdout);
+ fputs(
+" all transfers will be persistent.\n"
+"\n"
+"MULTIPLE TRANSFERS WITH A SINGLE COMMAND LINE\n"
+"\n"
+" As is mentioned above, you can download multiple files with one command line\n"
+" by simply adding more URLs. If you want those to get saved to a local file\n"
+" instead of just printed to stdout, you need to add one save option for each\n"
+" URL you specify. Note that this also goes for the -O option (but not\n"
+" --remote-name-all).\n"
+"\n"
+" For example: get two files and use -O for the first and a custom file\n"
+, stdout);
+ fputs(
+" name for the second:\n"
+"\n"
+" curl -O http://url.com/file.txt ftp://ftp.com/moo.exe -o moo.jpg\n"
+"\n"
+" You can also upload multiple files in a similar fashion:\n"
+"\n"
+" curl -T local1 ftp://ftp.com/moo.exe -T local2 ftp://ftp.com/moo2.txt\n"
+"\n"
+"IPv6\n"
+"\n"
+" curl will connect to a server with IPv6 when a host lookup returns an IPv6\n"
+" address and fall back to IPv4 if the connection fails. The --ipv4 and --ipv6\n"
+" options can specify which address to use when both are available. IPv6\n"
+, stdout);
+ fputs(
+" addresses can also be specified directly in URLs using the syntax:\n"
+"\n"
+" http://[2001:1890:1112:1::20]/overview.html\n"
+"\n"
+" When this style is used, the -g option must be given to stop curl from\n"
+" interpreting the square brackets as special globbing characters. Link local\n"
+" and site local addresses including a scope identifier, such as fe80::1234%1,\n"
+" may also be used, but the scope portion must be numeric or match an existing\n"
+, stdout);
+ fputs(
+" network interface on Linux and the percent character must be URL escaped. The\n"
+" previous example in an SFTP URL might look like:\n"
+"\n"
+" sftp://[fe80::1234%251]/\n"
+"\n"
+" IPv6 addresses provided other than in URLs (e.g. to the --proxy, --interface\n"
+" or --ftp-port options) should not be URL encoded.\n"
+"\n"
+"METALINK\n"
+"\n"
+" Curl supports Metalink (both version 3 and 4 (RFC 5854) are supported), a way\n"
+" to list multiple URIs and hashes for a file. Curl will make use of the mirrors\n"
+, stdout);
+ fputs(
+" listed within for failover if there are errors (such as the file or server not\n"
+" being available). It will also verify the hash of the file after the download\n"
+" completes. The Metalink file itself is downloaded and processed in memory and\n"
+" not stored in the local file system.\n"
+"\n"
+" Example to use a remote Metalink file:\n"
+"\n"
+" curl --metalink http://www.example.com/example.metalink\n"
+"\n"
+" To use a Metalink file in the local file system, use FILE protocol (file://):\n"
+"\n"
+, stdout);
+ fputs(
+" curl --metalink file://example.metalink\n"
+"\n"
+" Please note that if FILE protocol is disabled, there is no way to use a local\n"
+" Metalink file at the time of this writing. Also note that if --metalink and\n"
+" --include are used together, --include will be ignored. This is because including\n"
+" headers in the response will break Metalink parser and if the headers are included\n"
+" in the file described in Metalink file, hash check will fail.\n"
+"\n"
+"MAILING LISTS\n"
+"\n"
+, stdout);
+ fputs(
+" For your convenience, we have several open mailing lists to discuss curl,\n"
+" its development and things relevant to this. Get all info at\n"
+" http://curl.haxx.se/mail/. Some of the lists available are:\n"
+"\n"
+" curl-users\n"
+"\n"
+" Users of the command line tool. How to use it, what doesn't work, new\n"
+" features, related tools, questions, news, installations, compilations,\n"
+" running, porting etc.\n"
+"\n"
+" curl-library\n"
+"\n"
+" Developers using or developing libcurl. Bugs, extensions, improvements.\n"
+"\n"
+, stdout);
+ fputs(
+" curl-announce\n"
+"\n"
+" Low-traffic. Only receives announcements of new public versions. At worst,\n"
+" that makes something like one or two mails per month, but usually only one\n"
+" mail every second month.\n"
+"\n"
+" curl-and-php\n"
+"\n"
+" Using the curl functions in PHP. Everything curl with a PHP angle. Or PHP\n"
+" with a curl angle.\n"
+"\n"
+" curl-and-python\n"
+"\n"
+" Python hackers using curl with or without the python binding pycurl.\n"
+"\n"
+" Please direct curl questions, feature requests and trouble reports to one of\n"
+, stdout);
+ fputs(
+" these mailing lists instead of mailing any individual.\n"
+, stdout) ;
+}
+#else /* !USE_MANUAL */
+/* built-in manual is disabled, blank function */
+#include "tool_hugehelp.h"
+void hugehelp(void) {}
+#endif /* USE_MANUAL */
+#else
+/*
+ * NEVER EVER edit this manually, fix the mkhelp.pl script instead!
+ * Generation time: Wed Sep 10 00:40:56 2014
+ */
+#ifdef USE_MANUAL
+#include "tool_hugehelp.h"
+#include <zlib.h>
+#include "memdebug.h" /* keep this as LAST include */
+static const unsigned char hugehelpgz[] = {
+ /* This mumbo-jumbo is the huge help text compressed with gzip.
+ Thanks to this operation, the size of this data shrunk from 158943
+ to 48006 bytes. You can disable the use of compressed help
+ texts by NOT passing -c to the mkhelp.pl tool. */
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xed, 0xbd,
+ 0x6b, 0x7b, 0xe3, 0x46, 0x92, 0x2e, 0xf8, 0x5d, 0xbf, 0x02, 0xcd, 0xde,
+ 0x1e, 0x49, 0xd3, 0x24, 0x75, 0xa9, 0x8b, 0x5d, 0xea, 0x2a, 0x8f, 0x65,
+ 0x49, 0x65, 0x6b, 0xac, 0x2a, 0xe9, 0x88, 0x2a, 0xdb, 0x7d, 0x6c, 0x3f,
+ 0xf5, 0x80, 0x24, 0x24, 0xa1, 0x45, 0x02, 0x6c, 0x00, 0xd4, 0xa5, 0x67,
+ 0xe6, 0xfc, 0xf6, 0xcd, 0x78, 0x23, 0x22, 0x33, 0x81, 0x4c, 0x4a, 0x65,
+ 0x1f, 0xbb, 0x77, 0xf6, 0xec, 0x7a, 0xa6, 0x55, 0x12, 0x09, 0xe4, 0x35,
+ 0x32, 0x32, 0xae, 0x6f, 0x24, 0xc9, 0x53, 0xff, 0x7d, 0xc4, 0xff, 0x3e,
+ 0x9a, 0xff, 0xcc, 0xbf, 0x6b, 0x49, 0x72, 0x56, 0x95, 0x7f, 0xcb, 0x26,
+ 0x4d, 0xfc, 0xd9, 0x8f, 0x1f, 0xff, 0x33, 0xe1, 0xff, 0x33, 0xef, 0xfc,
+ 0x64, 0xfe, 0x5d, 0x7b, 0xb4, 0xed, 0xad, 0xc4, 0xbd, 0xf0, 0x9f, 0x1f,
+ 0x37, 0x93, 0xa7, 0x5e, 0xf8, 0xcf, 0x64, 0x03, 0x2f, 0x7c, 0x94, 0x1e,
+ 0x5e, 0xd3, 0xef, 0x1f, 0x3f, 0x3e, 0xde, 0xc9, 0x4f, 0x34, 0x2a, 0xfa,
+ 0xb1, 0x45, 0xef, 0xfd, 0xf4, 0x91, 0x7e, 0x35, 0x9f, 0xac, 0xad, 0xbd,
+ 0xdf, 0x7f, 0x77, 0xa4, 0xaf, 0x4e, 0x96, 0xd5, 0x2c, 0x19, 0x24, 0x4d,
+ 0x95, 0x16, 0xf5, 0x65, 0x56, 0x25, 0x69, 0xf2, 0xe1, 0xfc, 0x64, 0x6d,
+ 0x6d, 0xf4, 0xd7, 0xf7, 0xa7, 0x67, 0xa3, 0xe3, 0x51, 0xeb, 0xb1, 0x1f,
+ 0xcb, 0x45, 0x93, 0x97, 0x45, 0xfd, 0x73, 0xf2, 0xa3, 0x79, 0x68, 0x38,
+ 0x1c, 0xfe, 0xbc, 0xb6, 0x76, 0x78, 0x34, 0x3a, 0x38, 0x3f, 0x3e, 0xbb,
+ 0x38, 0x3e, 0x7d, 0xdf, 0x7a, 0x36, 0xc9, 0xeb, 0xc4, 0x34, 0xd6, 0x94,
+ 0xe5, 0xcc, 0xfc, 0x70, 0xed, 0x4f, 0xd3, 0x26, 0x4d, 0x2e, 0xab, 0x72,
+ 0x9e, 0x94, 0x15, 0x7d, 0x91, 0x26, 0x75, 0x56, 0xdd, 0x66, 0x55, 0x3f,
+ 0x59, 0xd6, 0x79, 0x71, 0x95, 0x94, 0x45, 0x96, 0x94, 0x97, 0x49, 0x73,
+ 0x9d, 0x69, 0x73, 0xf5, 0x72, 0xb1, 0x28, 0xab, 0x26, 0x9b, 0x26, 0x8b,
+ 0xaa, 0x6c, 0xca, 0x49, 0x39, 0xab, 0x93, 0x8d, 0xc3, 0xe3, 0x83, 0x8b,
+ 0x7e, 0xf2, 0xf6, 0xf8, 0xe4, 0xc8, 0xfc, 0xbc, 0x38, 0xc3, 0x8f, 0x51,
+ 0x3f, 0xf9, 0xfa, 0xf4, 0xec, 0x9b, 0xa3, 0xf3, 0x7e, 0xf2, 0xcd, 0x05,
+ 0x7d, 0x46, 0x3f, 0xcd, 0x87, 0xc9, 0xf1, 0xbb, 0xfd, 0xb3, 0xbe, 0x36,
+ 0x47, 0x7f, 0xd0, 0x87, 0x27, 0x87, 0xe6, 0x43, 0xfe, 0x87, 0xfe, 0x3c,
+ 0x3b, 0x3d, 0x7b, 0xd6, 0xc7, 0x4f, 0xf3, 0xd7, 0xf9, 0xc5, 0xbb, 0x33,
+ 0xfa, 0x39, 0x32, 0x3f, 0x47, 0x07, 0xf4, 0x03, 0x7d, 0x8c, 0xde, 0xe9,
+ 0xcf, 0x91, 0x6d, 0xee, 0xe2, 0xe8, 0xe4, 0xfd, 0xd1, 0x45, 0x92, 0x16,
+ 0xd3, 0xe4, 0xc2, 0x3c, 0xb4, 0x39, 0x34, 0x1f, 0x5d, 0x67, 0xc9, 0xa4,
+ 0x9c, 0xcf, 0xe9, 0x33, 0xb3, 0x0a, 0xd3, 0xac, 0xce, 0xaf, 0x0a, 0x33,
+ 0x7c, 0x33, 0xdb, 0xbb, 0xb2, 0xba, 0x49, 0xee, 0xf2, 0xe6, 0xba, 0x5c,
+ 0x36, 0x66, 0xc2, 0x66, 0x3d, 0x92, 0xbc, 0x68, 0xb2, 0x6a, 0xa0, 0xcd,
+ 0xa5, 0x13, 0x5a, 0xe1, 0xe1, 0x5a, 0x6b, 0x2d, 0xcb, 0x4b, 0xb3, 0x72,
+ 0xb5, 0x59, 0xaa, 0xf1, 0xb2, 0x9e, 0x95, 0xe9, 0x94, 0x16, 0xc8, 0xbc,
+ 0x7c, 0xb9, 0x34, 0x4b, 0x5b, 0xe5, 0x93, 0x9b, 0x3a, 0x99, 0xe5, 0x37,
+ 0x19, 0x2d, 0xcf, 0xfd, 0x83, 0x2e, 0x57, 0x9f, 0x9b, 0x4f, 0x97, 0x66,
+ 0x25, 0x0b, 0xdb, 0x7c, 0x93, 0x4f, 0x52, 0xea, 0x00, 0xeb, 0x95, 0x2c,
+ 0x17, 0xd4, 0x1a, 0xaf, 0x53, 0xb2, 0x28, 0x6b, 0xf3, 0xd2, 0x68, 0x74,
+ 0x62, 0xc6, 0x5e, 0x14, 0x19, 0xc6, 0x51, 0xf7, 0xcd, 0x1f, 0xe5, 0x4d,
+ 0x9e, 0x99, 0x5f, 0x2e, 0xf3, 0x59, 0x96, 0xf0, 0x3e, 0xda, 0xe6, 0x68,
+ 0x43, 0x93, 0x2a, 0xab, 0x97, 0xf3, 0xcc, 0x2c, 0xe1, 0xbb, 0xac, 0x49,
+ 0x67, 0x79, 0x71, 0x63, 0x7e, 0xa5, 0xa9, 0xcf, 0xcb, 0x2a, 0x1b, 0x26,
+ 0xfb, 0x75, 0xf2, 0x50, 0x2e, 0xcd, 0x9c, 0x67, 0x33, 0xb3, 0xd3, 0x59,
+ 0x32, 0xce, 0x66, 0xe5, 0x5d, 0x9f, 0xf6, 0x37, 0x29, 0x96, 0xf3, 0xb1,
+ 0x69, 0xa0, 0xbc, 0x74, 0xcd, 0xa5, 0xcd, 0xd2, 0x34, 0xc7, 0x4f, 0xcf,
+ 0x53, 0x33, 0x27, 0xf3, 0x6e, 0x95, 0x5c, 0x67, 0x66, 0xce, 0xf5, 0x22,
+ 0x2f, 0xfe, 0xd0, 0x5e, 0x17, 0xb3, 0xb8, 0x8b, 0xf2, 0x2e, 0xab, 0xcc,
+ 0xda, 0x8e, 0x1f, 0x12, 0xb3, 0x08, 0x63, 0x26, 0xbd, 0x4b, 0x43, 0x5a,
+ 0x49, 0x6a, 0x9a, 0xb0, 0x64, 0x37, 0xa8, 0xb2, 0x59, 0x4a, 0x24, 0x64,
+ 0xfb, 0x30, 0xfb, 0x34, 0xca, 0x2c, 0x8d, 0xc9, 0xab, 0x1b, 0xcf, 0x36,
+ 0xf1, 0xf2, 0xd4, 0xcc, 0x24, 0x9f, 0xd5, 0x66, 0x1b, 0xe8, 0x30, 0xe8,
+ 0x4e, 0x9b, 0x21, 0xd3, 0xe1, 0x30, 0x14, 0xf9, 0x50, 0x34, 0xe9, 0x3d,
+ 0xba, 0x17, 0x8a, 0x1c, 0x4c, 0xb3, 0x45, 0x56, 0x4c, 0xb3, 0xa2, 0x19,
+ 0x26, 0x7f, 0x2d, 0x97, 0xeb, 0xa6, 0xef, 0xcb, 0xdc, 0xac, 0x41, 0x2a,
+ 0x4d, 0x99, 0x9e, 0x0d, 0x19, 0x4c, 0xaa, 0x7c, 0xe1, 0x6d, 0x45, 0x59,
+ 0x98, 0xcd, 0x4f, 0xce, 0xdf, 0x1e, 0x24, 0xcf, 0x5e, 0x7d, 0xfe, 0xd2,
+ 0xed, 0xb9, 0x69, 0x20, 0x99, 0xa4, 0x85, 0x99, 0x71, 0x36, 0xc9, 0x2f,
+ 0x1f, 0x92, 0xf9, 0x72, 0xd6, 0xe4, 0x0b, 0xb3, 0xfa, 0xa6, 0xf3, 0x9a,
+ 0x8e, 0xcd, 0x22, 0xad, 0x9a, 0x9a, 0x88, 0x00, 0x1f, 0x60, 0xee, 0x77,
+ 0x55, 0xde, 0xd0, 0xf1, 0xc1, 0x77, 0x66, 0x84, 0x59, 0x53, 0x6b, 0x73,
+ 0x44, 0x6e, 0xa6, 0x9f, 0x71, 0x95, 0x4e, 0xcc, 0xd2, 0xa6, 0xb5, 0xe9,
+ 0x74, 0xcf, 0xf6, 0x95, 0x5c, 0x37, 0xcd, 0x62, 0x6f, 0x6b, 0xab, 0xce,
+ 0x9b, 0x6c, 0xf8, 0x1f, 0xe6, 0xf0, 0xf5, 0x9b, 0xbb, 0xb2, 0xdf, 0x5c,
+ 0x57, 0x59, 0xf6, 0x5f, 0x43, 0x43, 0xc4, 0xf6, 0x41, 0xd3, 0xed, 0x83,
+ 0x8c, 0xeb, 0x2a, 0x6b, 0x4c, 0x07, 0x7f, 0x5f, 0x66, 0x05, 0x35, 0x68,
+ 0x86, 0x91, 0xce, 0x16, 0xd7, 0xa9, 0xd9, 0xcd, 0xcc, 0x10, 0x23, 0x1d,
+ 0x67, 0x43, 0x2f, 0x34, 0x28, 0x3e, 0xd0, 0x3f, 0xfe, 0x1c, 0xf4, 0x79,
+ 0x89, 0x2e, 0xcd, 0xcf, 0xa1, 0xbc, 0x94, 0x9a, 0xb5, 0x36, 0x9d, 0x6d,
+ 0x11, 0x8d, 0xfd, 0xb8, 0x33, 0xd8, 0xd9, 0xde, 0xfe, 0x79, 0xd8, 0xdc,
+ 0x37, 0x9f, 0xf8, 0xc2, 0xf6, 0xb6, 0x7b, 0x85, 0x9e, 0xde, 0xa0, 0x19,
+ 0x27, 0x33, 0x43, 0x34, 0xd4, 0xff, 0x3f, 0xb2, 0xaa, 0xac, 0x37, 0x23,
+ 0x4d, 0xcd, 0xb2, 0xc6, 0x9c, 0x3c, 0xaf, 0x9d, 0x74, 0xf0, 0x0f, 0xee,
+ 0x56, 0x1f, 0x7e, 0x9f, 0xd5, 0xa0, 0x19, 0x37, 0xd9, 0x24, 0xad, 0x0c,
+ 0xdd, 0x96, 0x8d, 0x63, 0x4a, 0x7d, 0x73, 0x28, 0x1b, 0xbb, 0x34, 0xe6,
+ 0xcc, 0x99, 0xa7, 0x0d, 0x3b, 0x4b, 0x67, 0xc4, 0xc9, 0xea, 0xa4, 0xc8,
+ 0xdc, 0x34, 0xcc, 0xf9, 0xcf, 0xd2, 0xc9, 0x75, 0x52, 0x1a, 0xe2, 0xaf,
+ 0xc2, 0x2d, 0x48, 0x8b, 0x87, 0x61, 0x59, 0x5d, 0x6d, 0xa5, 0xd5, 0xe4,
+ 0x3a, 0xbf, 0x35, 0xeb, 0xf0, 0xea, 0xd5, 0xcb, 0x81, 0xf9, 0xf1, 0xea,
+ 0xe7, 0xad, 0xdb, 0x72, 0x66, 0x96, 0xe5, 0xf9, 0xcf, 0x5b, 0xb4, 0xbb,
+ 0xff, 0x91, 0xf6, 0xc7, 0xfd, 0xc9, 0x7f, 0x0d, 0xaf, 0x9b, 0xf9, 0x6c,
+ 0x25, 0xcd, 0x98, 0xc6, 0x92, 0x74, 0x5e, 0x2e, 0x8b, 0xc6, 0xd2, 0x89,
+ 0x21, 0xb7, 0xc6, 0xe3, 0x4c, 0xe6, 0xa4, 0x66, 0xcc, 0xac, 0x88, 0x7c,
+ 0xe8, 0xc0, 0x99, 0xb3, 0xe9, 0x4e, 0x62, 0x33, 0xb9, 0x36, 0x53, 0x37,
+ 0x74, 0x93, 0xca, 0xf4, 0x9b, 0x3c, 0xa5, 0x33, 0x69, 0x58, 0x43, 0x45,
+ 0x1f, 0x53, 0x53, 0xdc, 0x59, 0x6e, 0x9e, 0x2b, 0xab, 0x69, 0x56, 0xb5,
+ 0x29, 0x18, 0xc3, 0x71, 0xe3, 0x49, 0xcc, 0x52, 0x2e, 0x4c, 0xe7, 0x4b,
+ 0x62, 0x77, 0x38, 0x64, 0xd4, 0x82, 0x39, 0x9e, 0x57, 0x66, 0x95, 0xcc,
+ 0xca, 0x10, 0x51, 0xd1, 0xc2, 0x3d, 0x24, 0xef, 0xcd, 0xe6, 0x31, 0x6b,
+ 0xf0, 0x68, 0x8f, 0x37, 0x2b, 0x5c, 0xb4, 0xbb, 0xbb, 0xbb, 0xd5, 0x44,
+ 0xb4, 0xb7, 0xd3, 0xa1, 0x23, 0xef, 0xa5, 0xd8, 0xee, 0xef, 0xed, 0xb6,
+ 0xf7, 0xff, 0xf8, 0x12, 0x1b, 0xab, 0x73, 0xa0, 0xb3, 0xaf, 0xbc, 0x5b,
+ 0x0f, 0xbe, 0x69, 0xcd, 0xfc, 0x9e, 0x5d, 0xe6, 0xf7, 0x7d, 0xbd, 0xf8,
+ 0x78, 0x2d, 0x53, 0xd3, 0xfc, 0x7c, 0xd1, 0xd0, 0xae, 0x6b, 0x73, 0x57,
+ 0xcb, 0xac, 0x36, 0x24, 0x74, 0x77, 0x9d, 0x9a, 0x8f, 0xb5, 0x81, 0x04,
+ 0x5d, 0xcc, 0xf3, 0xab, 0xeb, 0x26, 0xb9, 0x4b, 0x89, 0x7f, 0x1c, 0x37,
+ 0xdc, 0x04, 0x31, 0x6e, 0xc3, 0x35, 0x2e, 0x53, 0x73, 0xfc, 0x69, 0x85,
+ 0xc0, 0xa5, 0x0d, 0xb1, 0x59, 0x72, 0x32, 0x6b, 0x05, 0x52, 0xf2, 0xee,
+ 0xc5, 0x71, 0x5a, 0xd3, 0x6e, 0x14, 0x66, 0xd3, 0x1b, 0xc3, 0xf6, 0x97,
+ 0xf4, 0xd7, 0xb5, 0x61, 0xec, 0x49, 0x91, 0xce, 0x33, 0x19, 0x28, 0x78,
+ 0xdf, 0x5b, 0x62, 0x91, 0xd9, 0x7d, 0x3a, 0xb7, 0xfc, 0xc8, 0x30, 0x98,
+ 0xbe, 0xb0, 0x4e, 0xfb, 0x46, 0x6d, 0x76, 0xcd, 0x50, 0x1c, 0x1d, 0x23,
+ 0x9c, 0xa9, 0x1e, 0x9d, 0x9b, 0x1e, 0xcf, 0x13, 0x63, 0x4c, 0x6b, 0xe2,
+ 0xfd, 0xcc, 0xe1, 0xcd, 0xe0, 0xbd, 0xc9, 0x9a, 0x45, 0x4b, 0x6f, 0xe8,
+ 0x96, 0xe9, 0xdc, 0x65, 0x78, 0x6d, 0x5a, 0x26, 0xb9, 0xe1, 0x60, 0x63,
+ 0x73, 0xbe, 0x68, 0x66, 0x74, 0x6a, 0xb0, 0x2a, 0xd4, 0xce, 0xc2, 0xb4,
+ 0x49, 0x1f, 0xe6, 0x0d, 0xf1, 0x0d, 0x88, 0x23, 0x66, 0xbc, 0x66, 0x51,
+ 0x20, 0x51, 0x98, 0xb3, 0xe7, 0xcd, 0x1f, 0x1c, 0xcf, 0x3c, 0x9b, 0xdc,
+ 0x9a, 0x8b, 0xc7, 0x48, 0x16, 0x99, 0x7d, 0x0b, 0x2c, 0x7a, 0x42, 0xd7,
+ 0xdd, 0x6c, 0xf6, 0x60, 0xc8, 0xae, 0xaa, 0x48, 0x74, 0xa3, 0x1d, 0x1c,
+ 0xf3, 0xe1, 0x98, 0x67, 0xe6, 0x66, 0xf0, 0x97, 0x33, 0x27, 0x26, 0x65,
+ 0x88, 0xd4, 0x5c, 0x35, 0x20, 0x43, 0x73, 0x25, 0xe0, 0x18, 0x63, 0xe2,
+ 0x18, 0x1d, 0xb5, 0x3d, 0x99, 0x64, 0x8b, 0xa6, 0x8e, 0xcd, 0x49, 0x37,
+ 0xdc, 0x0c, 0xa7, 0xca, 0x68, 0xe5, 0xfd, 0x7b, 0x14, 0xeb, 0x6a, 0xf9,
+ 0x38, 0xae, 0x52, 0xbd, 0x9a, 0xcc, 0xd5, 0x5a, 0xdb, 0x55, 0x6b, 0x40,
+ 0x1b, 0xe6, 0x2c, 0x60, 0xcd, 0xe7, 0x34, 0x50, 0x7a, 0xb8, 0x66, 0x89,
+ 0x09, 0x67, 0x8e, 0x36, 0x92, 0x45, 0x26, 0xee, 0x97, 0xb8, 0x91, 0x59,
+ 0x4f, 0xdb, 0xb8, 0xe9, 0xd5, 0xee, 0x29, 0x75, 0x5f, 0x1b, 0x61, 0xd3,
+ 0x70, 0xe7, 0x69, 0x7d, 0x6d, 0xee, 0x53, 0xb3, 0xf5, 0x17, 0xd7, 0x34,
+ 0xd3, 0xb9, 0xa1, 0x99, 0x5b, 0xda, 0xdf, 0x45, 0x96, 0x4d, 0x87, 0xc9,
+ 0xe9, 0x25, 0x1d, 0xcd, 0xca, 0x0c, 0xba, 0xc1, 0xd7, 0xc4, 0x2d, 0xcc,
+ 0xba, 0x4d, 0x21, 0x8d, 0x15, 0x96, 0x2b, 0x60, 0x28, 0xde, 0xb1, 0x27,
+ 0x4a, 0x33, 0x8b, 0x9d, 0x10, 0xa3, 0x9f, 0xb5, 0x59, 0x0b, 0x44, 0x00,
+ 0xc3, 0x02, 0x68, 0x78, 0xe3, 0x2c, 0x01, 0x25, 0x8e, 0xb3, 0xe6, 0x2e,
+ 0xcb, 0x6c, 0x73, 0x75, 0x66, 0xd8, 0x19, 0x6d, 0x1a, 0x5f, 0xe6, 0xc5,
+ 0x6d, 0x49, 0x03, 0x5c, 0x5b, 0x3b, 0x3b, 0x3f, 0xfd, 0xfa, 0xfc, 0x68,
+ 0x34, 0x4a, 0xde, 0x1d, 0x5d, 0x1c, 0x9d, 0xb7, 0x56, 0xba, 0x28, 0xab,
+ 0x39, 0x76, 0x74, 0x9a, 0xd7, 0x8b, 0x59, 0xfa, 0x40, 0x5b, 0x6d, 0x66,
+ 0x72, 0x55, 0xd1, 0xc9, 0x9a, 0x67, 0xc4, 0x5a, 0xa6, 0xcb, 0x0a, 0x64,
+ 0x51, 0x2e, 0xcc, 0xf6, 0x89, 0x10, 0x63, 0x1a, 0x9f, 0x42, 0xf2, 0x29,
+ 0xae, 0xdc, 0x4a, 0x9b, 0xdb, 0x5c, 0x38, 0x24, 0xb1, 0x48, 0xbb, 0x1f,
+ 0x24, 0x4d, 0x40, 0x4a, 0xed, 0xbb, 0xcf, 0x78, 0x99, 0x6a, 0xcc, 0xc9,
+ 0xd0, 0x6c, 0x3e, 0x87, 0x2c, 0x61, 0xfe, 0x75, 0x02, 0x44, 0x76, 0x69,
+ 0xa4, 0x27, 0xc3, 0x35, 0x3b, 0xa4, 0x61, 0xc7, 0x89, 0x75, 0x85, 0xf0,
+ 0x4b, 0xd2, 0xb0, 0xe9, 0xdc, 0x8c, 0x75, 0x9e, 0x17, 0x86, 0xc0, 0x0c,
+ 0x41, 0xca, 0x29, 0x27, 0x4a, 0x30, 0x63, 0xbd, 0x64, 0x9e, 0x20, 0x2b,
+ 0xd2, 0x96, 0xaa, 0xcd, 0xcb, 0x66, 0xb3, 0x0d, 0x67, 0xb5, 0xd3, 0xc3,
+ 0xa0, 0x0c, 0x69, 0x9a, 0xe6, 0xd3, 0x31, 0xb1, 0x26, 0x12, 0x33, 0x8d,
+ 0x34, 0x90, 0x45, 0x7b, 0xb3, 0x72, 0xab, 0x79, 0xc3, 0x8c, 0x2d, 0x1d,
+ 0xd3, 0x8e, 0xd2, 0x03, 0x9d, 0x55, 0x34, 0x87, 0x08, 0xbc, 0xe5, 0x2e,
+ 0xaf, 0x71, 0xa8, 0xee, 0xca, 0xe5, 0xcc, 0x88, 0x74, 0xf4, 0xc0, 0x72,
+ 0x81, 0x17, 0x4c, 0x57, 0x0b, 0x77, 0x7a, 0xe6, 0xf9, 0x3d, 0xad, 0x7a,
+ 0xb7, 0x15, 0x33, 0x34, 0xf3, 0xe7, 0xc2, 0x6c, 0x02, 0x0f, 0x67, 0xd8,
+ 0xe5, 0xad, 0xe0, 0x1a, 0xc1, 0x1e, 0xd2, 0x69, 0x01, 0xbb, 0x3b, 0x3b,
+ 0x1d, 0x5d, 0x10, 0xfb, 0x3f, 0xfb, 0x70, 0x61, 0x1a, 0x32, 0xd7, 0x50,
+ 0xdd, 0x98, 0xed, 0xa4, 0x17, 0x8b, 0x0c, 0x12, 0xb5, 0x36, 0x67, 0x76,
+ 0x2d, 0xc7, 0x11, 0xc7, 0xad, 0xa2, 0x5d, 0xf2, 0x18, 0x59, 0xcd, 0x20,
+ 0xe2, 0x55, 0x25, 0xa3, 0xbe, 0xce, 0x88, 0x47, 0xdb, 0x97, 0x92, 0x8d,
+ 0x2f, 0x36, 0xcd, 0x76, 0x0f, 0x6c, 0x73, 0x3f, 0xd2, 0xd3, 0x3f, 0x53,
+ 0xcf, 0x75, 0x3e, 0xcf, 0x67, 0xa9, 0x77, 0xb7, 0x09, 0x27, 0x22, 0xba,
+ 0xb6, 0xe7, 0x71, 0x62, 0xd8, 0x2e, 0x06, 0xed, 0xa4, 0x6a, 0x5a, 0x41,
+ 0x9c, 0x66, 0xb7, 0x51, 0xd3, 0x32, 0xe3, 0xf7, 0x8c, 0x28, 0x6b, 0x17,
+ 0x8e, 0x76, 0x8c, 0x8e, 0x79, 0x6b, 0x99, 0xba, 0xbb, 0x16, 0x2c, 0x1b,
+ 0x71, 0x72, 0x28, 0x6b, 0x76, 0xe1, 0x7a, 0xe3, 0xb4, 0xea, 0x59, 0x0e,
+ 0xc6, 0x1a, 0x94, 0x69, 0xf4, 0x6a, 0x69, 0x06, 0xcf, 0xab, 0xda, 0x4f,
+ 0x06, 0x7f, 0xa4, 0x91, 0x93, 0x48, 0x6d, 0x4f, 0xb4, 0x91, 0xd5, 0x8a,
+ 0xe9, 0x70, 0xed, 0x14, 0x0a, 0x9c, 0xd5, 0xf6, 0x4e, 0x59, 0xcf, 0x4b,
+ 0x98, 0xfd, 0xb3, 0x08, 0x99, 0xb0, 0x6a, 0x66, 0xee, 0xed, 0x3b, 0x43,
+ 0x83, 0xa9, 0x59, 0x42, 0xc3, 0x4c, 0xde, 0xd1, 0xd0, 0xa5, 0x33, 0x51,
+ 0x0e, 0xb1, 0x4f, 0x66, 0x59, 0xcd, 0xac, 0xac, 0x52, 0x33, 0x9d, 0xe6,
+ 0xf4, 0x9d, 0x21, 0x76, 0xc3, 0xa8, 0x97, 0x19, 0xa4, 0x22, 0x99, 0xe3,
+ 0xdc, 0xcd, 0x8d, 0x04, 0xec, 0xfa, 0xda, 0x48, 0x55, 0x49, 0x8f, 0x19,
+ 0xca, 0x80, 0xba, 0xe9, 0xd1, 0xc2, 0xce, 0x3b, 0x9d, 0x98, 0xb9, 0x4c,
+ 0xe5, 0xb2, 0xa2, 0x4b, 0x8c, 0xef, 0xae, 0x79, 0xfa, 0xe0, 0xcb, 0x30,
+ 0x60, 0x39, 0x18, 0x79, 0x59, 0xd9, 0x7b, 0xdb, 0xdc, 0x0c, 0x0b, 0x23,
+ 0x07, 0x2b, 0x2b, 0x02, 0x4f, 0xc7, 0xf9, 0xa9, 0x79, 0x68, 0x7d, 0x23,
+ 0xcc, 0xd2, 0x93, 0x57, 0xd7, 0xfa, 0xa8, 0x77, 0x3f, 0xa4, 0x66, 0x6e,
+ 0xc4, 0xe3, 0x48, 0xd2, 0x9f, 0x2a, 0xfb, 0x2a, 0xab, 0x21, 0x46, 0x3e,
+ 0x2b, 0x89, 0xeb, 0xf4, 0xa6, 0xe5, 0x72, 0x6c, 0x47, 0x8e, 0xa1, 0x13,
+ 0x61, 0x0d, 0xb0, 0xab, 0xf4, 0xa7, 0x36, 0x67, 0x87, 0x2d, 0xcb, 0x55,
+ 0x3f, 0x39, 0x34, 0xb7, 0x50, 0x23, 0x2c, 0x92, 0xb9, 0x01, 0x6a, 0x22,
+ 0x2b, 0x5d, 0x77, 0x50, 0x9b, 0xe1, 0xd8, 0xeb, 0x0d, 0x1f, 0x0e, 0x88,
+ 0x80, 0x9d, 0x95, 0xaf, 0x21, 0x95, 0x09, 0x3f, 0xb6, 0x33, 0x33, 0x33,
+ 0x9a, 0xe6, 0x86, 0xa5, 0x19, 0xbe, 0xaa, 0x3b, 0xe3, 0x04, 0xd5, 0x3e,
+ 0x2b, 0x97, 0xb4, 0xd6, 0x32, 0x66, 0xe6, 0x4e, 0x2d, 0xf1, 0x8e, 0xb4,
+ 0x2d, 0x9f, 0xb3, 0xea, 0x98, 0x06, 0xa7, 0x66, 0xa7, 0x4e, 0x30, 0x8f,
+ 0xc1, 0x6d, 0x42, 0xa7, 0xc1, 0x88, 0xd1, 0x74, 0x34, 0x06, 0xa7, 0x27,
+ 0xb7, 0x1e, 0x55, 0x93, 0x52, 0x51, 0xd0, 0x75, 0xdb, 0x87, 0xde, 0x36,
+ 0x2e, 0x4b, 0x23, 0xbe, 0xbb, 0xa9, 0x91, 0xd4, 0x9d, 0x15, 0xc4, 0xac,
+ 0x64, 0x47, 0x07, 0x03, 0xfe, 0x0a, 0x2d, 0x3f, 0x18, 0xd1, 0x31, 0xbd,
+ 0x4a, 0x73, 0x4b, 0x6f, 0xc2, 0xd8, 0xec, 0xb3, 0x45, 0x29, 0x8f, 0xd3,
+ 0x4e, 0xd1, 0x45, 0x2e, 0x3c, 0x64, 0x89, 0xfb, 0x2e, 0xa3, 0x79, 0x19,
+ 0x26, 0x80, 0x93, 0x2c, 0xcd, 0x42, 0xfa, 0xd1, 0xe6, 0xc6, 0x90, 0xf7,
+ 0x48, 0x74, 0x02, 0x27, 0x84, 0x20, 0x64, 0x9a, 0xec, 0x0d, 0x93, 0x6f,
+ 0x8c, 0xf6, 0x09, 0xdb, 0x05, 0x04, 0xe2, 0x9c, 0xf4, 0x70, 0x23, 0xd1,
+ 0xdc, 0x65, 0x46, 0xf7, 0xad, 0x1b, 0xb3, 0x9a, 0xb8, 0x44, 0xf1, 0x99,
+ 0x19, 0xa7, 0xbd, 0xf6, 0xae, 0xcb, 0x3b, 0x74, 0x6b, 0x27, 0x61, 0x77,
+ 0xf2, 0x92, 0x4f, 0x44, 0xb2, 0x81, 0x4b, 0x7a, 0x42, 0x8b, 0xb5, 0x68,
+ 0xdc, 0x2c, 0xec, 0x7a, 0x18, 0xb6, 0x59, 0x7b, 0x87, 0x8b, 0x6e, 0x2c,
+ 0x33, 0x82, 0xe4, 0xb3, 0xe1, 0xce, 0xab, 0xe1, 0xf6, 0x90, 0x4c, 0x55,
+ 0xd9, 0x6d, 0x5e, 0x2e, 0x6b, 0xd3, 0x3b, 0x86, 0x92, 0x78, 0x6f, 0x1a,
+ 0x75, 0x99, 0xae, 0x91, 0xab, 0xab, 0x19, 0x5f, 0xe0, 0x5b, 0xe5, 0xe5,
+ 0xa5, 0x77, 0xc7, 0x57, 0x46, 0x91, 0xc5, 0xed, 0x46, 0x8b, 0x23, 0x87,
+ 0x8e, 0x79, 0x9c, 0x7f, 0xb9, 0xcb, 0x72, 0x6e, 0xda, 0x1d, 0x1c, 0xfc,
+ 0xd1, 0x6c, 0xf4, 0x40, 0xb9, 0xd1, 0xc0, 0x30, 0xa3, 0x8e, 0x6d, 0xea,
+ 0x1d, 0x69, 0xf3, 0xfe, 0x95, 0xe8, 0x58, 0x17, 0x0b, 0x6c, 0x39, 0x48,
+ 0xcb, 0x7e, 0x68, 0x5a, 0x48, 0x2c, 0x3b, 0xf3, 0x6c, 0x04, 0x1e, 0x91,
+ 0x19, 0xe6, 0x54, 0x4c, 0xd3, 0xca, 0xa8, 0x60, 0x64, 0x6a, 0x30, 0x0f,
+ 0xd3, 0x69, 0x4b, 0x99, 0xdc, 0xfb, 0xcc, 0xf3, 0x1c, 0x89, 0x0d, 0xf6,
+ 0x68, 0x80, 0xbe, 0x3a, 0xa6, 0x5c, 0xc7, 0x5c, 0x05, 0x35, 0x8f, 0x4c,
+ 0x44, 0xd1, 0xd4, 0x49, 0x26, 0x8e, 0x79, 0xab, 0xc6, 0x72, 0x59, 0xce,
+ 0x66, 0xe5, 0x1d, 0x5d, 0x22, 0x24, 0x4c, 0x7a, 0xdb, 0xaa, 0xdb, 0x51,
+ 0xd7, 0xe5, 0x24, 0x67, 0x5b, 0x83, 0x2c, 0x3a, 0xb4, 0x2c, 0x98, 0xc3,
+ 0xe8, 0xd5, 0x5a, 0x6e, 0x77, 0x12, 0x5b, 0x6b, 0xc3, 0x49, 0x12, 0xab,
+ 0x30, 0xc2, 0xba, 0xd0, 0x69, 0xce, 0x5d, 0x7a, 0x7c, 0x24, 0x85, 0x15,
+ 0x9b, 0x91, 0xe4, 0x66, 0x7d, 0xca, 0x3b, 0xd5, 0xf8, 0x8c, 0xe2, 0x6d,
+ 0x59, 0xa3, 0x77, 0x54, 0xfb, 0x9d, 0xe6, 0xea, 0xa5, 0x69, 0xc3, 0xac,
+ 0xf7, 0x34, 0x27, 0x93, 0x92, 0x51, 0xea, 0xd8, 0x4a, 0xc4, 0xb2, 0xbe,
+ 0x79, 0x6d, 0xb2, 0xac, 0x1b, 0x23, 0x68, 0x6a, 0xaf, 0xdc, 0x94, 0xe9,
+ 0xd7, 0x90, 0xe4, 0x3e, 0xd1, 0x59, 0xa7, 0x39, 0x43, 0x74, 0x9f, 0x0d,
+ 0x9f, 0xbd, 0x1c, 0x6e, 0x7b, 0x84, 0xb0, 0x4d, 0xeb, 0x4c, 0x8a, 0xd6,
+ 0xce, 0x70, 0xbb, 0xf3, 0xf8, 0x06, 0xdd, 0xe9, 0x9b, 0xba, 0xe4, 0xad,
+ 0x35, 0xc7, 0x6d, 0xaf, 0xe7, 0xc0, 0xbc, 0xe9, 0xdf, 0x64, 0x7c, 0x67,
+ 0xe7, 0xce, 0xa2, 0x61, 0x7b, 0x37, 0x3b, 0x5c, 0x40, 0x1c, 0xe4, 0xfb,
+ 0xd0, 0xdc, 0xe7, 0x7b, 0xdc, 0xd2, 0xce, 0x70, 0xc7, 0xdb, 0x7a, 0x19,
+ 0xce, 0x4e, 0x7c, 0x38, 0x21, 0x01, 0x74, 0x06, 0xb3, 0xa3, 0x42, 0x33,
+ 0x4b, 0x4a, 0xb6, 0xdf, 0x4e, 0x73, 0xaa, 0xaa, 0xc9, 0x8b, 0xba, 0x64,
+ 0xb2, 0x48, 0xcf, 0x5a, 0x8b, 0x84, 0x11, 0xed, 0x7e, 0xc2, 0xf2, 0x80,
+ 0x4c, 0x72, 0xa3, 0x65, 0x51, 0xbf, 0x66, 0x43, 0xdc, 0xd6, 0xf0, 0xaa,
+ 0x60, 0xa8, 0xbb, 0x3c, 0xc0, 0x08, 0xe9, 0xe0, 0x62, 0xc1, 0xc5, 0x40,
+ 0x23, 0x5f, 0x9a, 0x7b, 0xab, 0x9a, 0x41, 0x6b, 0x52, 0x5b, 0x99, 0x61,
+ 0x24, 0x86, 0xbf, 0xe5, 0xb3, 0x46, 0x08, 0x92, 0xcd, 0x1a, 0xd4, 0xd7,
+ 0xb0, 0x3b, 0xba, 0x47, 0x66, 0x63, 0xb8, 0x61, 0xb1, 0x28, 0x3a, 0x2f,
+ 0x1c, 0x32, 0x17, 0x16, 0x51, 0xfb, 0xfd, 0xd9, 0x7b, 0x33, 0xb3, 0x93,
+ 0x11, 0xdd, 0x7c, 0x46, 0x35, 0xe5, 0x15, 0xc2, 0xa7, 0x66, 0x59, 0x95,
+ 0xb7, 0x3b, 0x51, 0xd8, 0x48, 0xc1, 0x9d, 0xe6, 0xc2, 0x11, 0xe3, 0x28,
+ 0x98, 0x5b, 0x82, 0x6c, 0x96, 0xe6, 0xdb, 0x2a, 0x35, 0x5a, 0x1b, 0xe6,
+ 0x2a, 0xb3, 0xa8, 0xa9, 0xf9, 0x21, 0xf7, 0x1c, 0xac, 0x0e, 0xa4, 0x03,
+ 0x28, 0x83, 0xb6, 0xe5, 0xf6, 0xbb, 0xbc, 0xb2, 0xb4, 0x2a, 0x45, 0x76,
+ 0x55, 0x36, 0x74, 0xa4, 0xf5, 0x33, 0xf3, 0xcc, 0xa0, 0xd3, 0x1c, 0x56,
+ 0x0d, 0x03, 0x02, 0x67, 0x62, 0xfd, 0x4c, 0x54, 0x11, 0xda, 0x6b, 0xa3,
+ 0x69, 0x19, 0xae, 0x06, 0x6e, 0xb0, 0xf6, 0xd8, 0xc2, 0xbe, 0x0c, 0x16,
+ 0x36, 0x9d, 0xad, 0x5c, 0x59, 0xea, 0x6a, 0xff, 0xc4, 0x4c, 0x8f, 0xd6,
+ 0xd5, 0x5b, 0x56, 0x7c, 0xe6, 0x2d, 0x2b, 0x2c, 0x84, 0xba, 0xb0, 0xab,
+ 0x57, 0x16, 0x4b, 0xfb, 0xc9, 0x6b, 0x4b, 0x9d, 0x70, 0x57, 0xdd, 0x63,
+ 0x59, 0x8b, 0xb6, 0xf7, 0x29, 0x6b, 0xeb, 0x2d, 0x2e, 0x7f, 0x9a, 0xec,
+ 0x06, 0x2c, 0x6b, 0xf1, 0xfb, 0x2c, 0xee, 0x0e, 0x31, 0xaa, 0x66, 0x56,
+ 0xdf, 0x06, 0x7c, 0xc1, 0x4c, 0x7a, 0x93, 0x2c, 0x24, 0x64, 0xf1, 0xf3,
+ 0xf9, 0x02, 0x2d, 0xb3, 0x63, 0x0b, 0xf7, 0xc9, 0x1d, 0x59, 0x68, 0x74,
+ 0x02, 0xd6, 0x48, 0x92, 0x06, 0xe7, 0x70, 0x5e, 0x36, 0xfc, 0x32, 0x0f,
+ 0x7d, 0xe8, 0xcc, 0x75, 0xd4, 0xaa, 0xbb, 0x9b, 0x65, 0x38, 0xc3, 0xed,
+ 0xbe, 0xfb, 0x7d, 0xa7, 0xcb, 0xc2, 0xe9, 0x0e, 0xb6, 0xdf, 0x62, 0x0d,
+ 0x8d, 0x9c, 0xd0, 0x54, 0x25, 0x0c, 0x46, 0xad, 0x21, 0xe2, 0x56, 0x34,
+ 0x9c, 0x71, 0x62, 0x74, 0x38, 0xc3, 0x23, 0x37, 0xf2, 0x96, 0x5b, 0x45,
+ 0x65, 0x49, 0xb3, 0xc1, 0xe3, 0x74, 0x72, 0x43, 0x37, 0x51, 0x2e, 0x06,
+ 0x4c, 0xdd, 0x26, 0xbe, 0x2d, 0x8c, 0x6e, 0x7b, 0x9b, 0x91, 0x13, 0x42,
+ 0x3b, 0xda, 0xf4, 0x58, 0xeb, 0x2e, 0x2d, 0x62, 0x5d, 0xcf, 0x6e, 0x77,
+ 0x3f, 0x75, 0x11, 0xa9, 0x43, 0x1d, 0xe1, 0x6e, 0xb8, 0x84, 0x72, 0xc1,
+ 0xad, 0x58, 0x44, 0x7a, 0x59, 0x16, 0xd1, 0x8d, 0xe1, 0x99, 0x8e, 0xe1,
+ 0x59, 0x74, 0x0c, 0x3a, 0x88, 0x95, 0xa3, 0x78, 0xf6, 0xcb, 0x36, 0x32,
+ 0x3a, 0x86, 0xe7, 0x34, 0x86, 0x7c, 0x71, 0xfb, 0xbc, 0xf3, 0x8e, 0xd1,
+ 0xd7, 0xd4, 0x55, 0x31, 0x49, 0x17, 0x38, 0xb5, 0x66, 0x21, 0x0d, 0x57,
+ 0x2e, 0x67, 0xb7, 0xd4, 0x91, 0xa1, 0x01, 0x23, 0xc0, 0x41, 0xe2, 0x69,
+ 0x3c, 0x23, 0x4e, 0x72, 0x6c, 0x4e, 0xc2, 0xad, 0xe7, 0x17, 0xd2, 0xc3,
+ 0xc0, 0x84, 0xb2, 0x71, 0x77, 0x9d, 0x93, 0x30, 0x90, 0x8b, 0x55, 0xcc,
+ 0xec, 0x2c, 0x5b, 0x00, 0x8e, 0xcf, 0x6e, 0x5f, 0x0e, 0xa4, 0xa3, 0xcd,
+ 0x3e, 0xcb, 0xa4, 0x22, 0x64, 0x36, 0x74, 0xab, 0x74, 0x9a, 0xd3, 0x15,
+ 0xe1, 0xf1, 0x64, 0x22, 0x07, 0x98, 0x0f, 0x4c, 0x3b, 0xcf, 0x75, 0x60,
+ 0x19, 0x1b, 0x83, 0xbc, 0xc9, 0xbe, 0x94, 0xc9, 0xbe, 0xfc, 0x3f, 0x66,
+ 0xb2, 0x2f, 0x57, 0x4f, 0x36, 0xa5, 0xc9, 0xa6, 0x0b, 0x72, 0xef, 0x74,
+ 0xc9, 0xcb, 0x68, 0xfb, 0x5b, 0xe4, 0x19, 0xdc, 0x4c, 0xbe, 0x27, 0x02,
+ 0x02, 0xd7, 0x23, 0x8b, 0x79, 0x61, 0x3d, 0x6b, 0x18, 0x13, 0x5b, 0x73,
+ 0xc9, 0xe2, 0xa0, 0x43, 0x88, 0x36, 0x47, 0xdc, 0x10, 0x57, 0xa5, 0xd1,
+ 0xb9, 0xc9, 0x1a, 0x2e, 0x1e, 0x37, 0x4f, 0x06, 0x36, 0xff, 0x33, 0xcb,
+ 0x64, 0x5d, 0x3d, 0x39, 0x19, 0x8b, 0x59, 0x42, 0xa7, 0x47, 0xbb, 0xe2,
+ 0x48, 0x99, 0xd5, 0xa4, 0x0b, 0x66, 0xf7, 0x39, 0x39, 0xf6, 0x72, 0xb1,
+ 0x2a, 0x1b, 0xdd, 0x2f, 0x99, 0x54, 0x10, 0xf1, 0x87, 0xe4, 0xe2, 0x20,
+ 0x8a, 0x16, 0xb3, 0x23, 0x06, 0x9b, 0x5c, 0xce, 0xd2, 0xab, 0xc8, 0x7d,
+ 0x99, 0x5f, 0x15, 0xa5, 0x38, 0xda, 0xea, 0x72, 0x4e, 0xa7, 0xe0, 0x1b,
+ 0x39, 0x05, 0xb5, 0xe1, 0x2c, 0xc5, 0x64, 0xb6, 0x84, 0xb7, 0xe5, 0xd4,
+ 0x4c, 0xcc, 0x7c, 0xe5, 0xb3, 0x88, 0x7d, 0x5a, 0x40, 0x12, 0x33, 0x07,
+ 0xe9, 0x15, 0x49, 0x9c, 0xaf, 0xf9, 0x9f, 0xba, 0x21, 0xfe, 0xfd, 0x45,
+ 0x5c, 0x06, 0x1a, 0x89, 0x5e, 0x49, 0x73, 0xfb, 0x40, 0xaf, 0xee, 0x7b,
+ 0xef, 0xd0, 0x4a, 0x41, 0x72, 0x16, 0x2b, 0x09, 0xee, 0x0d, 0x3d, 0x91,
+ 0x1d, 0xee, 0x46, 0x43, 0x35, 0xfc, 0x6d, 0x4a, 0x9a, 0x10, 0xac, 0x99,
+ 0xc9, 0xc1, 0xd7, 0xc7, 0x34, 0xcb, 0x34, 0x9f, 0xb1, 0xa9, 0x4d, 0x66,
+ 0x9d, 0x67, 0x33, 0xd2, 0xa2, 0xb0, 0x64, 0xf0, 0x9f, 0x25, 0xbe, 0xe9,
+ 0x5e, 0xfe, 0xeb, 0xbd, 0x2b, 0xff, 0x61, 0x16, 0x31, 0xdd, 0x7a, 0x3e,
+ 0xdc, 0xee, 0x91, 0x58, 0x6f, 0xb6, 0x2c, 0x2b, 0x26, 0xe5, 0x94, 0x3a,
+ 0x99, 0xa5, 0xc5, 0x4d, 0xcd, 0x8a, 0x18, 0x6b, 0x27, 0x34, 0xd6, 0xbe,
+ 0x61, 0xa2, 0x55, 0x55, 0x2e, 0x69, 0xb4, 0x01, 0xef, 0x95, 0xe9, 0x80,
+ 0xd9, 0x88, 0x09, 0xf5, 0xef, 0x4b, 0xda, 0x90, 0x79, 0x5a, 0xdd, 0xa8,
+ 0xa9, 0x96, 0xae, 0x89, 0x74, 0x56, 0x97, 0xd8, 0x39, 0x8c, 0xcb, 0xaa,
+ 0x00, 0x9d, 0xe6, 0x06, 0xdf, 0x40, 0xf4, 0x36, 0xc4, 0x42, 0x5e, 0x55,
+ 0x3e, 0x08, 0xa5, 0x1a, 0x76, 0x83, 0x9b, 0x11, 0x94, 0xe3, 0x4e, 0x8c,
+ 0xde, 0xda, 0xaa, 0x8c, 0x90, 0x71, 0xb3, 0x66, 0x3f, 0xed, 0x2c, 0xad,
+ 0x1b, 0x18, 0x7f, 0x94, 0x80, 0xe8, 0x41, 0x5f, 0xbc, 0x4e, 0x8b, 0x07,
+ 0xf2, 0x33, 0x7f, 0x8a, 0x78, 0x7d, 0x99, 0x5f, 0x2d, 0xab, 0x8c, 0xad,
+ 0x5e, 0x70, 0x4d, 0xab, 0x47, 0x9a, 0xf4, 0xb5, 0xeb, 0x12, 0xf4, 0x65,
+ 0xe4, 0xdc, 0x6c, 0x76, 0x19, 0xbb, 0xf7, 0x54, 0x61, 0x87, 0x4e, 0x5b,
+ 0x67, 0x13, 0x34, 0x55, 0x64, 0x62, 0xeb, 0x02, 0x77, 0x26, 0x47, 0x66,
+ 0x32, 0x99, 0xa5, 0xf9, 0xbc, 0x6e, 0x89, 0xb4, 0x5d, 0xca, 0x50, 0x89,
+ 0x1e, 0x44, 0x31, 0x26, 0x33, 0x7b, 0x55, 0x93, 0xf9, 0x04, 0x7c, 0x4a,
+ 0xa5, 0x6c, 0x36, 0x62, 0x5f, 0x67, 0x93, 0x1b, 0x90, 0x9d, 0x67, 0x5a,
+ 0xec, 0xf2, 0x2a, 0x5e, 0x75, 0x2c, 0xd8, 0x92, 0xbc, 0xd2, 0x46, 0x1c,
+ 0x19, 0x1b, 0x9a, 0xcb, 0x8b, 0xe9, 0x72, 0x82, 0xc3, 0x4a, 0xd6, 0x12,
+ 0x23, 0xa2, 0x55, 0x29, 0x89, 0x3c, 0x0d, 0xe2, 0x00, 0x12, 0xd0, 0xc5,
+ 0xc0, 0x10, 0xc1, 0x22, 0x3a, 0x3a, 0x70, 0x3b, 0x96, 0x53, 0x5b, 0x4c,
+ 0xa0, 0x16, 0xf7, 0x00, 0x2c, 0xef, 0xaa, 0xfd, 0xb5, 0x57, 0xb3, 0xd3,
+ 0x1c, 0xaf, 0x6d, 0x3f, 0x61, 0x4e, 0xaa, 0xce, 0xca, 0x69, 0x29, 0xa4,
+ 0x34, 0x30, 0xfa, 0x7a, 0x9d, 0x4f, 0xd8, 0x50, 0x95, 0x5f, 0x65, 0xc4,
+ 0x2f, 0x48, 0xf8, 0x6c, 0x66, 0x73, 0xf6, 0xe5, 0x77, 0x09, 0x6d, 0x60,
+ 0xa5, 0xb6, 0x80, 0xac, 0x7c, 0x86, 0xc2, 0x2a, 0x8a, 0xa5, 0x0f, 0x35,
+ 0x9b, 0xfa, 0x46, 0xb4, 0x9c, 0xed, 0x99, 0x66, 0x28, 0xcc, 0x32, 0xbb,
+ 0x6c, 0x07, 0x7e, 0x8f, 0xba, 0x31, 0xbc, 0xa5, 0x4f, 0x47, 0x64, 0x02,
+ 0x63, 0x34, 0x19, 0xfa, 0xd4, 0xca, 0xa8, 0xe6, 0xd2, 0x31, 0x09, 0x86,
+ 0xe4, 0x81, 0xba, 0xcb, 0x27, 0xec, 0x7c, 0x80, 0x03, 0x2d, 0x62, 0x36,
+ 0x98, 0xcc, 0x72, 0x7a, 0x70, 0x6e, 0x54, 0x5d, 0x7a, 0x8b, 0x25, 0x69,
+ 0xba, 0x16, 0x8c, 0x56, 0x3f, 0xb5, 0x1c, 0x15, 0x26, 0xb4, 0xfa, 0x1a,
+ 0x66, 0xef, 0xb4, 0xca, 0xe1, 0xa1, 0x0a, 0x9a, 0xe3, 0x31, 0xd3, 0x24,
+ 0xfd, 0x71, 0x42, 0xd5, 0x62, 0x23, 0xb0, 0xb3, 0x1f, 0xe0, 0xec, 0x10,
+ 0xd7, 0xf1, 0x0e, 0xce, 0x98, 0xce, 0x2b, 0x07, 0x58, 0x24, 0xaf, 0xe9,
+ 0x3a, 0x7a, 0x43, 0xb3, 0x59, 0xc1, 0x12, 0xcf, 0xe0, 0x17, 0xbb, 0x6e,
+ 0x1b, 0x88, 0x3d, 0xd6, 0xc7, 0x66, 0x14, 0x6e, 0x0d, 0x4e, 0x44, 0xa2,
+ 0x9e, 0xa8, 0xa6, 0x62, 0x28, 0x8a, 0xd8, 0xa1, 0x6d, 0x6b, 0xe1, 0xac,
+ 0x45, 0x66, 0x6b, 0xb2, 0xfc, 0xd6, 0xcc, 0xdc, 0xf9, 0x9b, 0xb8, 0x71,
+ 0x38, 0x82, 0x7b, 0xa3, 0xac, 0xe9, 0x36, 0x77, 0x80, 0x0e, 0xf7, 0x7a,
+ 0x9e, 0x3f, 0x99, 0x5b, 0x95, 0xb5, 0x1b, 0x67, 0xea, 0x2d, 0x66, 0xeb,
+ 0x8c, 0x61, 0xa2, 0x14, 0x7e, 0xb4, 0xf3, 0xe6, 0xbb, 0xfd, 0x93, 0x0f,
+ 0x47, 0x3b, 0x7f, 0xe9, 0x92, 0x8f, 0xf9, 0x6e, 0x97, 0xbf, 0xdb, 0xed,
+ 0xc5, 0x78, 0x96, 0xa1, 0xa0, 0x24, 0x59, 0x7f, 0xb3, 0x9e, 0xd4, 0x0f,
+ 0xf3, 0x71, 0x39, 0xb3, 0x7c, 0x4b, 0x3a, 0xa1, 0x51, 0xf4, 0x45, 0x3e,
+ 0x68, 0xf8, 0x9a, 0xe3, 0x85, 0xa1, 0x1b, 0xb2, 0x3b, 0x76, 0x38, 0x45,
+ 0x45, 0x20, 0x04, 0x05, 0xa4, 0x53, 0x7f, 0x31, 0xea, 0x06, 0x37, 0x9e,
+ 0x6c, 0x10, 0xb5, 0x5c, 0x33, 0x41, 0xf6, 0x13, 0x3e, 0x49, 0x5d, 0x76,
+ 0xce, 0x33, 0xb6, 0xee, 0x2e, 0x35, 0x0a, 0x8a, 0x72, 0x92, 0xb0, 0xfc,
+ 0xfd, 0x60, 0xc8, 0xb7, 0x21, 0x8b, 0xca, 0x87, 0x9a, 0x99, 0x4a, 0x5e,
+ 0xcb, 0xf9, 0xec, 0x32, 0x3c, 0x62, 0xfa, 0xe4, 0xc3, 0xbc, 0x35, 0xb3,
+ 0xe0, 0xad, 0xef, 0xc9, 0x58, 0x16, 0xa9, 0xe1, 0xe8, 0x55, 0x4f, 0xce,
+ 0xb3, 0x8b, 0x96, 0x11, 0x9b, 0x01, 0x1d, 0xb0, 0x2a, 0xb4, 0xd5, 0x98,
+ 0x53, 0x47, 0x3d, 0x4a, 0x44, 0x0f, 0x85, 0x66, 0x29, 0x47, 0xa0, 0x03,
+ 0x65, 0x46, 0x4d, 0x6e, 0xc2, 0x07, 0x39, 0x92, 0xeb, 0x55, 0x26, 0xe7,
+ 0x97, 0x3d, 0x82, 0x5d, 0xd2, 0x37, 0x8d, 0x8d, 0xf3, 0x42, 0x69, 0x5b,
+ 0x54, 0xb3, 0xc1, 0x09, 0x51, 0xf4, 0xac, 0x14, 0x96, 0xee, 0x8c, 0xae,
+ 0xe2, 0xf3, 0xb4, 0x34, 0x10, 0xb5, 0xe7, 0x69, 0x88, 0x51, 0x99, 0xf0,
+ 0x56, 0xe8, 0x40, 0xf9, 0x6c, 0x59, 0x72, 0x5a, 0x18, 0xe6, 0x5e, 0x30,
+ 0xe5, 0x0b, 0xd7, 0x4d, 0xca, 0x2a, 0xd2, 0xdc, 0xfb, 0xac, 0xa9, 0x8d,
+ 0x74, 0x98, 0x6d, 0xc9, 0xa5, 0xad, 0x1b, 0x89, 0x5e, 0x78, 0x20, 0x21,
+ 0xf7, 0x3a, 0xbd, 0x38, 0x72, 0xf6, 0x12, 0x3c, 0xe9, 0xbc, 0x9d, 0x6c,
+ 0x87, 0xf5, 0x0f, 0xad, 0xfa, 0x49, 0x85, 0x4b, 0xa7, 0xa1, 0x85, 0x6a,
+ 0xb1, 0x6c, 0xc8, 0xcc, 0x51, 0xda, 0xc9, 0xe8, 0x1d, 0x2a, 0xc4, 0xa5,
+ 0x67, 0xc3, 0xf4, 0x34, 0x24, 0x71, 0x02, 0x1f, 0xdb, 0xa0, 0xab, 0xd0,
+ 0x66, 0xc1, 0xcb, 0x3c, 0x71, 0x63, 0x18, 0xfc, 0x2d, 0x75, 0x97, 0xbd,
+ 0xc4, 0xe8, 0x60, 0xa5, 0xcc, 0x3d, 0x5e, 0x24, 0x75, 0x7a, 0xcb, 0xaf,
+ 0x60, 0xbd, 0xe2, 0x77, 0x96, 0x73, 0x8f, 0x29, 0xc3, 0x3e, 0xa4, 0xe6,
+ 0xa7, 0xcb, 0xf9, 0x42, 0x84, 0x89, 0x3f, 0xfc, 0x7e, 0xb2, 0xc3, 0x57,
+ 0x22, 0x1c, 0x0e, 0xd2, 0x7a, 0x92, 0xe7, 0x31, 0x01, 0x9b, 0x02, 0xf4,
+ 0x8c, 0x12, 0x77, 0x54, 0xb0, 0x31, 0x69, 0x7f, 0x74, 0x70, 0x7c, 0xec,
+ 0x3c, 0xb3, 0x1a, 0xca, 0x80, 0xf8, 0xbc, 0xa6, 0x23, 0x2f, 0x75, 0x9a,
+ 0xcb, 0xc8, 0x40, 0x3c, 0x61, 0x19, 0x96, 0x67, 0x6a, 0x1e, 0x25, 0x2b,
+ 0x2e, 0x36, 0xdc, 0xdc, 0x47, 0xb5, 0x18, 0xf7, 0xff, 0xd2, 0x3c, 0x2c,
+ 0xb2, 0x37, 0xfb, 0x3d, 0x6b, 0xb8, 0xe5, 0x79, 0x76, 0x4f, 0x40, 0xba,
+ 0x24, 0x75, 0x81, 0x99, 0x1d, 0xae, 0x1e, 0xda, 0xbe, 0xa9, 0xb8, 0x60,
+ 0x85, 0xef, 0x91, 0x3b, 0x65, 0x4e, 0xf2, 0xe1, 0x25, 0x9c, 0x50, 0xc5,
+ 0xb3, 0x5d, 0xc3, 0xb8, 0xcc, 0x5d, 0x3e, 0xaf, 0x7d, 0x01, 0x0a, 0xd7,
+ 0xef, 0xa3, 0xd6, 0xc0, 0xc0, 0x3c, 0xf9, 0x15, 0xbd, 0xd2, 0xb9, 0xf5,
+ 0x5b, 0x76, 0xca, 0x15, 0xd6, 0xc9, 0x14, 0x92, 0x68, 0x67, 0xef, 0x96,
+ 0x6c, 0x44, 0x35, 0xc2, 0x4f, 0x33, 0x33, 0xcc, 0xaa, 0x9f, 0x2c, 0x0b,
+ 0xfa, 0xd7, 0x3a, 0x49, 0x92, 0xbc, 0x89, 0x28, 0x2b, 0xa4, 0x8c, 0x54,
+ 0x39, 0xc9, 0xbe, 0x69, 0xe2, 0xf3, 0x4d, 0x96, 0x52, 0xd5, 0x93, 0xc2,
+ 0xa2, 0x00, 0x05, 0xa4, 0x51, 0x34, 0x9c, 0xda, 0x9d, 0xbb, 0xbc, 0x2e,
+ 0x2a, 0x0b, 0x6e, 0xa8, 0xb9, 0xda, 0xca, 0x22, 0x9e, 0x7c, 0x42, 0xbb,
+ 0xae, 0x82, 0x48, 0x97, 0xb1, 0x1b, 0x86, 0xe9, 0x6b, 0x20, 0xdd, 0xe3,
+ 0xf2, 0x1a, 0xc4, 0x4e, 0xdc, 0x7f, 0xc5, 0x5d, 0xeb, 0xf4, 0x8f, 0x52,
+ 0x38, 0x24, 0xde, 0xb0, 0x0e, 0x6b, 0xdd, 0x0d, 0xf6, 0xb3, 0x93, 0xc7,
+ 0x4a, 0x4e, 0x6c, 0x77, 0x1c, 0x97, 0xf0, 0x82, 0x13, 0xb3, 0x34, 0x8a,
+ 0x2e, 0xdd, 0x45, 0x56, 0x20, 0x18, 0x26, 0x07, 0xb0, 0x66, 0x52, 0x0b,
+ 0xb5, 0xdf, 0x84, 0xbf, 0x94, 0x81, 0x01, 0x82, 0x44, 0x40, 0xb0, 0xc3,
+ 0xd4, 0xe3, 0x4b, 0x18, 0x9b, 0x59, 0xa5, 0xbb, 0x0c, 0x11, 0x39, 0xad,
+ 0xc6, 0x5a, 0x17, 0x7a, 0xdc, 0x9e, 0xc1, 0x37, 0xfc, 0x46, 0xbd, 0x09,
+ 0xd9, 0xa7, 0x70, 0xac, 0x8a, 0xbc, 0x6e, 0x37, 0x45, 0x79, 0x67, 0x44,
+ 0x9a, 0xa2, 0xe4, 0x5e, 0xf4, 0x14, 0xd3, 0xb0, 0xbb, 0x8b, 0xde, 0x64,
+ 0x85, 0xdc, 0xff, 0xc2, 0xc8, 0x35, 0xa8, 0x0c, 0x4f, 0x37, 0x50, 0x90,
+ 0x55, 0x8c, 0x56, 0xde, 0xec, 0xf3, 0xe4, 0xae, 0xe4, 0xc7, 0x1c, 0xda,
+ 0x06, 0x61, 0x65, 0x1e, 0x4f, 0xd6, 0x8b, 0xdb, 0x8b, 0x3d, 0x81, 0x4b,
+ 0xda, 0x90, 0x45, 0x6f, 0xd0, 0xeb, 0xc7, 0x94, 0xa3, 0x2e, 0xff, 0xd5,
+ 0x31, 0xd9, 0x43, 0x1b, 0xdc, 0x05, 0x7c, 0xf4, 0xd5, 0xed, 0xc5, 0x7e,
+ 0x2f, 0xa5, 0x6a, 0x8e, 0xf8, 0x91, 0xbb, 0x59, 0xc2, 0xea, 0x30, 0x91,
+ 0xac, 0xb8, 0xca, 0xa1, 0x90, 0xa4, 0x5d, 0x12, 0xa7, 0x0b, 0x5a, 0xce,
+ 0x31, 0xdf, 0xcf, 0x56, 0xa3, 0x91, 0xa1, 0x0d, 0x93, 0xfd, 0x82, 0xe3,
+ 0xb9, 0xee, 0x52, 0x50, 0x9e, 0x6d, 0x1f, 0xe2, 0x4c, 0x78, 0x00, 0xed,
+ 0x75, 0xe0, 0x5f, 0x49, 0x72, 0xe7, 0x46, 0x39, 0xb6, 0x1d, 0x25, 0x1d,
+ 0x02, 0xc3, 0x27, 0xd7, 0x21, 0x00, 0x8b, 0x35, 0x00, 0x5e, 0x72, 0xbb,
+ 0x28, 0xcc, 0xbd, 0xef, 0xae, 0xcb, 0x19, 0x7b, 0xed, 0x3a, 0xcd, 0x79,
+ 0x72, 0x2d, 0x1c, 0xce, 0x50, 0xa7, 0xc9, 0x57, 0x44, 0x97, 0x4e, 0x95,
+ 0xc1, 0x60, 0x6b, 0x98, 0xab, 0xe1, 0x0f, 0xe4, 0x54, 0x9a, 0x65, 0x69,
+ 0x35, 0x7b, 0x30, 0xc4, 0xc1, 0x22, 0x4f, 0x32, 0xb8, 0xed, 0x34, 0x87,
+ 0xe5, 0x24, 0x9b, 0x47, 0x6a, 0xe6, 0x5e, 0x15, 0xf4, 0x90, 0x78, 0x09,
+ 0x35, 0xc0, 0xb2, 0x61, 0xbf, 0x2d, 0x3b, 0x97, 0xe9, 0xca, 0xbd, 0xcd,
+ 0x49, 0xc3, 0x32, 0xf4, 0x60, 0xe4, 0xf4, 0x2e, 0x25, 0x92, 0x3d, 0x13,
+ 0x44, 0x83, 0x26, 0x39, 0x28, 0xe6, 0x3a, 0xf7, 0xd4, 0x32, 0x73, 0x16,
+ 0xaf, 0xcd, 0x3d, 0x65, 0x74, 0xc5, 0x65, 0xba, 0x7a, 0xb9, 0x3e, 0xe9,
+ 0x82, 0xe3, 0x1b, 0xce, 0x8f, 0x89, 0x8a, 0xd0, 0x32, 0xe8, 0x75, 0xc5,
+ 0x0d, 0x78, 0xc0, 0x9b, 0x67, 0x98, 0x5f, 0xb1, 0x34, 0xd7, 0x60, 0x93,
+ 0xbc, 0x2e, 0x2f, 0x2f, 0x0d, 0xb5, 0x7f, 0x11, 0x08, 0xda, 0xfc, 0xc8,
+ 0xd6, 0x39, 0xe2, 0xad, 0x5b, 0x4c, 0x37, 0x69, 0x87, 0x94, 0x25, 0x22,
+ 0xbf, 0x5c, 0xe5, 0xb4, 0x1d, 0xdc, 0x5c, 0xa8, 0x61, 0xb6, 0xbf, 0xd7,
+ 0xc5, 0x65, 0x5f, 0xb8, 0xc6, 0x66, 0x43, 0xdf, 0x1c, 0x3f, 0x10, 0x8b,
+ 0x12, 0x46, 0xde, 0x8d, 0x14, 0x55, 0xd9, 0xf7, 0x26, 0x5f, 0x2c, 0x68,
+ 0xb3, 0x38, 0xc4, 0x13, 0xdb, 0x6c, 0x75, 0x88, 0x71, 0x66, 0x0e, 0x05,
+ 0x76, 0x55, 0x1d, 0xca, 0xe5, 0xd2, 0x5c, 0xc4, 0x3c, 0xe8, 0x71, 0x66,
+ 0x4e, 0x7a, 0xb7, 0x39, 0x15, 0xe0, 0x5d, 0x48, 0x96, 0x28, 0x3c, 0x53,
+ 0x0a, 0xbf, 0x2a, 0x84, 0x83, 0xd2, 0x36, 0xb9, 0x28, 0x0f, 0x51, 0x20,
+ 0xfb, 0x91, 0xc3, 0xff, 0xd6, 0x69, 0x49, 0x7a, 0x9e, 0x47, 0xc7, 0xff,
+ 0xf3, 0xc8, 0x05, 0xd0, 0xd9, 0x08, 0xb5, 0x07, 0x50, 0x7b, 0x40, 0x0f,
+ 0x1f, 0xe8, 0x12, 0xec, 0x0d, 0x0e, 0xcc, 0x7e, 0xf5, 0x30, 0x94, 0x96,
+ 0x35, 0x6f, 0xd9, 0x94, 0xe4, 0x77, 0xe6, 0x58, 0x43, 0xc4, 0x7d, 0x13,
+ 0xc9, 0x19, 0x7d, 0xb1, 0xca, 0xb6, 0xe0, 0xec, 0x2f, 0x03, 0xce, 0x8b,
+ 0x2d, 0x44, 0x88, 0x8f, 0x15, 0x64, 0x8e, 0x1b, 0x0e, 0xf9, 0x84, 0x54,
+ 0xe1, 0xb6, 0x4f, 0x82, 0x98, 0xb6, 0x20, 0x4b, 0x4a, 0x0c, 0x5e, 0xc8,
+ 0x0b, 0xc4, 0xae, 0xc2, 0x11, 0x47, 0x11, 0x66, 0xf6, 0x1b, 0x5a, 0x7b,
+ 0x26, 0xf9, 0xe2, 0x9a, 0xc4, 0xc6, 0xd7, 0x08, 0x6c, 0x20, 0x03, 0x13,
+ 0x7f, 0xf0, 0x45, 0xd4, 0xfa, 0x3e, 0x92, 0x83, 0x51, 0xcb, 0x45, 0xaa,
+ 0x6f, 0x0b, 0xff, 0xca, 0x35, 0x28, 0x59, 0x43, 0x25, 0x25, 0x98, 0xc6,
+ 0x34, 0xdd, 0x65, 0x39, 0xb6, 0x23, 0x56, 0xdd, 0x35, 0xf4, 0x04, 0xa1,
+ 0x9f, 0xfa, 0xd5, 0x30, 0x39, 0xc7, 0x1d, 0xb9, 0x5c, 0x70, 0x6c, 0x22,
+ 0xd9, 0xea, 0xe5, 0xbb, 0xc0, 0xe9, 0x55, 0x37, 0x2d, 0xf1, 0x08, 0x11,
+ 0xff, 0x7e, 0x7f, 0x45, 0x4b, 0x9f, 0xc8, 0xbd, 0xef, 0x8c, 0xcc, 0xb8,
+ 0xd7, 0x95, 0xa5, 0x5d, 0x64, 0xb1, 0xe1, 0x8d, 0x45, 0x5d, 0xcf, 0x10,
+ 0xcb, 0x3d, 0x2d, 0x27, 0xf5, 0x56, 0xba, 0x58, 0xd4, 0x5b, 0x3a, 0xc0,
+ 0x56, 0xd4, 0xb6, 0x6a, 0x1d, 0xa3, 0x91, 0x9d, 0x1b, 0x5d, 0xba, 0xb0,
+ 0x49, 0x59, 0x51, 0x69, 0x06, 0xcf, 0x5b, 0x21, 0xa6, 0xd5, 0x13, 0xf1,
+ 0x00, 0x7d, 0x5d, 0x2c, 0x2f, 0x4e, 0x46, 0x7c, 0xe1, 0x76, 0x6f, 0xce,
+ 0x25, 0x1d, 0x51, 0xdd, 0x1d, 0xbf, 0x71, 0x28, 0x72, 0x7c, 0x01, 0x8f,
+ 0x46, 0x07, 0xf8, 0x70, 0xb4, 0x24, 0x11, 0xc6, 0x74, 0x53, 0x3d, 0x30,
+ 0xdb, 0x08, 0x6e, 0x1a, 0x9a, 0x6d, 0xf2, 0xc9, 0xff, 0xc9, 0x42, 0x5c,
+ 0xe5, 0xcd, 0xf0, 0x32, 0x9b, 0x96, 0x55, 0x1a, 0x58, 0xca, 0x4a, 0x0a,
+ 0xaa, 0xc7, 0xea, 0x4c, 0xcc, 0x53, 0x5b, 0x46, 0x3a, 0xfe, 0x68, 0xd6,
+ 0x6b, 0x48, 0xbf, 0x43, 0xb5, 0xe3, 0x45, 0xd3, 0x8f, 0x69, 0xbd, 0xfe,
+ 0x78, 0x88, 0x30, 0x3d, 0x73, 0x1c, 0xea, 0xdf, 0x93, 0xae, 0x8d, 0x90,
+ 0x06, 0x17, 0xc0, 0x34, 0x2e, 0x14, 0x9e, 0xab, 0x4d, 0x30, 0x71, 0x4f,
+ 0xba, 0xb0, 0xbd, 0x6e, 0xf6, 0x92, 0x91, 0xc2, 0xae, 0x4a, 0x73, 0x9d,
+ 0x5e, 0xcf, 0xa3, 0x7e, 0x08, 0xf5, 0xb1, 0xf5, 0xb1, 0x9b, 0x50, 0xd3,
+ 0xf8, 0x3a, 0x59, 0x16, 0x5e, 0xeb, 0x86, 0x12, 0x26, 0x86, 0x51, 0x50,
+ 0x54, 0x38, 0x1b, 0x3f, 0x22, 0xdb, 0xa3, 0x72, 0xb6, 0x33, 0x16, 0xaa,
+ 0xf1, 0x4b, 0x59, 0x5e, 0x0d, 0xd5, 0x86, 0xbc, 0x12, 0x85, 0xcb, 0xa5,
+ 0x82, 0xd9, 0x9a, 0x0c, 0xd4, 0xb1, 0xd1, 0x61, 0x89, 0x3a, 0xd7, 0x78,
+ 0x7b, 0xa9, 0x70, 0x5c, 0x07, 0xb4, 0xbc, 0xc4, 0xea, 0x5e, 0xd7, 0x46,
+ 0xa2, 0x31, 0x9d, 0x7c, 0x11, 0x04, 0xfd, 0xdc, 0xe7, 0xf3, 0xe5, 0x1c,
+ 0xdb, 0x40, 0x94, 0x27, 0x8f, 0x31, 0x9b, 0xa2, 0x0b, 0x1a, 0x11, 0x31,
+ 0x32, 0x73, 0xc7, 0x03, 0xac, 0x2f, 0xa4, 0x7b, 0xc9, 0xf0, 0x7c, 0xf8,
+ 0x5b, 0x23, 0x4e, 0x0d, 0xad, 0x94, 0x26, 0x81, 0x56, 0x73, 0x0a, 0x91,
+ 0x68, 0xf3, 0x93, 0x64, 0x71, 0x9d, 0xd6, 0x59, 0x1f, 0x81, 0x67, 0xb1,
+ 0xa9, 0x9a, 0x6f, 0xf5, 0xe9, 0x2c, 0xd0, 0x8c, 0x4a, 0xc8, 0xc3, 0xf0,
+ 0xa3, 0x9a, 0xa5, 0xa5, 0x94, 0x21, 0x98, 0x20, 0x3f, 0x1b, 0x3e, 0xdb,
+ 0x1d, 0x6e, 0xf7, 0x03, 0x9b, 0x83, 0x53, 0x15, 0x35, 0x50, 0xdc, 0xf0,
+ 0x95, 0x49, 0x3e, 0xb7, 0xd1, 0x77, 0x2a, 0xcb, 0x64, 0x24, 0xdb, 0x2d,
+ 0x85, 0x3e, 0x71, 0x57, 0xe4, 0xb3, 0x30, 0x9c, 0x84, 0x04, 0x33, 0x66,
+ 0x91, 0xa6, 0xb5, 0x65, 0x95, 0x4e, 0x1e, 0x38, 0xa8, 0xd4, 0xb7, 0x49,
+ 0x68, 0x03, 0x66, 0x5c, 0x78, 0x1a, 0x07, 0x9c, 0x3a, 0x1d, 0x04, 0xe2,
+ 0xe7, 0x4c, 0x7c, 0xc1, 0x60, 0xb2, 0xa3, 0x2c, 0x63, 0x2d, 0x19, 0x02,
+ 0xe4, 0x9c, 0x64, 0x90, 0x79, 0x7a, 0x8f, 0x0d, 0x7d, 0x54, 0x84, 0xfc,
+ 0x8d, 0x8e, 0x1a, 0x44, 0x4e, 0xa3, 0xcb, 0x55, 0x5d, 0x6a, 0x86, 0x23,
+ 0xcd, 0x1a, 0xbd, 0x41, 0x14, 0x7f, 0x33, 0x47, 0xa2, 0x63, 0x66, 0xd2,
+ 0x48, 0xb8, 0xbe, 0x47, 0xae, 0xdc, 0x66, 0xc4, 0x0e, 0x64, 0xb6, 0xd6,
+ 0x9c, 0x26, 0x0a, 0x60, 0x20, 0xc3, 0x14, 0xc5, 0x9f, 0x11, 0x33, 0x29,
+ 0xcd, 0xdf, 0xd7, 0xb9, 0x19, 0x79, 0x35, 0xb9, 0xc6, 0xba, 0x92, 0xc1,
+ 0x17, 0x3e, 0xb1, 0xc7, 0x54, 0x7e, 0xf4, 0x51, 0x8b, 0xed, 0x34, 0xa7,
+ 0xab, 0x88, 0xb4, 0xd6, 0xb2, 0x50, 0x19, 0xa4, 0x33, 0x3a, 0x92, 0xe7,
+ 0x89, 0x2d, 0x64, 0x33, 0xa2, 0x9e, 0xe3, 0x98, 0xd1, 0x6b, 0x50, 0x7a,
+ 0x2a, 0x0d, 0xae, 0x7e, 0x43, 0x71, 0xa6, 0x69, 0x92, 0xa6, 0xd9, 0x60,
+ 0xc8, 0x1d, 0x91, 0xd9, 0x9b, 0xfb, 0x42, 0x20, 0x19, 0xa9, 0x82, 0x5d,
+ 0xf5, 0x50, 0x3c, 0x7d, 0xf2, 0xbe, 0xae, 0xbd, 0x3a, 0xfb, 0x02, 0xf5,
+ 0xa6, 0xd4, 0xf9, 0xa8, 0x22, 0xa8, 0x0b, 0xc3, 0x97, 0xb5, 0xd5, 0xd7,
+ 0x48, 0x78, 0x32, 0x83, 0xe1, 0x14, 0x48, 0xba, 0x26, 0x06, 0x83, 0xcb,
+ 0x26, 0x30, 0x2b, 0x7b, 0x5b, 0xda, 0xde, 0xe9, 0xd9, 0x25, 0xec, 0x38,
+ 0x9b, 0x24, 0xc0, 0x1a, 0x4a, 0x69, 0x92, 0x93, 0xb7, 0x74, 0x80, 0x0f,
+ 0xce, 0xcd, 0xbf, 0xb9, 0x7a, 0x4a, 0xc9, 0x1a, 0x8a, 0x7c, 0x46, 0x32,
+ 0x93, 0xbc, 0xfb, 0x6e, 0x94, 0x6c, 0x9c, 0x8e, 0xb6, 0x9e, 0xbd, 0xda,
+ 0xde, 0xec, 0xb6, 0x45, 0x4b, 0x05, 0xf5, 0x3d, 0xaa, 0xb9, 0x8f, 0xb6,
+ 0x28, 0x0d, 0x74, 0x93, 0x52, 0x75, 0x6f, 0xc9, 0x30, 0xd1, 0x32, 0x6b,
+ 0x9d, 0x1d, 0xbd, 0x53, 0xfb, 0x23, 0xbb, 0xf7, 0x8d, 0x4c, 0x6d, 0xc6,
+ 0x43, 0xde, 0x93, 0x90, 0x70, 0xce, 0xb3, 0x5b, 0xb5, 0x62, 0x26, 0x27,
+ 0x10, 0x15, 0xc0, 0xb3, 0xc8, 0x50, 0xaa, 0x82, 0xc7, 0x22, 0x23, 0x71,
+ 0xd2, 0xb5, 0x20, 0x6c, 0x8d, 0x2e, 0xf0, 0x40, 0xe0, 0x1b, 0x83, 0x25,
+ 0xd5, 0x66, 0x4c, 0x15, 0x2e, 0x0d, 0x0a, 0xec, 0x9f, 0xfe, 0x7e, 0x27,
+ 0x2c, 0x12, 0xfc, 0xb2, 0xf3, 0x6a, 0xf8, 0x99, 0xcd, 0x82, 0x1b, 0x4c,
+ 0xfb, 0x1a, 0x93, 0xfc, 0xfa, 0x11, 0x97, 0xc3, 0x28, 0x63, 0x66, 0xed,
+ 0x33, 0x1c, 0xbc, 0x04, 0x6f, 0x00, 0x62, 0xf3, 0xd5, 0x51, 0xe6, 0xbc,
+ 0xd7, 0x11, 0x43, 0xa3, 0x66, 0xf8, 0x5a, 0xdf, 0x28, 0x47, 0x94, 0x42,
+ 0xcf, 0x95, 0x45, 0x4b, 0xc6, 0x55, 0x79, 0x47, 0xa1, 0x88, 0x08, 0x92,
+ 0x07, 0xf5, 0xa5, 0x1c, 0x9b, 0x78, 0x1d, 0x58, 0x55, 0xcd, 0x9e, 0xce,
+ 0xac, 0xa7, 0xfd, 0x9b, 0x8b, 0x77, 0x27, 0x1c, 0x21, 0x4e, 0xd7, 0xde,
+ 0x42, 0x7c, 0xf8, 0x18, 0xf3, 0x72, 0x6c, 0xee, 0x03, 0xe2, 0xb8, 0x8d,
+ 0x35, 0x8d, 0xc5, 0x18, 0x2d, 0xec, 0x78, 0x56, 0x98, 0x5f, 0xc4, 0xdc,
+ 0x2c, 0x72, 0xf1, 0x38, 0xfb, 0x05, 0xe9, 0x6b, 0xe6, 0x34, 0x0e, 0xc8,
+ 0x50, 0xd8, 0xb5, 0xf9, 0x2c, 0x16, 0x33, 0xb1, 0x63, 0x6d, 0xdd, 0x0f,
+ 0x8c, 0x40, 0x38, 0xa0, 0xd1, 0x0d, 0x4c, 0xf3, 0xec, 0x29, 0x26, 0x16,
+ 0x73, 0x60, 0xae, 0x78, 0xa6, 0x93, 0x64, 0xf0, 0x96, 0xb6, 0x82, 0x1e,
+ 0x09, 0xb6, 0xcf, 0xdb, 0x25, 0x51, 0xce, 0xb0, 0x6c, 0x69, 0xad, 0x01,
+ 0xe5, 0x6c, 0x34, 0x15, 0x3f, 0xf4, 0x02, 0x71, 0xbe, 0x1c, 0x67, 0xbe,
+ 0x30, 0xba, 0x40, 0x60, 0x3d, 0x22, 0x73, 0x7d, 0xf5, 0xc0, 0x91, 0xcf,
+ 0x62, 0x4d, 0x57, 0xb7, 0xa2, 0xb5, 0x24, 0x70, 0xb3, 0xfc, 0xa4, 0x33,
+ 0xdf, 0x97, 0x24, 0x03, 0x0e, 0x02, 0x6b, 0x2a, 0xfc, 0xde, 0xf4, 0x1a,
+ 0x07, 0xf5, 0x53, 0x22, 0x28, 0xef, 0x04, 0x3b, 0xd3, 0x91, 0xd7, 0x96,
+ 0x3e, 0xa0, 0x71, 0x69, 0xd8, 0x2e, 0x42, 0x8c, 0xf4, 0x5d, 0x2a, 0x41,
+ 0xed, 0x02, 0xc8, 0xf5, 0x0c, 0xe0, 0x0e, 0x86, 0x18, 0x8c, 0x08, 0x72,
+ 0xc9, 0x65, 0x64, 0x32, 0x32, 0x02, 0x53, 0x78, 0xdb, 0xa9, 0xc9, 0xa6,
+ 0x2f, 0x14, 0x27, 0x0b, 0x93, 0xd3, 0x65, 0xd0, 0xb2, 0xe9, 0xf3, 0xf9,
+ 0x99, 0x67, 0xd5, 0x15, 0xb4, 0xcc, 0xab, 0xac, 0x09, 0x95, 0x05, 0xe1,
+ 0x17, 0x12, 0x16, 0x0c, 0xe5, 0xf6, 0x5f, 0x06, 0xec, 0x80, 0xc2, 0x85,
+ 0xb1, 0xa4, 0xf8, 0x5c, 0xa6, 0x8e, 0x64, 0x9d, 0x32, 0x13, 0xc4, 0x99,
+ 0x57, 0x98, 0x85, 0xa0, 0x7d, 0x0c, 0x95, 0xe5, 0xd9, 0xec, 0xcd, 0xcc,
+ 0x28, 0xee, 0x0f, 0xeb, 0x89, 0xa4, 0xd6, 0x48, 0x00, 0x7c, 0x23, 0x8a,
+ 0x3d, 0x36, 0x73, 0x72, 0xbd, 0x2c, 0x6e, 0x54, 0xf1, 0x9e, 0x95, 0x25,
+ 0x85, 0x17, 0x50, 0x30, 0x7e, 0xa7, 0xb9, 0x75, 0xaf, 0xb7, 0x7f, 0xf1,
+ 0xdb, 0x8e, 0xad, 0x32, 0x76, 0x1f, 0x59, 0x1d, 0x96, 0xc8, 0xed, 0xcd,
+ 0xc5, 0x39, 0x91, 0xc9, 0x97, 0x7d, 0x75, 0x75, 0x37, 0x2d, 0xa7, 0x56,
+ 0x10, 0x10, 0xc5, 0x66, 0x3e, 0xdc, 0x5c, 0xd6, 0x7f, 0x66, 0x5b, 0x65,
+ 0x47, 0x99, 0x61, 0xe7, 0x03, 0x75, 0xf2, 0xb6, 0x4c, 0xa7, 0xf4, 0x70,
+ 0xe4, 0x3a, 0x74, 0xf0, 0x00, 0x70, 0xa6, 0x0e, 0x93, 0x77, 0x7e, 0xd2,
+ 0x5c, 0x3b, 0x1a, 0xc2, 0xee, 0xe2, 0x30, 0x39, 0x33, 0xeb, 0x35, 0x08,
+ 0x9c, 0x2f, 0x57, 0xba, 0xed, 0x68, 0x90, 0xd6, 0xd5, 0x8d, 0x78, 0x9a,
+ 0xac, 0x5f, 0x96, 0xe5, 0x38, 0xad, 0xd6, 0x65, 0x03, 0xe0, 0xb8, 0x1f,
+ 0x8b, 0xf2, 0x45, 0x4b, 0x12, 0x38, 0xbd, 0xd1, 0xd6, 0x97, 0xfc, 0xd6,
+ 0x90, 0x25, 0x15, 0xef, 0x78, 0x96, 0xb3, 0xa9, 0x5d, 0x84, 0x6e, 0x87,
+ 0x91, 0x4d, 0xa3, 0x4d, 0x35, 0xe2, 0x4b, 0x5a, 0x55, 0x79, 0x7a, 0x45,
+ 0x8b, 0xdd, 0x2c, 0xab, 0x82, 0x33, 0xcc, 0x8a, 0xec, 0x8e, 0x9d, 0x8d,
+ 0xce, 0x57, 0x54, 0xc1, 0xba, 0xd2, 0xd6, 0xec, 0x03, 0x37, 0x4d, 0xfc,
+ 0x62, 0xfc, 0x1e, 0x36, 0x6a, 0x49, 0xf1, 0xe2, 0x94, 0x53, 0xcf, 0xf1,
+ 0xd3, 0x66, 0xee, 0x70, 0x43, 0xc5, 0xed, 0xa0, 0x9e, 0x9a, 0xc1, 0x6e,
+ 0x42, 0x9b, 0xb7, 0x69, 0x96, 0xc1, 0xcb, 0xff, 0x14, 0x0f, 0x16, 0xb5,
+ 0x2b, 0xdd, 0x44, 0x26, 0xce, 0x8c, 0x9b, 0x8c, 0x32, 0x39, 0x0c, 0xd0,
+ 0xb8, 0x66, 0x4a, 0x6a, 0x66, 0x28, 0x0e, 0x65, 0x2f, 0xe3, 0xd1, 0x0e,
+ 0x97, 0x1d, 0x5b, 0x21, 0xd1, 0x14, 0x4c, 0x9d, 0xbc, 0xf2, 0xb9, 0x64,
+ 0x24, 0x42, 0xd3, 0xb0, 0x58, 0x14, 0x85, 0xbd, 0xcd, 0xad, 0xef, 0x47,
+ 0x2c, 0xa7, 0xc1, 0x2e, 0xb7, 0xec, 0xa8, 0x7f, 0x80, 0x35, 0x62, 0x95,
+ 0xbf, 0x8d, 0xd6, 0x82, 0x33, 0x40, 0xe8, 0x02, 0xc3, 0xe1, 0xe9, 0x32,
+ 0x0e, 0xb6, 0xe4, 0xb6, 0xbc, 0x7a, 0xc1, 0x02, 0x77, 0x64, 0x5e, 0x71,
+ 0x65, 0x65, 0xbe, 0xd5, 0xca, 0xaa, 0x99, 0x4c, 0x18, 0x69, 0xe5, 0xcb,
+ 0x13, 0x81, 0xac, 0x41, 0xd3, 0xeb, 0xc9, 0xaa, 0xf5, 0xc4, 0xe3, 0xb3,
+ 0xe4, 0xb7, 0x48, 0xd3, 0xc4, 0x21, 0xad, 0x7e, 0xd7, 0x88, 0x20, 0x77,
+ 0x3b, 0xc5, 0x05, 0x0c, 0x52, 0x3f, 0xdc, 0xf5, 0x16, 0xbc, 0x29, 0x17,
+ 0xd0, 0x63, 0xb2, 0xc9, 0x85, 0x18, 0x74, 0x1b, 0xf1, 0xc0, 0xc1, 0x6e,
+ 0x39, 0x83, 0x24, 0xdf, 0xf1, 0xd8, 0x52, 0xc0, 0x80, 0x44, 0xde, 0x98,
+ 0x13, 0x10, 0xc8, 0xad, 0xe4, 0x9c, 0xa7, 0x20, 0x2c, 0x43, 0x96, 0x75,
+ 0x99, 0xb5, 0xa2, 0x3a, 0xbd, 0xa8, 0x03, 0xa4, 0x6c, 0x48, 0x36, 0xdc,
+ 0x27, 0x31, 0x4e, 0xe7, 0xaf, 0x8e, 0x71, 0x4d, 0xe2, 0x40, 0xe6, 0xe6,
+ 0x38, 0x14, 0xe6, 0xb1, 0x80, 0x4d, 0x44, 0xb2, 0xed, 0x39, 0xe1, 0x30,
+ 0xd1, 0x5c, 0xfb, 0xe0, 0xbe, 0x8f, 0xc4, 0xf9, 0x51, 0x76, 0xc8, 0x3d,
+ 0x72, 0x85, 0xe4, 0xb2, 0xb0, 0x2c, 0x84, 0xb3, 0x70, 0xbb, 0x4c, 0x86,
+ 0xe3, 0x82, 0x41, 0x5b, 0xd3, 0x48, 0x98, 0xd5, 0x04, 0x92, 0x7a, 0x6d,
+ 0x53, 0xaf, 0x0a, 0x90, 0x38, 0x31, 0xc6, 0x5f, 0x49, 0x33, 0x7c, 0x8e,
+ 0x4b, 0x0e, 0xa0, 0xb0, 0x09, 0x34, 0x11, 0x0d, 0x9f, 0xa3, 0xb0, 0xd8,
+ 0xbb, 0x82, 0x18, 0x49, 0x5e, 0xe8, 0xb4, 0x16, 0xf8, 0x8c, 0x31, 0xaf,
+ 0xd2, 0x23, 0xa4, 0x63, 0x45, 0x8c, 0x5f, 0x42, 0x3d, 0x7d, 0xbb, 0xea,
+ 0xc2, 0x12, 0xd9, 0x0f, 0x23, 0xdc, 0x5d, 0x65, 0x91, 0xc8, 0xa5, 0xc0,
+ 0x16, 0x73, 0x5a, 0x79, 0x44, 0x9d, 0x5e, 0xa7, 0xea, 0x69, 0xc8, 0x2a,
+ 0x92, 0x84, 0x6a, 0x08, 0x4e, 0x6a, 0x6a, 0x69, 0x67, 0x84, 0xec, 0x7c,
+ 0x4e, 0xd1, 0xe8, 0x81, 0x4e, 0x66, 0x08, 0xe6, 0xe0, 0xeb, 0x63, 0x18,
+ 0xa3, 0x66, 0xb9, 0x61, 0xa9, 0x4c, 0x52, 0x3c, 0x17, 0x06, 0xf7, 0xb0,
+ 0x94, 0x75, 0x45, 0xbc, 0x4e, 0xc2, 0xa5, 0xdb, 0x19, 0x6b, 0xd6, 0x85,
+ 0x46, 0x4b, 0x6d, 0xf3, 0x1c, 0x6c, 0xc2, 0x22, 0x36, 0x39, 0x55, 0x21,
+ 0xd6, 0xc6, 0x90, 0xa5, 0xce, 0xfe, 0x1a, 0x5d, 0x3b, 0xf4, 0x2e, 0xf9,
+ 0x83, 0x24, 0x26, 0xb3, 0x55, 0x1e, 0x1c, 0x36, 0xb0, 0x7e, 0xb9, 0x5d,
+ 0x66, 0xb0, 0x94, 0xac, 0xde, 0x5b, 0x0b, 0x3c, 0x72, 0xe8, 0x3e, 0x8e,
+ 0x61, 0x74, 0x61, 0x03, 0x67, 0xe7, 0x36, 0x71, 0xcc, 0xae, 0x65, 0xe6,
+ 0xcb, 0xe0, 0x2c, 0xf7, 0x93, 0xd4, 0x1e, 0xf3, 0xba, 0x59, 0x63, 0xae,
+ 0x39, 0x6d, 0xff, 0x4e, 0x66, 0x63, 0xa8, 0x62, 0x86, 0xa8, 0x49, 0xd9,
+ 0x84, 0xf9, 0x43, 0x7c, 0x25, 0xda, 0x9a, 0x86, 0xcd, 0xd2, 0xdf, 0x69,
+ 0x10, 0xf5, 0x62, 0x0f, 0xc9, 0x43, 0xf2, 0x86, 0x64, 0x9b, 0x2f, 0x25,
+ 0x0c, 0x89, 0xec, 0x78, 0xa2, 0xff, 0xb1, 0x83, 0x84, 0xaf, 0x25, 0x0e,
+ 0xca, 0x61, 0x8d, 0x07, 0xcb, 0x10, 0x6f, 0x0e, 0x01, 0x41, 0xfe, 0xea,
+ 0x31, 0xf9, 0x4d, 0x60, 0xcf, 0x01, 0x60, 0x4e, 0x10, 0x81, 0xf1, 0xe6,
+ 0xe9, 0xd5, 0xfb, 0xa5, 0xcb, 0xf7, 0xf8, 0xea, 0x5d, 0x5c, 0x73, 0x2e,
+ 0x41, 0x86, 0x70, 0xb7, 0x37, 0x5e, 0xf8, 0x15, 0xf9, 0x4f, 0x38, 0x00,
+ 0xd8, 0xc5, 0xb3, 0xb4, 0x8f, 0xa6, 0xe7, 0x05, 0x7b, 0xf3, 0x5b, 0xed,
+ 0x3a, 0x88, 0x11, 0x52, 0x3e, 0x0d, 0x3e, 0xde, 0x1c, 0xf3, 0x42, 0x4e,
+ 0x34, 0x2a, 0x9b, 0xcc, 0x6d, 0x36, 0xa3, 0x61, 0x50, 0x0b, 0x94, 0x25,
+ 0x73, 0xbf, 0x10, 0xe3, 0x1f, 0x4e, 0x5f, 0x44, 0xd5, 0x69, 0x69, 0x3c,
+ 0x53, 0xb5, 0xbe, 0x04, 0xf3, 0xfb, 0x52, 0x39, 0xfb, 0x53, 0x93, 0x6b,
+ 0x05, 0x6b, 0x21, 0x4e, 0xb0, 0x25, 0xa7, 0x82, 0x5e, 0xc4, 0xf9, 0x13,
+ 0x71, 0x26, 0x2a, 0x27, 0x73, 0x41, 0xd7, 0xa0, 0x47, 0xcb, 0xf3, 0x37,
+ 0xfb, 0xed, 0x35, 0xa3, 0xac, 0x60, 0x30, 0x51, 0xd9, 0xe8, 0x78, 0x73,
+ 0x39, 0x5d, 0xe8, 0xba, 0x7d, 0xa4, 0xda, 0x47, 0xb7, 0xef, 0xff, 0xb0,
+ 0x29, 0x72, 0xb4, 0x02, 0x2b, 0x30, 0x0c, 0x9c, 0x74, 0x45, 0x71, 0x2a,
+ 0x1c, 0xac, 0xfb, 0x77, 0x32, 0xd0, 0x26, 0x84, 0xdd, 0xb5, 0x82, 0x09,
+ 0xe0, 0x82, 0x22, 0x9f, 0x27, 0xb9, 0xf3, 0x66, 0x50, 0x0b, 0x4d, 0xe3,
+ 0xa0, 0x72, 0xa7, 0xed, 0x0f, 0x10, 0x78, 0x28, 0x54, 0x3b, 0x04, 0x1d,
+ 0x3e, 0x42, 0xac, 0x96, 0x38, 0xe3, 0x74, 0xb9, 0x92, 0x02, 0xcd, 0x4d,
+ 0x95, 0xcd, 0xb2, 0x2b, 0x16, 0x71, 0x4f, 0x8e, 0xbe, 0x3b, 0x3a, 0x09,
+ 0x04, 0xae, 0x86, 0x3f, 0xb7, 0xde, 0x4b, 0xcf, 0xae, 0xa1, 0xe8, 0x26,
+ 0x79, 0xcd, 0x06, 0x79, 0xee, 0x53, 0x5a, 0x8c, 0x06, 0xbe, 0xe6, 0xc4,
+ 0x20, 0x25, 0x7d, 0x02, 0x56, 0x9a, 0x89, 0x91, 0x43, 0x19, 0x23, 0xa8,
+ 0x86, 0x2d, 0x4f, 0x64, 0xaf, 0xaf, 0x47, 0xa3, 0xad, 0x9b, 0xac, 0x1a,
+ 0x13, 0x06, 0x53, 0x48, 0x50, 0x88, 0xc7, 0x4f, 0x0e, 0x11, 0x41, 0xc0,
+ 0x9e, 0x00, 0xda, 0x65, 0x37, 0x93, 0xe0, 0x8d, 0x45, 0x39, 0xcb, 0x27,
+ 0x0f, 0xc9, 0xa1, 0x8c, 0x8c, 0x93, 0x41, 0xb0, 0xeb, 0x70, 0x00, 0x88,
+ 0xbd, 0xf4, 0xf4, 0xdb, 0xc1, 0xfe, 0x68, 0x70, 0x78, 0x74, 0x72, 0xf4,
+ 0xf5, 0xfe, 0xc5, 0x11, 0x27, 0x34, 0x20, 0x0c, 0x73, 0x05, 0xd7, 0x11,
+ 0x8a, 0xf8, 0x56, 0xc6, 0x89, 0x55, 0xa1, 0x20, 0xe2, 0x26, 0x9f, 0xdc,
+ 0x64, 0x8d, 0x06, 0x7b, 0x2a, 0xa2, 0x1d, 0x71, 0xeb, 0x86, 0x5d, 0xe3,
+ 0xf1, 0xe6, 0xcc, 0xd6, 0xcc, 0xe6, 0x32, 0xd4, 0x60, 0x06, 0xe9, 0xec,
+ 0x8e, 0xd0, 0x40, 0x3e, 0x14, 0xa4, 0x9e, 0x48, 0x6a, 0x3e, 0x49, 0xad,
+ 0x98, 0xbd, 0xb7, 0x25, 0xde, 0xfa, 0xb7, 0x76, 0x19, 0xd1, 0x4f, 0x2b,
+ 0x82, 0x96, 0x38, 0x44, 0x4e, 0xb2, 0xeb, 0x0e, 0xf1, 0xe4, 0xca, 0x00,
+ 0x31, 0x52, 0xa3, 0xe5, 0xab, 0x40, 0x22, 0x66, 0x2a, 0xaa, 0x27, 0xd7,
+ 0xd9, 0x5c, 0x0e, 0x17, 0xc5, 0x19, 0x98, 0x47, 0x05, 0x29, 0xc4, 0x1c,
+ 0xb0, 0x3b, 0x8a, 0x5f, 0xe1, 0xa3, 0xcc, 0xea, 0x06, 0x47, 0xc0, 0x21,
+ 0x24, 0x2c, 0x16, 0xd9, 0x79, 0x97, 0x23, 0x41, 0x9b, 0x43, 0x41, 0x10,
+ 0x15, 0x07, 0x2a, 0xd1, 0xd8, 0xd2, 0x78, 0x34, 0x29, 0x83, 0xbd, 0x74,
+ 0x15, 0xb4, 0xa5, 0xa6, 0x93, 0xd8, 0x5c, 0x9f, 0x52, 0x22, 0xce, 0x18,
+ 0x4f, 0x8f, 0x4f, 0xb3, 0xbd, 0x19, 0x68, 0xa4, 0x8c, 0xf5, 0xc6, 0x11,
+ 0xb5, 0x61, 0x28, 0x3b, 0x22, 0xcb, 0xbc, 0x90, 0x76, 0x46, 0x2b, 0xb0,
+ 0x41, 0xeb, 0x64, 0x91, 0x56, 0xf4, 0x38, 0x4d, 0xe8, 0x8e, 0x69, 0x08,
+ 0x4d, 0x57, 0x4d, 0x16, 0x8d, 0xae, 0x23, 0x0a, 0x83, 0x50, 0x39, 0x90,
+ 0xa9, 0x12, 0x25, 0x2a, 0x9a, 0x9b, 0xda, 0xde, 0x75, 0xe4, 0x7b, 0x0e,
+ 0xb2, 0x45, 0xd5, 0x44, 0x42, 0x24, 0x39, 0xc7, 0xc2, 0x5a, 0x56, 0xa6,
+ 0x5e, 0x76, 0xa8, 0x97, 0xc4, 0x7f, 0x74, 0x76, 0xce, 0x30, 0x85, 0x27,
+ 0xf4, 0x8b, 0x84, 0x41, 0x74, 0x7b, 0x86, 0x36, 0x2f, 0x49, 0x10, 0x70,
+ 0xb8, 0x42, 0x09, 0xb5, 0x50, 0x45, 0x1a, 0xb4, 0xc6, 0x61, 0x13, 0x02,
+ 0xc5, 0x23, 0x24, 0x8d, 0xf9, 0x04, 0x71, 0x78, 0x16, 0x13, 0x89, 0x46,
+ 0x42, 0x43, 0xe8, 0xb3, 0x68, 0x84, 0x41, 0x70, 0xe8, 0x87, 0x9a, 0xe7,
+ 0x4f, 0xe9, 0xcb, 0xf1, 0xb2, 0xb1, 0xf9, 0x2d, 0x2b, 0x5c, 0x9d, 0x7d,
+ 0x4e, 0x05, 0xe3, 0x6b, 0x86, 0x9a, 0xa5, 0x37, 0x93, 0x0a, 0x08, 0x5a,
+ 0xa9, 0x19, 0xca, 0xb0, 0x33, 0x55, 0x80, 0x47, 0x50, 0x72, 0x6c, 0x3c,
+ 0xbf, 0x4c, 0x25, 0x7e, 0xd3, 0x00, 0xe0, 0x78, 0x68, 0xc2, 0x6a, 0x29,
+ 0x61, 0xef, 0x2c, 0x03, 0x8b, 0x90, 0x98, 0xc3, 0xf8, 0x8d, 0x8c, 0x7a,
+ 0x14, 0xd8, 0x91, 0x25, 0x1b, 0xca, 0xfa, 0xf8, 0x1e, 0x24, 0xff, 0x96,
+ 0x6d, 0x97, 0x97, 0xe2, 0xc5, 0x4a, 0x67, 0x79, 0xf3, 0xc0, 0x9a, 0x1e,
+ 0x5b, 0x0c, 0xd8, 0x46, 0x70, 0x9d, 0xc6, 0x52, 0x15, 0xcc, 0xc2, 0x5b,
+ 0xfc, 0x0e, 0xcc, 0x52, 0xb6, 0x2d, 0x34, 0x15, 0x83, 0x36, 0x7c, 0x70,
+ 0x0f, 0x80, 0x78, 0xdc, 0x93, 0x29, 0x3a, 0x27, 0xb5, 0x58, 0x86, 0xc2,
+ 0x2b, 0x43, 0x58, 0x19, 0x42, 0xe5, 0x45, 0x19, 0xa3, 0x2a, 0x61, 0x10,
+ 0x46, 0x01, 0x61, 0x08, 0x80, 0x36, 0x09, 0x06, 0xbd, 0x73, 0x3e, 0x32,
+ 0xd8, 0x00, 0x3a, 0x00, 0x8d, 0x4f, 0xae, 0x05, 0xdb, 0x8d, 0xbd, 0x9d,
+ 0x44, 0x4b, 0xe3, 0xec, 0x3a, 0xbd, 0xcd, 0x09, 0x30, 0xc5, 0x47, 0xff,
+ 0x09, 0x9c, 0x25, 0xb5, 0x21, 0x00, 0xc3, 0x6f, 0xc5, 0x18, 0x4f, 0x2f,
+ 0x22, 0x82, 0xd6, 0x43, 0xfd, 0xe1, 0xcd, 0x40, 0x64, 0xea, 0xe0, 0x0c,
+ 0x61, 0xa1, 0xe4, 0x91, 0xe2, 0xcc, 0xf5, 0x20, 0x16, 0x1c, 0x41, 0xbf,
+ 0x16, 0xb9, 0x43, 0x1e, 0x4d, 0xeb, 0xdb, 0xf8, 0x09, 0xab, 0x6f, 0xa3,
+ 0x27, 0x8c, 0x8f, 0x98, 0x97, 0x93, 0x3f, 0xf5, 0xb3, 0xdb, 0x5b, 0xc7,
+ 0x6c, 0xf4, 0x9d, 0x0d, 0x32, 0x8a, 0xdc, 0x9c, 0x7c, 0xb8, 0x74, 0x62,
+ 0xb1, 0xd3, 0x25, 0x94, 0x6d, 0xcf, 0x97, 0x1e, 0xb0, 0x47, 0x4f, 0x18,
+ 0xc6, 0xc4, 0x67, 0xcc, 0xf4, 0x2f, 0x07, 0xeb, 0x6c, 0x7f, 0xf4, 0x9d,
+ 0x77, 0xa4, 0x3c, 0x45, 0xdd, 0xe6, 0x03, 0x06, 0x57, 0x72, 0x03, 0x17,
+ 0x1f, 0x1f, 0x49, 0x6a, 0x2b, 0x4a, 0x6a, 0xf5, 0xed, 0xa7, 0x90, 0x9a,
+ 0x19, 0x48, 0x40, 0x6a, 0xc1, 0xf2, 0x3e, 0x46, 0x6a, 0xfe, 0x1e, 0x05,
+ 0xa4, 0x86, 0xf6, 0x03, 0x4a, 0xd3, 0x85, 0xfd, 0xc5, 0xa4, 0x26, 0x24,
+ 0x1a, 0x50, 0x1a, 0xbc, 0x17, 0x67, 0x7d, 0x8f, 0xc4, 0x5a, 0x74, 0x53,
+ 0xd4, 0x03, 0xc0, 0x41, 0x5c, 0x12, 0x72, 0xcf, 0x6b, 0xfb, 0xeb, 0x17,
+ 0x11, 0x90, 0x11, 0xcb, 0xa0, 0x91, 0xbb, 0x58, 0x2e, 0x9b, 0x2b, 0x90,
+ 0x42, 0x72, 0xf8, 0x7e, 0xe4, 0xc1, 0x3a, 0x98, 0x59, 0x54, 0x80, 0x1f,
+ 0xf2, 0x5b, 0x1b, 0x3e, 0x65, 0x92, 0x25, 0xb9, 0x44, 0xb0, 0x15, 0x59,
+ 0x8e, 0x25, 0xcf, 0x92, 0x37, 0x32, 0xc9, 0xa1, 0x55, 0x04, 0xaa, 0x20,
+ 0x4c, 0xf9, 0x92, 0x50, 0xb0, 0xcc, 0x40, 0x36, 0x59, 0x24, 0xa6, 0x30,
+ 0x91, 0x19, 0x19, 0xd0, 0x24, 0x43, 0xd1, 0xe6, 0x4a, 0x15, 0x89, 0x6b,
+ 0x93, 0x2f, 0xda, 0x8d, 0x48, 0x73, 0x36, 0xcd, 0x77, 0xf3, 0x09, 0x63,
+ 0xb2, 0x85, 0xa8, 0x50, 0x1f, 0x87, 0x8f, 0x44, 0xe0, 0x03, 0x11, 0x68,
+ 0xd2, 0x6e, 0x15, 0x89, 0xf4, 0x44, 0x26, 0x68, 0x0b, 0x5e, 0x40, 0x08,
+ 0xdd, 0x46, 0x5a, 0x03, 0x90, 0x77, 0x90, 0x52, 0x47, 0x36, 0xd5, 0xbd,
+ 0x8e, 0x99, 0x9f, 0x40, 0x4e, 0x08, 0x3a, 0x27, 0x5b, 0xd7, 0xa3, 0x90,
+ 0x17, 0xd8, 0xf9, 0xc5, 0xed, 0xf3, 0x01, 0x4d, 0xd5, 0xec, 0xd5, 0x62,
+ 0x20, 0x73, 0x7e, 0x74, 0xeb, 0xc7, 0x39, 0xa7, 0xad, 0xfa, 0xcf, 0xf3,
+ 0xa5, 0x6b, 0xf4, 0x25, 0x5a, 0x69, 0x24, 0x5e, 0x13, 0x45, 0x58, 0xe0,
+ 0x97, 0x2e, 0xc5, 0x7a, 0x36, 0x0b, 0xff, 0x39, 0xbd, 0xc0, 0x8c, 0xfc,
+ 0x22, 0x96, 0x73, 0x3a, 0x59, 0xdc, 0x85, 0xe8, 0x39, 0x69, 0x75, 0xb5,
+ 0x0c, 0x1c, 0x65, 0x30, 0x00, 0x39, 0x5b, 0xa5, 0x86, 0x53, 0xfb, 0x09,
+ 0xe0, 0xff, 0xef, 0xde, 0xc4, 0x4f, 0xd9, 0xc5, 0x97, 0xbf, 0xfd, 0x2e,
+ 0xbe, 0xfc, 0x6f, 0xb2, 0x8b, 0x2f, 0xff, 0x3f, 0xb2, 0x8b, 0x9a, 0x8b,
+ 0xee, 0xed, 0x49, 0x7f, 0xf5, 0x76, 0x92, 0x3a, 0x2c, 0xe1, 0xdb, 0x08,
+ 0xee, 0xa0, 0x30, 0x67, 0xda, 0x07, 0x6d, 0x85, 0x55, 0x6e, 0xc9, 0xe2,
+ 0x6b, 0x41, 0xea, 0x71, 0xf6, 0x4e, 0x3c, 0xb9, 0x46, 0xd2, 0x1f, 0x34,
+ 0xf2, 0xf2, 0xf8, 0xcc, 0x43, 0x15, 0x70, 0xbb, 0xa3, 0xe0, 0x52, 0xa2,
+ 0x22, 0x47, 0xbd, 0xd7, 0x35, 0xb9, 0x34, 0x0d, 0x1f, 0xe7, 0x30, 0xec,
+ 0x1a, 0x12, 0x28, 0xdc, 0x9e, 0xbc, 0x5d, 0x90, 0x0b, 0xc6, 0x1a, 0x21,
+ 0x6c, 0x36, 0x68, 0xef, 0x35, 0x2d, 0xf7, 0x80, 0x1f, 0xff, 0x22, 0x9a,
+ 0x85, 0x02, 0xf8, 0x28, 0x37, 0xa4, 0x38, 0x39, 0x08, 0x35, 0xb4, 0xa1,
+ 0x83, 0x62, 0xf8, 0x30, 0xce, 0xee, 0xfc, 0x04, 0x39, 0xfc, 0x2a, 0x7a,
+ 0xf8, 0xdf, 0x22, 0x87, 0x8c, 0x2e, 0x6b, 0xe0, 0x41, 0x91, 0x4b, 0xf4,
+ 0xc3, 0xf9, 0xc9, 0x93, 0xd1, 0x2d, 0xbd, 0x73, 0x46, 0x8f, 0xaa, 0x92,
+ 0xb3, 0xf4, 0x2a, 0xeb, 0xf9, 0x48, 0x62, 0x9f, 0x80, 0x31, 0x10, 0x64,
+ 0xe9, 0x93, 0x32, 0xea, 0xa2, 0xc1, 0xfc, 0xa4, 0x7c, 0x98, 0x22, 0x5c,
+ 0x4a, 0x3e, 0xbb, 0xfe, 0x62, 0xc0, 0x44, 0x2c, 0xaa, 0xb6, 0xb3, 0x29,
+ 0x35, 0x6d, 0x5b, 0x1c, 0x23, 0xbd, 0xbf, 0x50, 0xdc, 0x79, 0x4f, 0x07,
+ 0x68, 0xa7, 0x1c, 0x46, 0xef, 0x02, 0x6c, 0xc3, 0xda, 0x53, 0xdb, 0xd1,
+ 0xea, 0x9a, 0x56, 0x63, 0x33, 0x09, 0x00, 0x72, 0x7c, 0xcd, 0xf0, 0x83,
+ 0x97, 0xe5, 0xac, 0x4b, 0x9a, 0x00, 0x30, 0x4b, 0x93, 0x13, 0x19, 0xd4,
+ 0x9e, 0x38, 0x67, 0x79, 0x23, 0x75, 0x48, 0x22, 0x35, 0x88, 0x88, 0xa8,
+ 0x51, 0xa9, 0x33, 0x42, 0x17, 0xef, 0x06, 0x91, 0x10, 0xfd, 0xda, 0x1c,
+ 0x70, 0xb2, 0x03, 0xd1, 0x80, 0x20, 0x66, 0xe4, 0x00, 0x9c, 0xb6, 0xd3,
+ 0xfa, 0x1d, 0xbd, 0x95, 0x47, 0xf0, 0xee, 0x52, 0x68, 0xda, 0x6b, 0x2f,
+ 0x9c, 0xeb, 0xc7, 0x3d, 0x35, 0x1f, 0xfc, 0x1c, 0x8f, 0x6c, 0x0f, 0x70,
+ 0xba, 0x34, 0x8a, 0xc6, 0xf9, 0x1f, 0x25, 0xd5, 0xdc, 0x6b, 0x35, 0x66,
+ 0xed, 0xc4, 0x72, 0x2b, 0xe6, 0x6f, 0xaa, 0x89, 0x56, 0x86, 0x00, 0xa4,
+ 0x7e, 0x01, 0xc5, 0xb4, 0x25, 0xf0, 0xda, 0xb0, 0x5f, 0xc0, 0xf4, 0x3e,
+ 0x60, 0xa0, 0x67, 0xe8, 0xa9, 0x81, 0xfd, 0x46, 0x82, 0x52, 0xc8, 0xfc,
+ 0xea, 0x75, 0xac, 0x32, 0x9c, 0x39, 0x32, 0x67, 0xdf, 0x1e, 0x8c, 0xfe,
+ 0xb8, 0xb3, 0xab, 0xd1, 0x70, 0xb9, 0x42, 0xac, 0x8d, 0x80, 0xa8, 0xd0,
+ 0x25, 0x6f, 0x52, 0x4f, 0xb8, 0xa2, 0x00, 0x01, 0xb1, 0xba, 0x20, 0x3a,
+ 0xfb, 0x1a, 0xdb, 0x66, 0x79, 0x6c, 0x92, 0x00, 0xe5, 0xe2, 0x95, 0xb3,
+ 0xa8, 0x0e, 0x4f, 0xc1, 0xa8, 0x6a, 0x46, 0x62, 0xcc, 0x0d, 0xbb, 0x68,
+ 0x2d, 0xa8, 0x12, 0x73, 0x2b, 0x56, 0x08, 0x4c, 0x30, 0x5d, 0x73, 0xcc,
+ 0x4f, 0x90, 0x74, 0x26, 0x08, 0xa9, 0x2d, 0x0b, 0xbf, 0x23, 0x0b, 0x41,
+ 0xa8, 0x66, 0x09, 0xb9, 0xe7, 0xad, 0x47, 0x2f, 0x6a, 0x78, 0xe6, 0xbb,
+ 0x4f, 0x6e, 0x24, 0xf2, 0x17, 0x73, 0x02, 0x56, 0x72, 0x93, 0x3d, 0x88,
+ 0x1f, 0x3d, 0xb3, 0x1f, 0xfa, 0x8b, 0x4b, 0x50, 0x8d, 0x14, 0xfe, 0x18,
+ 0x98, 0xcc, 0x0d, 0x9b, 0xff, 0x03, 0x7b, 0xbb, 0x99, 0xc2, 0x58, 0x15,
+ 0xa2, 0xe6, 0x48, 0x11, 0x70, 0x28, 0x27, 0x73, 0x82, 0x8a, 0xd0, 0x1a,
+ 0x02, 0xb3, 0x87, 0x18, 0xb5, 0x2b, 0xb4, 0x0e, 0x33, 0x60, 0x68, 0x56,
+ 0x75, 0xa3, 0xc1, 0xfc, 0x2d, 0xa0, 0x2e, 0xf1, 0x3e, 0x35, 0x8f, 0xe5,
+ 0xae, 0xd2, 0xf7, 0x4e, 0xa6, 0x21, 0x6b, 0x5b, 0x3e, 0xb9, 0x81, 0x48,
+ 0x2f, 0x17, 0x9d, 0x3f, 0x3d, 0x8d, 0xf5, 0xe0, 0x4a, 0x02, 0xe1, 0x2e,
+ 0xd0, 0x00, 0xc8, 0x00, 0x4f, 0x54, 0x49, 0x97, 0x61, 0x5e, 0x70, 0x2e,
+ 0x0d, 0xdc, 0xa3, 0xc5, 0x6d, 0x5e, 0x95, 0x05, 0x44, 0x94, 0xdb, 0xb4,
+ 0xca, 0xa1, 0x1c, 0x9a, 0xd1, 0x7e, 0x3c, 0x3c, 0x3e, 0x4f, 0x36, 0x28,
+ 0x8b, 0x73, 0xfc, 0xb0, 0x22, 0x57, 0x35, 0xd9, 0xca, 0x9a, 0xc9, 0xd6,
+ 0xe2, 0x26, 0xdf, 0x2a, 0xea, 0x7a, 0x3a, 0xde, 0x1c, 0x5a, 0xa2, 0xe2,
+ 0x2e, 0x89, 0x18, 0x99, 0x96, 0x77, 0x48, 0x71, 0x5b, 0x9a, 0x86, 0x37,
+ 0xcc, 0x1a, 0x04, 0xbb, 0x50, 0x9b, 0x85, 0x9e, 0x0f, 0xeb, 0x72, 0x13,
+ 0xda, 0xe6, 0x6d, 0x9a, 0xcf, 0xd4, 0x40, 0x56, 0x30, 0x41, 0x23, 0xb4,
+ 0x48, 0xe0, 0x63, 0xd9, 0x5d, 0x81, 0x30, 0x3d, 0x71, 0xfc, 0x07, 0x31,
+ 0x1d, 0x45, 0xe3, 0xa0, 0x22, 0x39, 0x9b, 0x5c, 0x63, 0x55, 0xcc, 0x6a,
+ 0x02, 0x55, 0xd1, 0xc6, 0x18, 0xf7, 0x09, 0x57, 0x9d, 0x56, 0x85, 0x7d,
+ 0x67, 0x59, 0x98, 0x49, 0xcb, 0x29, 0xc7, 0xc3, 0xad, 0x9e, 0xc5, 0x91,
+ 0xcf, 0x0b, 0xc6, 0xd3, 0x87, 0x5a, 0x7a, 0x5b, 0xe6, 0x70, 0xc8, 0x5f,
+ 0x2e, 0x6b, 0x6b, 0x1c, 0x85, 0xbb, 0x57, 0xb6, 0x6b, 0x18, 0x35, 0x45,
+ 0x7a, 0xdb, 0x29, 0x8e, 0xcc, 0x3a, 0xe9, 0xed, 0xf5, 0x70, 0xb6, 0x0a,
+ 0x40, 0x59, 0xb3, 0x84, 0x23, 0xa3, 0xc2, 0x66, 0xf5, 0x7e, 0xea, 0x25,
+ 0x81, 0x7d, 0xb4, 0x71, 0xae, 0x01, 0x85, 0xee, 0xb8, 0x2a, 0xf2, 0x7f,
+ 0x30, 0xaa, 0x82, 0x3d, 0xc2, 0xd3, 0x0c, 0xb1, 0xf7, 0x48, 0xc7, 0xb6,
+ 0x3b, 0x44, 0x23, 0x88, 0x22, 0x2e, 0x78, 0x43, 0xfa, 0x29, 0x1c, 0x52,
+ 0x86, 0xc4, 0x50, 0xb4, 0xdf, 0xfb, 0x09, 0x43, 0xf2, 0x06, 0x11, 0x31,
+ 0x57, 0xb4, 0x87, 0x44, 0xd9, 0x0a, 0x92, 0x59, 0x7a, 0x6d, 0xa4, 0xac,
+ 0x49, 0x13, 0xb9, 0x39, 0x36, 0xf2, 0xd3, 0x11, 0x0e, 0xe2, 0xbb, 0x74,
+ 0x92, 0x98, 0x5f, 0x7f, 0x80, 0x74, 0xb1, 0xb9, 0xfa, 0x8c, 0x09, 0x63,
+ 0x14, 0x5e, 0x18, 0x83, 0xfe, 0xeb, 0xbb, 0x33, 0xd7, 0x61, 0xbb, 0xde,
+ 0x5d, 0x98, 0xe5, 0x60, 0x91, 0xe3, 0xcc, 0xb9, 0x79, 0x28, 0x66, 0x32,
+ 0x08, 0x48, 0xb1, 0x2f, 0x6f, 0x29, 0xab, 0x21, 0x7e, 0xa1, 0x35, 0x17,
+ 0x20, 0x7f, 0x12, 0x2b, 0x86, 0xb9, 0xdb, 0x7c, 0x63, 0x26, 0x4a, 0xa8,
+ 0x23, 0x48, 0x88, 0x0e, 0x8f, 0xe6, 0x22, 0x85, 0x31, 0x95, 0x73, 0x65,
+ 0x85, 0xf1, 0x5b, 0x3f, 0x92, 0x3f, 0x50, 0x0e, 0x9f, 0xb5, 0xfd, 0xa9,
+ 0xe1, 0xe4, 0xbf, 0x1d, 0xf1, 0xa7, 0x1e, 0xe9, 0xff, 0x7e, 0x01, 0x4c,
+ 0x92, 0xc7, 0xfb, 0x3a, 0x96, 0x24, 0x3e, 0xca, 0x66, 0x00, 0x0d, 0xc7,
+ 0x5e, 0x6b, 0x56, 0xd6, 0xa4, 0x7a, 0x58, 0x90, 0x1d, 0x4c, 0xf2, 0x7f,
+ 0x79, 0x85, 0xe8, 0xda, 0xe2, 0xdc, 0x2b, 0x0f, 0x8e, 0x7e, 0x18, 0xc9,
+ 0x2d, 0xb4, 0x1d, 0xb2, 0x3a, 0x42, 0xdb, 0x65, 0xf6, 0x82, 0x3c, 0x2a,
+ 0xa9, 0xaf, 0xa2, 0x10, 0x59, 0x4e, 0x39, 0x49, 0xc3, 0x55, 0x20, 0x09,
+ 0xe2, 0x72, 0xa9, 0xa1, 0x7a, 0xd8, 0x86, 0xe2, 0x81, 0xc1, 0x14, 0x25,
+ 0x71, 0xc0, 0x72, 0xc9, 0xf5, 0xb6, 0xa9, 0x9c, 0x5e, 0xde, 0x10, 0x14,
+ 0x90, 0xae, 0xf2, 0x60, 0xd9, 0xa5, 0x69, 0xa6, 0x5a, 0x16, 0xe8, 0xbd,
+ 0xbd, 0x52, 0x96, 0xbf, 0x77, 0xcf, 0xd9, 0xf9, 0xf1, 0xe8, 0x80, 0x0e,
+ 0xd8, 0xe9, 0xfb, 0x93, 0xbf, 0x92, 0xbc, 0x0d, 0x08, 0x00, 0x94, 0xfc,
+ 0xa0, 0xae, 0x63, 0x17, 0x43, 0xad, 0x08, 0xed, 0x11, 0x4a, 0x16, 0xbc,
+ 0x36, 0x92, 0x75, 0xef, 0x74, 0x8b, 0x5d, 0x1a, 0x15, 0x91, 0x0b, 0x9c,
+ 0x68, 0x86, 0xe0, 0x72, 0x52, 0x77, 0x28, 0xe2, 0x6b, 0xa2, 0x18, 0x58,
+ 0xcb, 0x10, 0xb1, 0x89, 0x02, 0x40, 0x7c, 0x41, 0x9f, 0xb5, 0x24, 0xb2,
+ 0x1a, 0x9a, 0xee, 0xcd, 0x44, 0x3b, 0x89, 0xa0, 0x66, 0xa2, 0x57, 0xec,
+ 0xcc, 0x5d, 0x91, 0x7f, 0xe0, 0x65, 0x3b, 0x3e, 0x88, 0x29, 0x92, 0x82,
+ 0xcf, 0x34, 0x38, 0x96, 0xa9, 0xe5, 0x88, 0x00, 0x14, 0x17, 0xe6, 0x9e,
+ 0xf9, 0x3a, 0x25, 0x5e, 0xc0, 0xf6, 0xbf, 0x34, 0x9b, 0x07, 0x17, 0x74,
+ 0x5d, 0x92, 0xef, 0x51, 0xe5, 0x38, 0xfe, 0xcb, 0xf3, 0x2a, 0xc1, 0x8a,
+ 0xc8, 0x81, 0x7c, 0xb4, 0xa0, 0x53, 0x73, 0x02, 0x85, 0x80, 0x88, 0xe4,
+ 0xcc, 0x50, 0xc2, 0x58, 0x1b, 0x2d, 0x45, 0xd1, 0xcd, 0xfd, 0x19, 0xf0,
+ 0xfb, 0x3c, 0xb5, 0x6e, 0xea, 0x0f, 0x4b, 0x2d, 0x08, 0x73, 0x4f, 0x5e,
+ 0xd3, 0xcf, 0xf8, 0xb4, 0x3d, 0x8c, 0x0a, 0xf8, 0x92, 0x5b, 0xb2, 0x03,
+ 0xbd, 0x2b, 0xe1, 0xa7, 0x94, 0x94, 0x31, 0x6d, 0xb1, 0xb8, 0xd0, 0x1a,
+ 0x4c, 0x41, 0xbf, 0xe6, 0x52, 0xee, 0x27, 0x87, 0x47, 0xe7, 0x60, 0x4a,
+ 0x47, 0xef, 0xbf, 0x86, 0x0f, 0xc7, 0x63, 0xf4, 0xd4, 0x66, 0xcd, 0x77,
+ 0x0d, 0xe3, 0xe9, 0xab, 0xec, 0xd8, 0x69, 0x8e, 0x2e, 0x77, 0xba, 0xf2,
+ 0x21, 0x03, 0x4e, 0x7f, 0xd7, 0x8c, 0xa6, 0x94, 0x15, 0x88, 0x83, 0x7d,
+ 0x7f, 0x76, 0x4f, 0xae, 0x56, 0x5c, 0x6b, 0xe8, 0xa8, 0x0b, 0xf4, 0x94,
+ 0x19, 0x91, 0xa1, 0xab, 0x98, 0x6b, 0x95, 0xd2, 0x50, 0xda, 0xb8, 0x0b,
+ 0x74, 0x8e, 0xe5, 0x8a, 0x75, 0x20, 0x8b, 0xed, 0x81, 0xb1, 0x31, 0x69,
+ 0xf5, 0xcd, 0xb3, 0x51, 0x6f, 0xb6, 0x14, 0x06, 0x2b, 0xf5, 0x93, 0x9c,
+ 0x2d, 0x7e, 0x89, 0xf6, 0x5d, 0x19, 0xda, 0xd6, 0xf9, 0x8a, 0x50, 0x59,
+ 0x4e, 0x51, 0x77, 0xb0, 0xe2, 0x7d, 0xbe, 0xd5, 0x5b, 0x4b, 0x6f, 0xf6,
+ 0x54, 0x74, 0x52, 0xa1, 0xf0, 0xc0, 0x73, 0x4e, 0xe7, 0x93, 0x63, 0x3d,
+ 0xbc, 0x36, 0x83, 0x4d, 0xb5, 0x08, 0x0b, 0xa0, 0x95, 0x7a, 0xb5, 0x0c,
+ 0xca, 0x51, 0xe0, 0xc9, 0xfa, 0x81, 0x51, 0x79, 0x3f, 0x1e, 0xec, 0x7f,
+ 0xfc, 0xea, 0xc3, 0xfb, 0xc3, 0x93, 0xa3, 0xf5, 0x2e, 0x45, 0x5e, 0x3a,
+ 0xe4, 0xc9, 0x1a, 0xd1, 0x00, 0x02, 0xdb, 0xe0, 0xe7, 0x68, 0xe3, 0xa8,
+ 0x03, 0x66, 0x0a, 0xbf, 0x01, 0x50, 0x47, 0x16, 0xbc, 0x6b, 0x16, 0x59,
+ 0x16, 0x53, 0x40, 0xfd, 0x78, 0x93, 0x57, 0x1c, 0x15, 0x31, 0xb7, 0xe8,
+ 0x00, 0x23, 0x16, 0x1a, 0xa2, 0x3f, 0x73, 0x58, 0x8d, 0x0a, 0xee, 0x41,
+ 0xc6, 0x7b, 0x25, 0x68, 0x5a, 0xaa, 0x3d, 0x32, 0x06, 0xb4, 0x18, 0x5a,
+ 0x62, 0xc6, 0x13, 0xd9, 0xee, 0xda, 0x25, 0x9f, 0x4d, 0x93, 0x75, 0x6a,
+ 0xc9, 0x50, 0xf2, 0x40, 0x06, 0x39, 0xa9, 0x9a, 0xf5, 0xbe, 0x4a, 0x2d,
+ 0xb9, 0x97, 0x71, 0x81, 0x0b, 0x3e, 0x80, 0xff, 0xa0, 0x8c, 0xba, 0x94,
+ 0xe9, 0x7a, 0x98, 0xdd, 0x67, 0x50, 0x17, 0xe5, 0xad, 0x03, 0x91, 0x0c,
+ 0xbe, 0x2f, 0x2b, 0xd8, 0x47, 0x0f, 0x9d, 0x84, 0xc0, 0x0f, 0x19, 0x0d,
+ 0x32, 0x8c, 0x5d, 0x24, 0x29, 0x20, 0x45, 0x59, 0x05, 0x54, 0x81, 0x3b,
+ 0xdb, 0xbf, 0xf8, 0x26, 0xea, 0x79, 0x77, 0xf5, 0x06, 0x85, 0x14, 0xad,
+ 0xdc, 0x66, 0x35, 0x05, 0x5f, 0x3d, 0xea, 0x5b, 0x9d, 0xc9, 0x90, 0x75,
+ 0x97, 0x61, 0x84, 0xda, 0x84, 0xa7, 0x3d, 0x58, 0x31, 0x95, 0xb3, 0x21,
+ 0xec, 0xcd, 0xc8, 0x6b, 0xbc, 0x3a, 0x37, 0x57, 0x0b, 0xff, 0x19, 0x0e,
+ 0xb8, 0x20, 0x00, 0xee, 0xdf, 0x97, 0x11, 0x81, 0x04, 0x3b, 0x8c, 0xc8,
+ 0xc9, 0x64, 0x9f, 0x60, 0xcb, 0x78, 0x92, 0x29, 0xb9, 0x0c, 0xca, 0xe0,
+ 0x94, 0x32, 0x9f, 0x62, 0x7e, 0x0f, 0xc6, 0x64, 0xf3, 0x37, 0x68, 0x58,
+ 0xb6, 0xfc, 0x84, 0x77, 0x19, 0x8c, 0x1f, 0x12, 0x2f, 0xb1, 0x26, 0xe4,
+ 0x70, 0x73, 0x11, 0x12, 0xf7, 0x7a, 0xc9, 0x46, 0x36, 0xbc, 0x32, 0xac,
+ 0xae, 0x47, 0x4d, 0xed, 0xec, 0xd1, 0xcf, 0x5d, 0xfc, 0x7c, 0xd6, 0x13,
+ 0xbf, 0x55, 0x2b, 0x1b, 0x8f, 0xf8, 0x57, 0x98, 0x86, 0xd7, 0xe2, 0x66,
+ 0xec, 0xdf, 0xcf, 0x2f, 0x1f, 0x21, 0x21, 0x91, 0xef, 0xa2, 0x98, 0x32,
+ 0x6e, 0x1d, 0x98, 0x59, 0x92, 0xf4, 0x40, 0x48, 0xa0, 0x54, 0xbd, 0xc3,
+ 0x4c, 0x70, 0xc2, 0x49, 0xdc, 0x5e, 0xd6, 0xd8, 0xc7, 0x2a, 0xbb, 0x4e,
+ 0xeb, 0xeb, 0x64, 0xd9, 0xe4, 0x14, 0x06, 0x10, 0x41, 0xba, 0x9e, 0xd9,
+ 0xb0, 0x75, 0xe9, 0x58, 0x71, 0xe2, 0xec, 0xce, 0xb2, 0xa5, 0x11, 0x69,
+ 0xd3, 0xf2, 0xc8, 0x40, 0x8a, 0x20, 0xc6, 0x18, 0x21, 0xa8, 0x95, 0x63,
+ 0xf1, 0xe8, 0x49, 0xbf, 0x24, 0xd5, 0x9c, 0xac, 0xa9, 0x88, 0x4d, 0xc8,
+ 0x2e, 0xcd, 0x9a, 0xe5, 0x1e, 0xd4, 0x00, 0x86, 0x1c, 0x66, 0x46, 0xf0,
+ 0x1d, 0x27, 0x51, 0x56, 0xf6, 0x6f, 0x70, 0x10, 0xab, 0xd2, 0xa1, 0x66,
+ 0x55, 0xf7, 0xb2, 0x79, 0x9a, 0xde, 0xc1, 0x5a, 0x19, 0xe0, 0x83, 0x79,
+ 0xbb, 0xcc, 0x96, 0x53, 0xcb, 0x94, 0xd8, 0x05, 0x84, 0x36, 0x06, 0x0d,
+ 0x6a, 0x51, 0x81, 0x7f, 0xed, 0xc9, 0xb9, 0x84, 0x8f, 0xd7, 0x1c, 0xe9,
+ 0x15, 0xd1, 0x55, 0x6f, 0x81, 0x18, 0x5b, 0x53, 0xfc, 0x23, 0xad, 0xd3,
+ 0x06, 0x95, 0xe3, 0xe0, 0xf2, 0x42, 0x29, 0xa2, 0xd7, 0x36, 0xc9, 0x40,
+ 0x25, 0xd1, 0x5b, 0x48, 0x98, 0xaf, 0xa3, 0xa8, 0xfc, 0x84, 0xf6, 0xc7,
+ 0xc5, 0x41, 0x90, 0x68, 0x04, 0x9d, 0x17, 0x61, 0x20, 0xe2, 0x36, 0x47,
+ 0x91, 0x48, 0xc3, 0x97, 0xb3, 0x66, 0xe2, 0x7d, 0x39, 0xcd, 0xd2, 0x59,
+ 0x12, 0x0b, 0x40, 0xbf, 0xe4, 0xe2, 0x92, 0x1a, 0x07, 0x00, 0xa1, 0xa8,
+ 0xd0, 0xe0, 0x01, 0x89, 0x20, 0xe6, 0x6c, 0xca, 0xa2, 0x05, 0x16, 0x79,
+ 0x09, 0xb4, 0x8b, 0xe0, 0xf8, 0x92, 0x22, 0xcf, 0xe9, 0x2c, 0x8a, 0x3c,
+ 0x00, 0xfd, 0xdc, 0x66, 0x0e, 0x20, 0x32, 0x12, 0x29, 0x97, 0xf6, 0x01,
+ 0xa4, 0x45, 0x70, 0x4e, 0x5c, 0x60, 0x3d, 0x50, 0xe8, 0x66, 0x54, 0xa3,
+ 0x13, 0x44, 0x43, 0x0d, 0xe4, 0xa7, 0x71, 0x3d, 0xd8, 0x42, 0xa1, 0x9b,
+ 0x72, 0x25, 0xc2, 0x42, 0x8e, 0x1d, 0x32, 0x0a, 0xe1, 0x20, 0x60, 0x2e,
+ 0x9a, 0x40, 0xc6, 0x05, 0x64, 0xb1, 0xfc, 0x0d, 0x9f, 0xae, 0xb4, 0x91,
+ 0x6a, 0x53, 0x34, 0x50, 0x01, 0x1e, 0xda, 0xdd, 0x8d, 0x7b, 0x39, 0x04,
+ 0x5e, 0x4c, 0x6c, 0x1a, 0xb4, 0x14, 0x83, 0x3a, 0xbd, 0xcc, 0xd4, 0xc2,
+ 0x47, 0xb5, 0x8b, 0x08, 0x58, 0x76, 0x62, 0x96, 0x8f, 0x03, 0xff, 0xf1,
+ 0x19, 0x29, 0x4d, 0x83, 0xb0, 0x9e, 0x06, 0x9d, 0x72, 0xd2, 0x25, 0x5c,
+ 0x8e, 0x4e, 0x42, 0xca, 0xb5, 0xc6, 0x5f, 0x27, 0xf5, 0x2c, 0x5f, 0xa8,
+ 0x53, 0xdf, 0xdc, 0xa6, 0xe0, 0xa8, 0xb8, 0x9f, 0x23, 0xc1, 0x21, 0x1d,
+ 0x18, 0x34, 0x48, 0xc3, 0xb7, 0xe4, 0x5d, 0x99, 0x26, 0x1b, 0xb6, 0x79,
+ 0x6e, 0xfd, 0xf9, 0xf6, 0x0e, 0xc6, 0xfb, 0x7c, 0xfb, 0x33, 0x3f, 0x49,
+ 0xda, 0x66, 0x93, 0x0a, 0xa0, 0xa8, 0x04, 0x9e, 0x3e, 0x96, 0x06, 0x31,
+ 0x23, 0xbd, 0x0c, 0xab, 0x9a, 0x19, 0x69, 0x11, 0xa6, 0x00, 0x49, 0xb1,
+ 0x1d, 0xe4, 0x05, 0x27, 0x74, 0x9a, 0x7f, 0x65, 0x27, 0x53, 0x0e, 0xb3,
+ 0xeb, 0x62, 0x7a, 0xa4, 0x0c, 0x5b, 0xc6, 0xa0, 0x15, 0x1c, 0xef, 0xce,
+ 0xd9, 0xb7, 0xed, 0xf4, 0x5b, 0x81, 0xcc, 0xd3, 0x5b, 0x06, 0x19, 0xc4,
+ 0x64, 0x37, 0x0c, 0x24, 0x47, 0xe5, 0x98, 0x40, 0x3d, 0xa2, 0x44, 0xdb,
+ 0x0b, 0xd2, 0x22, 0x44, 0x9a, 0x4d, 0xab, 0x66, 0x0b, 0x39, 0xb5, 0x1c,
+ 0x51, 0x9c, 0x4e, 0x08, 0x4d, 0xcb, 0x96, 0x02, 0x3c, 0x7f, 0x7b, 0xd0,
+ 0x69, 0x6e, 0xf7, 0xd9, 0xe7, 0x9f, 0xdb, 0xbc, 0xfe, 0x4c, 0x82, 0x24,
+ 0x1d, 0x74, 0xab, 0x11, 0xa1, 0x24, 0xdf, 0x88, 0xed, 0x80, 0x54, 0xc4,
+ 0x8d, 0x32, 0x31, 0x38, 0x6e, 0x28, 0xe4, 0xfa, 0xeb, 0xb2, 0xa6, 0xeb,
+ 0x1c, 0x32, 0xcc, 0x56, 0x2b, 0xad, 0x2f, 0x26, 0x75, 0x82, 0x3c, 0x38,
+ 0x4b, 0xd6, 0x00, 0xc5, 0x6e, 0x67, 0x0e, 0xc1, 0x97, 0x41, 0x14, 0xda,
+ 0x55, 0xc1, 0x29, 0xbc, 0x7f, 0xa3, 0x3b, 0xe4, 0x2a, 0x6b, 0xc2, 0x38,
+ 0x77, 0x81, 0x7c, 0x0b, 0xba, 0x58, 0x0d, 0x35, 0xa5, 0xb5, 0x12, 0x38,
+ 0x4a, 0xff, 0x35, 0x5f, 0x8f, 0x0a, 0x29, 0xe3, 0x15, 0x99, 0xfa, 0x12,
+ 0x44, 0xf4, 0xda, 0xda, 0xbc, 0x8b, 0xa8, 0x41, 0xfc, 0x4b, 0x85, 0x2f,
+ 0x13, 0x93, 0x0f, 0x70, 0xb5, 0x9a, 0x26, 0xd5, 0x1a, 0xa1, 0xb8, 0xee,
+ 0x29, 0x65, 0xd5, 0x42, 0xad, 0x2a, 0x02, 0x7a, 0xe0, 0xea, 0xc8, 0x25,
+ 0x32, 0xf1, 0xb5, 0x6d, 0x11, 0x18, 0x89, 0x9c, 0x32, 0x4c, 0x63, 0xc1,
+ 0x2a, 0xa0, 0x07, 0x0b, 0x0b, 0xd2, 0x20, 0xf6, 0xd4, 0xaf, 0x9e, 0xd5,
+ 0x8a, 0x99, 0x76, 0xef, 0x7b, 0xeb, 0x14, 0x9c, 0xfc, 0x23, 0x5b, 0x27,
+ 0x4c, 0x43, 0x70, 0x20, 0x55, 0xba, 0x68, 0x56, 0xd1, 0xb4, 0x5c, 0x10,
+ 0x6e, 0x5f, 0x0e, 0xfe, 0x3a, 0x3d, 0xd3, 0x3d, 0xf9, 0xf4, 0xce, 0xba,
+ 0xe6, 0x65, 0xfb, 0x76, 0x73, 0x50, 0x26, 0x0f, 0xc7, 0xa2, 0x07, 0xb2,
+ 0x1d, 0x9b, 0x7a, 0xb2, 0x19, 0xc7, 0x11, 0x55, 0x0e, 0x08, 0x4f, 0x7b,
+ 0x51, 0x7d, 0x66, 0xf0, 0xd6, 0x0e, 0xf4, 0xcd, 0x97, 0xad, 0xd6, 0xee,
+ 0xee, 0x86, 0xf3, 0x07, 0xfd, 0xae, 0x6e, 0x95, 0xec, 0x75, 0x49, 0x45,
+ 0x02, 0xa7, 0xca, 0x14, 0xe5, 0xb2, 0x6b, 0x7d, 0xdf, 0xb6, 0x2b, 0x90,
+ 0x67, 0xae, 0x76, 0xc5, 0x19, 0x59, 0x05, 0x9a, 0x2b, 0xc7, 0xf9, 0x8a,
+ 0xc2, 0x89, 0x48, 0xf6, 0x1d, 0x97, 0x86, 0xde, 0x94, 0x94, 0x28, 0x31,
+ 0xb1, 0xa9, 0x96, 0x93, 0x26, 0xbc, 0xf7, 0xb5, 0xec, 0x05, 0x2e, 0x02,
+ 0xf6, 0x3f, 0x68, 0xd1, 0x54, 0xd0, 0x59, 0xfb, 0xb4, 0x6b, 0x48, 0x1b,
+ 0x44, 0xc4, 0x98, 0x48, 0xb2, 0x0e, 0x9c, 0xce, 0xf5, 0x3e, 0x87, 0x53,
+ 0x4a, 0xbe, 0x9c, 0xcb, 0xe4, 0x5a, 0xb9, 0x94, 0xbd, 0xbb, 0x6c, 0xfc,
+ 0xe6, 0x4b, 0x72, 0xb8, 0xdc, 0x03, 0x5f, 0x88, 0xf1, 0x3e, 0x89, 0x8e,
+ 0xb6, 0xe8, 0xcf, 0x5e, 0x42, 0x2a, 0x4c, 0x64, 0x25, 0x0d, 0xfd, 0xad,
+ 0x6a, 0xd1, 0x4b, 0xc1, 0xf6, 0x5a, 0xbb, 0x2c, 0xcb, 0x95, 0x8d, 0xb9,
+ 0x1a, 0xb9, 0x58, 0x0d, 0x2f, 0x80, 0x8e, 0xe3, 0xd9, 0x1c, 0x61, 0x31,
+ 0x31, 0xd9, 0x3d, 0x92, 0xa3, 0x15, 0x4b, 0xce, 0x1a, 0x3f, 0x58, 0x70,
+ 0x70, 0x4d, 0xd4, 0x78, 0x23, 0xf5, 0xdb, 0x48, 0xde, 0x5a, 0xbd, 0x20,
+ 0xf4, 0xf4, 0x9b, 0x2f, 0x81, 0x8f, 0x42, 0xbf, 0xfe, 0xc5, 0xbe, 0x4d,
+ 0x3f, 0x0c, 0x5d, 0x9a, 0xb3, 0xbd, 0x72, 0x22, 0x46, 0x98, 0xd3, 0xc7,
+ 0xb7, 0x58, 0x42, 0x55, 0x59, 0x70, 0xbd, 0xbf, 0x4e, 0xfa, 0xdd, 0xfa,
+ 0x5f, 0xd6, 0x21, 0x45, 0xa8, 0x41, 0x01, 0x18, 0xf7, 0x5c, 0xb2, 0x7b,
+ 0x5a, 0x06, 0xb1, 0x2c, 0x14, 0xfa, 0x87, 0x27, 0xb8, 0xaa, 0xf9, 0x53,
+ 0x63, 0xfe, 0xa9, 0x67, 0x47, 0xfd, 0x53, 0xcf, 0x8d, 0xfb, 0xa7, 0x9e,
+ 0x1b, 0xf9, 0x4f, 0xbd, 0x5f, 0xb1, 0xa3, 0xeb, 0xdc, 0xbc, 0x6b, 0xdd,
+ 0x6b, 0xdc, 0x6b, 0xbb, 0xb7, 0xbe, 0xaa, 0x69, 0xdf, 0xfa, 0x8a, 0x2c,
+ 0x85, 0xa4, 0xb3, 0x4c, 0xe6, 0x00, 0xb9, 0x95, 0x90, 0xb2, 0x81, 0x3c,
+ 0xf1, 0x7e, 0x44, 0x1f, 0xf6, 0x1f, 0xa0, 0x45, 0xa5, 0x68, 0x89, 0x7a,
+ 0x46, 0xca, 0x84, 0xf3, 0xca, 0xd9, 0x0e, 0xec, 0x52, 0xab, 0x33, 0x25,
+ 0x70, 0xb1, 0xd9, 0xd7, 0x83, 0x33, 0x4a, 0xd6, 0xc1, 0xcb, 0x65, 0x05,
+ 0xa5, 0x5f, 0xaa, 0x88, 0x71, 0x1a, 0xa9, 0x42, 0xa4, 0x49, 0x5f, 0xef,
+ 0xf6, 0xdf, 0x7f, 0xd8, 0x3f, 0x79, 0x34, 0x8c, 0xc4, 0x8f, 0x11, 0xb5,
+ 0x86, 0x28, 0x88, 0xe4, 0xbe, 0xc6, 0x4a, 0x71, 0x95, 0x74, 0x87, 0x53,
+ 0x25, 0xd6, 0x1f, 0xe9, 0x4a, 0xff, 0x39, 0x1a, 0x81, 0xfb, 0xbd, 0x48,
+ 0xb1, 0x6f, 0x7d, 0xc4, 0xf3, 0x1b, 0xe6, 0x3f, 0x3d, 0x7d, 0x9f, 0x5e,
+ 0xef, 0x89, 0x29, 0xd7, 0x56, 0x36, 0x8b, 0x68, 0x0b, 0x96, 0xeb, 0x93,
+ 0xe4, 0xa2, 0xfa, 0x1a, 0x14, 0xd2, 0xbe, 0x57, 0xa9, 0x15, 0x7a, 0x09,
+ 0x2a, 0x68, 0x5f, 0xae, 0x36, 0x4b, 0xef, 0x1f, 0x1c, 0xb8, 0xb8, 0xec,
+ 0x76, 0x86, 0x67, 0x2b, 0x2e, 0xe5, 0xb7, 0x57, 0xf5, 0xb1, 0x70, 0x33,
+ 0xd4, 0x22, 0xa3, 0xd8, 0xd5, 0x41, 0x53, 0x72, 0x5e, 0xc4, 0x6b, 0x19,
+ 0xcd, 0x17, 0xf1, 0x48, 0x66, 0x32, 0x99, 0xf8, 0x82, 0xa6, 0x56, 0xa0,
+ 0x40, 0xad, 0x8d, 0x91, 0x18, 0x5d, 0xcf, 0xf6, 0x09, 0x36, 0x4e, 0x92,
+ 0x04, 0x58, 0x5b, 0x08, 0x62, 0xd8, 0x32, 0x85, 0x12, 0x76, 0xd3, 0xd7,
+ 0x64, 0x76, 0xd5, 0x33, 0x55, 0x28, 0xbb, 0x58, 0xce, 0x0d, 0xf5, 0x1a,
+ 0x89, 0x63, 0xba, 0x5e, 0x27, 0x4f, 0xc4, 0x19, 0x38, 0x9c, 0xaf, 0x12,
+ 0x3f, 0x11, 0xfe, 0xa0, 0x80, 0xcd, 0x91, 0x90, 0x8a, 0x7e, 0xf4, 0x6e,
+ 0xe8, 0x8d, 0x8e, 0x2f, 0x8e, 0x92, 0xfd, 0x0f, 0x17, 0xdf, 0xf4, 0xbc,
+ 0x02, 0x2c, 0xed, 0x0c, 0x1b, 0xa3, 0x2c, 0x54, 0x79, 0xa6, 0x08, 0xd9,
+ 0xb4, 0x76, 0x2c, 0xac, 0x45, 0xb0, 0x72, 0x3b, 0x1e, 0xf1, 0xce, 0x46,
+ 0xbf, 0x18, 0xbe, 0xd8, 0xec, 0x6c, 0xcc, 0x6a, 0x88, 0x2b, 0xaf, 0x6c,
+ 0x8c, 0xac, 0x16, 0x5d, 0x02, 0x1e, 0xca, 0x12, 0xc5, 0xe0, 0x6c, 0x39,
+ 0x84, 0x55, 0x88, 0xcc, 0x6a, 0x59, 0x0c, 0x73, 0x34, 0x6d, 0xc2, 0x2a,
+ 0xdb, 0xd8, 0x28, 0x00, 0xfb, 0x1e, 0x01, 0x68, 0x45, 0x4b, 0x94, 0xf1,
+ 0x0b, 0x26, 0xda, 0xe8, 0xe8, 0x48, 0x12, 0x93, 0x5a, 0x75, 0x09, 0x53,
+ 0x92, 0xaa, 0x15, 0xf8, 0x30, 0xf5, 0x21, 0xe8, 0x96, 0x0a, 0x10, 0x2e,
+ 0xd1, 0x23, 0x0a, 0x0b, 0x95, 0xcc, 0x73, 0xce, 0xb2, 0xf7, 0x20, 0xa6,
+ 0xba, 0x94, 0x2c, 0x4a, 0xd9, 0x8f, 0xfc, 0x6f, 0x9c, 0x07, 0x1c, 0x48,
+ 0xa5, 0x2b, 0x48, 0x0b, 0xf2, 0x02, 0xc3, 0xe9, 0x71, 0x74, 0x9d, 0x03,
+ 0xf2, 0x47, 0xe1, 0x2a, 0x76, 0x69, 0x60, 0x81, 0x43, 0x40, 0xd0, 0x8d,
+ 0xd1, 0x66, 0x62, 0x0b, 0x72, 0x91, 0x74, 0x2c, 0xed, 0x51, 0x7c, 0x65,
+ 0x27, 0x9e, 0x32, 0xc8, 0x6b, 0x8e, 0x41, 0x8d, 0x78, 0x27, 0x31, 0xbc,
+ 0x68, 0xc1, 0xfd, 0x26, 0x77, 0xd3, 0x78, 0xc6, 0x18, 0x97, 0xc5, 0x2c,
+ 0xb9, 0x06, 0x2c, 0x47, 0x6e, 0x1e, 0x7c, 0x7f, 0xd8, 0x29, 0x3e, 0xc9,
+ 0xe5, 0x1f, 0xd9, 0x9d, 0xcb, 0x31, 0xde, 0xab, 0xb2, 0x93, 0xbd, 0xe4,
+ 0x4a, 0x14, 0x4f, 0x27, 0x80, 0xf4, 0x69, 0x96, 0x2d, 0x2c, 0xde, 0x19,
+ 0xd0, 0xff, 0x59, 0x11, 0xa6, 0x22, 0xe8, 0x28, 0x77, 0x3e, 0x0f, 0xaf,
+ 0x1c, 0xeb, 0x3b, 0x62, 0x2e, 0xe0, 0x92, 0xc7, 0x08, 0xd3, 0xd4, 0xa8,
+ 0x59, 0xc9, 0xce, 0x67, 0xcf, 0x3e, 0x4f, 0x6a, 0xca, 0x4d, 0xc8, 0x3b,
+ 0x48, 0x31, 0x8c, 0x15, 0xb0, 0x3a, 0x47, 0x54, 0xe4, 0x66, 0x35, 0xf6,
+ 0x28, 0x2a, 0x5e, 0x4d, 0xc9, 0x87, 0xb8, 0xb9, 0x24, 0x7a, 0x3f, 0x4c,
+ 0x19, 0x34, 0x8b, 0xa8, 0x32, 0x23, 0x56, 0x0c, 0xf0, 0x0e, 0xb4, 0x5a,
+ 0x6c, 0x85, 0x19, 0xb6, 0xab, 0xcc, 0x13, 0xca, 0x6b, 0x3f, 0x39, 0x3f,
+ 0xba, 0x38, 0xef, 0x27, 0xa3, 0x8b, 0xd3, 0xf3, 0x15, 0x89, 0xbd, 0xcd,
+ 0x04, 0x4c, 0x8f, 0xd6, 0x8c, 0xc8, 0x86, 0xf0, 0x33, 0xd5, 0x90, 0xef,
+ 0x71, 0x0c, 0xda, 0x85, 0x94, 0x99, 0x08, 0xd4, 0xf0, 0xf9, 0x60, 0x55,
+ 0x3a, 0x77, 0x6b, 0xb5, 0x40, 0x36, 0x86, 0x97, 0x3f, 0x3a, 0x31, 0xde,
+ 0xf6, 0x4f, 0xa0, 0x10, 0xa2, 0x45, 0x9a, 0xae, 0x65, 0xd9, 0x18, 0xad,
+ 0x94, 0x8c, 0x72, 0x06, 0x49, 0x31, 0x65, 0xac, 0xa0, 0x10, 0xa6, 0x2c,
+ 0xb4, 0xe6, 0x40, 0xb5, 0x7b, 0x9a, 0x71, 0xd2, 0x4b, 0xc8, 0xf0, 0x7d,
+ 0x93, 0x79, 0x78, 0x5d, 0x4f, 0xd0, 0x6f, 0x5a, 0x93, 0x01, 0xc7, 0xab,
+ 0x5a, 0x43, 0x25, 0xa2, 0x58, 0xa4, 0x87, 0x81, 0x51, 0x19, 0x4f, 0x9d,
+ 0x58, 0x5c, 0x83, 0x58, 0xca, 0x93, 0xc5, 0x33, 0xa2, 0x5d, 0x5e, 0xb7,
+ 0x89, 0x2b, 0xa5, 0x50, 0x07, 0xef, 0x8b, 0x11, 0x70, 0x66, 0x0d, 0x90,
+ 0xa2, 0xd6, 0x75, 0x54, 0xeb, 0x96, 0xd4, 0x3a, 0x5c, 0x79, 0xa7, 0xcb,
+ 0x95, 0x29, 0xef, 0x27, 0xca, 0x59, 0xc8, 0x09, 0xdf, 0xca, 0x36, 0xd2,
+ 0x7a, 0xaf, 0x10, 0x04, 0x7c, 0x78, 0xda, 0x33, 0x79, 0x6a, 0x45, 0xdc,
+ 0xb2, 0x16, 0x07, 0x75, 0x51, 0x4c, 0xba, 0xe7, 0x9c, 0x89, 0xb3, 0xec,
+ 0xb2, 0xd3, 0x4e, 0x26, 0x4d, 0x57, 0x40, 0x55, 0x8c, 0x7d, 0x57, 0xa6,
+ 0x25, 0x19, 0x9c, 0x6d, 0xb9, 0x7c, 0x27, 0x05, 0xe9, 0x6a, 0xcd, 0x7c,
+ 0xe7, 0x57, 0x0b, 0x1e, 0x52, 0xcf, 0x42, 0xec, 0x17, 0x15, 0x02, 0x0f,
+ 0x8a, 0x6c, 0x45, 0xfd, 0x4c, 0x42, 0xf4, 0x2e, 0x38, 0xa1, 0x89, 0x53,
+ 0xa6, 0xb5, 0xc0, 0x82, 0xae, 0x24, 0xa5, 0xc2, 0x52, 0x5e, 0x2e, 0x2e,
+ 0xa8, 0x69, 0x09, 0x03, 0x27, 0x2d, 0x42, 0x18, 0x57, 0x02, 0x81, 0x15,
+ 0x21, 0x34, 0x7a, 0xa5, 0x48, 0x63, 0x62, 0x0c, 0xa9, 0x50, 0xa7, 0xbd,
+ 0x9d, 0x88, 0xc3, 0x46, 0xfa, 0xe0, 0x28, 0x9d, 0xf9, 0xdb, 0xc8, 0x1c,
+ 0x0e, 0x52, 0xb8, 0x63, 0x0c, 0x4d, 0xf5, 0x10, 0xe6, 0x6a, 0xf1, 0x6c,
+ 0xc3, 0x62, 0x47, 0x1c, 0x25, 0x86, 0x4c, 0x2a, 0xa9, 0x8a, 0xd0, 0x4e,
+ 0x51, 0xd2, 0x95, 0xec, 0xde, 0x67, 0x84, 0x88, 0x0d, 0x7a, 0x1b, 0xe4,
+ 0x8b, 0xa7, 0x93, 0x36, 0xc9, 0x10, 0xa9, 0x4e, 0x17, 0x17, 0xa4, 0xdd,
+ 0x42, 0x71, 0x5d, 0x5e, 0x5d, 0x21, 0x45, 0x20, 0x0f, 0x93, 0xb1, 0x6b,
+ 0x67, 0x7c, 0x14, 0x44, 0x0e, 0x23, 0x66, 0xd1, 0x98, 0x5b, 0x99, 0x68,
+ 0xdc, 0x99, 0xd0, 0x72, 0xed, 0x60, 0xd1, 0x56, 0xc6, 0x0a, 0xc0, 0x98,
+ 0x2c, 0x85, 0xa7, 0x26, 0x5e, 0x6a, 0x5a, 0x95, 0x0d, 0xa0, 0x97, 0x5b,
+ 0x87, 0xa0, 0x37, 0xe2, 0x20, 0xc4, 0x47, 0x72, 0xd5, 0x59, 0x8c, 0xd1,
+ 0x53, 0xa5, 0x25, 0x2b, 0xfd, 0xbe, 0x5a, 0x14, 0xfc, 0x7c, 0xb8, 0xbb,
+ 0xf9, 0x98, 0x6a, 0x41, 0x72, 0xbb, 0xe1, 0xfc, 0x19, 0x67, 0x2e, 0x19,
+ 0xfd, 0x8a, 0xd3, 0x47, 0x39, 0xfd, 0xb0, 0xe2, 0x9d, 0x55, 0x12, 0x57,
+ 0x92, 0x0a, 0x01, 0xa5, 0x69, 0x89, 0xba, 0xfb, 0x66, 0x8e, 0x59, 0xf3,
+ 0x64, 0x0a, 0xa0, 0x9a, 0x90, 0xd2, 0xe4, 0xcc, 0x5c, 0x2e, 0x76, 0x95,
+ 0xbd, 0xbc, 0xbb, 0x64, 0x03, 0xb1, 0x0b, 0x66, 0x1c, 0x9b, 0xdd, 0x8b,
+ 0x90, 0x50, 0x27, 0xd3, 0xdc, 0xd7, 0x64, 0xcc, 0xc1, 0x9b, 0x9b, 0x4f,
+ 0xc8, 0x29, 0x50, 0x99, 0x31, 0x10, 0x8c, 0xba, 0xd6, 0xb7, 0x12, 0x09,
+ 0x9b, 0x6c, 0xcf, 0xca, 0x45, 0xd7, 0xa2, 0xf7, 0xb3, 0x78, 0x21, 0x3d,
+ 0x9f, 0x14, 0xc5, 0x0d, 0x99, 0xb3, 0x59, 0xfb, 0xb5, 0x21, 0x96, 0x0b,
+ 0xd6, 0xe5, 0xca, 0xbb, 0x02, 0x68, 0xe9, 0x21, 0x35, 0x61, 0xf0, 0x74,
+ 0x76, 0x3a, 0x51, 0xf6, 0xbb, 0xdb, 0xc3, 0xfb, 0x2e, 0x3b, 0xad, 0xeb,
+ 0xd9, 0x60, 0x32, 0x99, 0xac, 0xe4, 0xa8, 0x07, 0x07, 0x07, 0xc9, 0xc6,
+ 0x01, 0x72, 0xbe, 0x0f, 0x64, 0x94, 0x07, 0xd7, 0x64, 0xa6, 0x99, 0x51,
+ 0x8d, 0x8d, 0xeb, 0x25, 0x59, 0xf5, 0x68, 0x28, 0xc2, 0x70, 0x46, 0xa3,
+ 0x93, 0xad, 0x8b, 0x93, 0x51, 0x37, 0xe4, 0x3c, 0x7d, 0x20, 0x5d, 0x8f,
+ 0x4b, 0x69, 0xb4, 0xf4, 0x16, 0x96, 0xdb, 0x00, 0xb7, 0xa4, 0x41, 0xab,
+ 0x4a, 0x57, 0xdc, 0x4b, 0x34, 0xb9, 0x62, 0x59, 0xa8, 0x7d, 0xdd, 0x2a,
+ 0x56, 0x45, 0x56, 0x20, 0x7e, 0x8b, 0x58, 0x1a, 0xa8, 0x4c, 0x2a, 0x75,
+ 0xbf, 0xdf, 0xbf, 0xa0, 0x22, 0x6d, 0x8d, 0xa4, 0x84, 0xac, 0x08, 0x88,
+ 0xb7, 0x60, 0x5d, 0xc8, 0xe4, 0x4c, 0x3d, 0x18, 0x73, 0xbd, 0x02, 0xc0,
+ 0x8a, 0xf2, 0x5a, 0xf9, 0xe2, 0x50, 0x22, 0x82, 0x23, 0x30, 0xaa, 0xb2,
+ 0xa2, 0x03, 0x7b, 0x07, 0x71, 0x58, 0x35, 0xfd, 0x59, 0x77, 0x36, 0x64,
+ 0xe7, 0x65, 0x78, 0xbf, 0xb5, 0x5e, 0xff, 0x91, 0x73, 0x1a, 0xb7, 0xa4,
+ 0xd7, 0x9f, 0x7f, 0xd5, 0x36, 0x21, 0x6a, 0x4b, 0x6c, 0xf1, 0xe6, 0x31,
+ 0xa5, 0x8c, 0x8b, 0x48, 0xa0, 0xa1, 0xdc, 0x8b, 0xe8, 0xdb, 0x26, 0xb1,
+ 0x36, 0x12, 0xca, 0x2f, 0x18, 0x74, 0xb5, 0xd9, 0xf4, 0x29, 0x4a, 0x8a,
+ 0x8c, 0x81, 0x5a, 0xcc, 0xdc, 0xe5, 0x2e, 0x0d, 0xd8, 0x86, 0x72, 0x0a,
+ 0x0f, 0x0f, 0xa1, 0x34, 0xcc, 0x85, 0x3d, 0xb6, 0x16, 0xb7, 0xbf, 0xca,
+ 0x16, 0xb3, 0x07, 0x2b, 0xa6, 0x49, 0xdb, 0xab, 0xf4, 0x37, 0x5f, 0xd8,
+ 0xf7, 0xd3, 0x3d, 0x75, 0x80, 0x75, 0xbb, 0x15, 0x74, 0x94, 0xe6, 0x5c,
+ 0x05, 0xbd, 0xcb, 0xd4, 0xa4, 0xe7, 0x4e, 0x99, 0xb4, 0x70, 0x87, 0x76,
+ 0xa3, 0x3b, 0xc4, 0x54, 0x1a, 0xdd, 0x8f, 0x73, 0x39, 0xf7, 0x72, 0x16,
+ 0xec, 0x3a, 0x10, 0x7d, 0x19, 0x62, 0xbb, 0x42, 0xa8, 0x27, 0xc3, 0x28,
+ 0x48, 0xd8, 0x81, 0x16, 0x10, 0xe8, 0xda, 0x25, 0xa4, 0xd8, 0xbc, 0x94,
+ 0x49, 0xec, 0xf8, 0x96, 0x78, 0xfd, 0x89, 0xab, 0x58, 0xd2, 0x17, 0xc4,
+ 0x53, 0xcd, 0x46, 0x8e, 0xec, 0x87, 0xfa, 0x89, 0x27, 0x54, 0xcb, 0xe3,
+ 0x2d, 0x7b, 0x10, 0xbd, 0x12, 0x06, 0xea, 0x19, 0x56, 0xf5, 0x5d, 0x35,
+ 0xd3, 0x95, 0xf5, 0xb2, 0x65, 0x8e, 0xe1, 0xaa, 0x6d, 0x6f, 0xca, 0x95,
+ 0x6d, 0xa4, 0x0a, 0xc3, 0xc3, 0x9c, 0xf9, 0x43, 0x64, 0xc2, 0x20, 0x6f,
+ 0x79, 0xcc, 0x20, 0xc6, 0xb7, 0x0a, 0xa2, 0x76, 0xb9, 0x6c, 0x68, 0xd2,
+ 0x5a, 0x8a, 0xdd, 0xdf, 0x03, 0x32, 0xcf, 0x4b, 0x50, 0x2e, 0xbb, 0xc8,
+ 0x1e, 0x2f, 0x44, 0xea, 0x70, 0xc1, 0xc4, 0xaf, 0x26, 0x40, 0x6b, 0x36,
+ 0x7d, 0x8f, 0x3d, 0xd4, 0x1a, 0xe7, 0xab, 0xa1, 0x20, 0x31, 0xb7, 0x0c,
+ 0x10, 0x29, 0x2a, 0xf3, 0x0b, 0xe0, 0x43, 0xf4, 0x76, 0x9a, 0x51, 0xdc,
+ 0x34, 0x89, 0x49, 0xc3, 0xe4, 0x24, 0x63, 0x8f, 0xd4, 0xfa, 0x97, 0xeb,
+ 0xa0, 0xbe, 0xf5, 0xd7, 0xeb, 0x12, 0xc6, 0x1c, 0xd6, 0xda, 0xa9, 0x04,
+ 0x3a, 0x9e, 0x86, 0xb0, 0xce, 0x26, 0xe7, 0x75, 0x1d, 0x84, 0x58, 0xe8,
+ 0x78, 0x64, 0x88, 0x49, 0x28, 0x24, 0xd9, 0xc0, 0x08, 0x7a, 0x24, 0x11,
+ 0x45, 0xf4, 0xd7, 0x36, 0x1e, 0xc7, 0x82, 0xb3, 0x6e, 0xc8, 0x53, 0xe4,
+ 0x66, 0xce, 0xdb, 0x5b, 0x65, 0xeb, 0x35, 0x32, 0x3e, 0xb8, 0x9a, 0x4a,
+ 0x2c, 0x90, 0xc1, 0xae, 0x8d, 0x8c, 0x87, 0x07, 0x82, 0x1c, 0xb6, 0xc9,
+ 0x24, 0xa7, 0x0c, 0x07, 0x88, 0x85, 0xe6, 0x4b, 0x23, 0xd2, 0x30, 0x79,
+ 0x63, 0xce, 0x08, 0x61, 0x36, 0x93, 0xee, 0x92, 0x5e, 0x96, 0xd2, 0x6e,
+ 0x02, 0x8e, 0xbd, 0x0b, 0x95, 0x3b, 0xb8, 0x22, 0x89, 0xf0, 0x6a, 0x56,
+ 0x8e, 0xcb, 0xcb, 0xcb, 0x47, 0xe4, 0x05, 0x4e, 0xf4, 0x46, 0x1b, 0x4c,
+ 0xa4, 0x3d, 0x4a, 0x74, 0xa2, 0xf7, 0xc6, 0x9c, 0x8f, 0x8f, 0x82, 0x7a,
+ 0x82, 0xea, 0x29, 0xf5, 0x86, 0x62, 0xf8, 0xee, 0x6a, 0x02, 0xd1, 0x64,
+ 0x2c, 0x4d, 0xe1, 0x30, 0xad, 0xa9, 0x98, 0x29, 0x91, 0x77, 0x0e, 0x17,
+ 0xd0, 0x1c, 0xc2, 0xff, 0xf8, 0xaf, 0x1f, 0x7f, 0x8e, 0x84, 0x3e, 0x93,
+ 0x66, 0xa3, 0x21, 0xa7, 0x08, 0x75, 0x61, 0x30, 0x15, 0xe8, 0x10, 0x24,
+ 0x87, 0xb8, 0x8a, 0x24, 0x52, 0x14, 0xd5, 0x4b, 0x73, 0x09, 0x19, 0x5c,
+ 0xed, 0x3a, 0x04, 0x6a, 0x5f, 0xd9, 0x68, 0x1c, 0x00, 0x01, 0xc9, 0x00,
+ 0x49, 0xcb, 0x79, 0xd3, 0x2c, 0x48, 0x85, 0xe8, 0xed, 0xe1, 0x81, 0xb2,
+ 0x60, 0x43, 0xd6, 0xbf, 0x2a, 0x7c, 0xf6, 0xc3, 0xf9, 0xb1, 0xd5, 0xe8,
+ 0xbc, 0x9d, 0xf8, 0x1a, 0x3b, 0x11, 0x2c, 0x9b, 0x43, 0xb7, 0xec, 0x77,
+ 0x41, 0x52, 0x1c, 0xd2, 0x17, 0xa9, 0xd5, 0x5c, 0x48, 0xad, 0x53, 0x6d,
+ 0x6f, 0xda, 0x8f, 0xc2, 0xb0, 0xf6, 0xbb, 0x50, 0xc5, 0x55, 0x88, 0xff,
+ 0xd7, 0xca, 0xe1, 0x94, 0xc0, 0x85, 0x00, 0x9a, 0xfa, 0x6b, 0x23, 0xbd,
+ 0x59, 0x10, 0xeb, 0x4e, 0xaa, 0x67, 0x0b, 0xe0, 0x9a, 0x2b, 0xab, 0x10,
+ 0xfd, 0xdf, 0xa1, 0x18, 0xa8, 0xd8, 0x86, 0xa2, 0x5a, 0xd1, 0x85, 0x03,
+ 0x88, 0x64, 0xd6, 0xa5, 0x50, 0x51, 0x6e, 0x05, 0x4f, 0x34, 0x98, 0x7d,
+ 0xfd, 0xdf, 0xd6, 0x1d, 0x30, 0x5f, 0x24, 0x99, 0x43, 0xc7, 0x1f, 0x20,
+ 0xe4, 0x0c, 0x8e, 0xfb, 0x6e, 0x94, 0xec, 0x09, 0xe7, 0x3b, 0xd7, 0xd6,
+ 0x8a, 0x1d, 0x47, 0xa0, 0xa9, 0x57, 0x0d, 0xe3, 0x9b, 0xa3, 0xfd, 0x43,
+ 0x9d, 0xeb, 0x3f, 0x05, 0xde, 0xc6, 0x9a, 0x47, 0xc6, 0x19, 0x03, 0x70,
+ 0x2f, 0x0b, 0x2d, 0xbe, 0x4b, 0x7b, 0xa2, 0x77, 0x07, 0xa8, 0xc3, 0x88,
+ 0xda, 0x54, 0xc2, 0x81, 0x48, 0x36, 0xa2, 0x3a, 0x8a, 0xdd, 0x69, 0xa5,
+ 0xf2, 0xe8, 0x19, 0xe6, 0xd4, 0xc6, 0x47, 0xa7, 0x97, 0x59, 0x9c, 0x47,
+ 0xbf, 0x7e, 0xa2, 0xe6, 0x6b, 0xfe, 0x77, 0x55, 0x79, 0xb8, 0x23, 0xc0,
+ 0x89, 0xca, 0xb3, 0x66, 0x31, 0x05, 0xfe, 0x4e, 0x19, 0xaf, 0xd2, 0x0c,
+ 0x94, 0x2e, 0xd2, 0x13, 0x68, 0x5e, 0x11, 0xe2, 0x43, 0x9c, 0xa8, 0x4a,
+ 0x0e, 0x7f, 0x15, 0xb8, 0x6c, 0xe5, 0x28, 0xc4, 0x62, 0xa5, 0x0a, 0x13,
+ 0x05, 0xcb, 0x33, 0x80, 0xa9, 0x80, 0xba, 0x4a, 0x70, 0x7f, 0x34, 0x57,
+ 0xe7, 0xd2, 0x07, 0xf8, 0x36, 0x5a, 0x19, 0xd9, 0xcc, 0x8d, 0x72, 0x6d,
+ 0xe4, 0x14, 0x1d, 0x2f, 0x3d, 0x76, 0x9d, 0x7a, 0x88, 0xe2, 0x05, 0xc3,
+ 0x8a, 0x07, 0x29, 0xb7, 0xd6, 0xea, 0x69, 0x8d, 0x1a, 0x80, 0xf0, 0x64,
+ 0x45, 0x9a, 0x8d, 0x7d, 0x4b, 0xda, 0x18, 0xf6, 0xa4, 0x03, 0x64, 0xa7,
+ 0xe2, 0xdc, 0xe4, 0x08, 0xfb, 0x94, 0xde, 0x7d, 0x67, 0x46, 0xf7, 0xc0,
+ 0xf9, 0xdd, 0xb4, 0x05, 0xf1, 0x70, 0xd7, 0x35, 0xa7, 0x15, 0x19, 0xa4,
+ 0xe6, 0x26, 0x99, 0xdc, 0x50, 0xd4, 0x7f, 0xdd, 0x2c, 0xc1, 0xdf, 0xd3,
+ 0x42, 0x15, 0x56, 0x1e, 0xa6, 0x03, 0x53, 0x99, 0x96, 0x43, 0xf8, 0x5e,
+ 0x57, 0xd4, 0x6e, 0x45, 0x9e, 0x04, 0xc9, 0x76, 0x84, 0x70, 0xa1, 0xe3,
+ 0x91, 0x3c, 0x59, 0xc5, 0x21, 0x56, 0xce, 0x4d, 0xb5, 0xf1, 0x70, 0x79,
+ 0x84, 0xa5, 0xeb, 0x49, 0x2b, 0xa5, 0x10, 0x1f, 0xd2, 0xba, 0xee, 0xa4,
+ 0xd8, 0xc9, 0x3a, 0x2a, 0xfb, 0xe0, 0xaa, 0x3d, 0x87, 0xac, 0x62, 0xe1,
+ 0x34, 0x68, 0xca, 0xb2, 0x3c, 0x86, 0xdd, 0x5f, 0xe5, 0xb7, 0x51, 0x28,
+ 0xeb, 0xd4, 0x0e, 0x8c, 0xc3, 0xae, 0xec, 0x05, 0xa2, 0x8e, 0xfd, 0xa4,
+ 0x14, 0x45, 0x8a, 0xb1, 0x90, 0x08, 0x1d, 0x58, 0x56, 0x36, 0xcc, 0x10,
+ 0xa5, 0x3b, 0x2c, 0xa5, 0xab, 0x7e, 0xcf, 0x10, 0x7e, 0xd2, 0xfb, 0xa6,
+ 0xac, 0x9b, 0xbd, 0x9e, 0x57, 0x6c, 0x4f, 0x24, 0x8b, 0x36, 0xe5, 0x08,
+ 0x9c, 0x6e, 0x10, 0x96, 0xc5, 0x12, 0x10, 0x1f, 0x40, 0x73, 0xb5, 0xc8,
+ 0xd3, 0xea, 0x83, 0x94, 0x14, 0x4d, 0x9b, 0xf0, 0x4e, 0x24, 0x3f, 0xcf,
+ 0x65, 0x0c, 0x94, 0xd2, 0xdd, 0xe5, 0x52, 0x35, 0x86, 0xf4, 0xc3, 0xe0,
+ 0x00, 0x9d, 0x0f, 0xbe, 0x41, 0x73, 0x7f, 0xe9, 0x59, 0xa5, 0xbb, 0xfb,
+ 0xd5, 0x5e, 0x2f, 0x1e, 0x04, 0xee, 0xae, 0x97, 0xda, 0xd6, 0xc6, 0x82,
+ 0x15, 0x5d, 0x06, 0xc8, 0xa0, 0xbe, 0xe6, 0x88, 0x6c, 0xe9, 0x86, 0x4b,
+ 0x94, 0x77, 0x11, 0x4d, 0x53, 0x92, 0x1c, 0x86, 0x05, 0x62, 0xf5, 0xa6,
+ 0x83, 0xf2, 0x72, 0x80, 0x92, 0x80, 0x54, 0xab, 0x9d, 0x1c, 0x2c, 0xde,
+ 0xa9, 0x03, 0xda, 0x32, 0x51, 0x12, 0x1d, 0xbf, 0xc8, 0x5d, 0x2d, 0x91,
+ 0xe2, 0x95, 0x55, 0x5b, 0x65, 0x40, 0xb2, 0x91, 0x7b, 0xa4, 0xea, 0xe8,
+ 0xeb, 0x16, 0xc9, 0x97, 0x52, 0x89, 0x04, 0xc8, 0x37, 0xa8, 0x26, 0x86,
+ 0xe0, 0xbc, 0x3e, 0xdf, 0xe7, 0x98, 0x35, 0xd8, 0xf0, 0x9c, 0x2d, 0x48,
+ 0x30, 0x01, 0x18, 0xbd, 0xff, 0x92, 0xcb, 0xc3, 0x46, 0x1d, 0xbe, 0x2e,
+ 0x1d, 0x64, 0x5f, 0xe1, 0xd5, 0x06, 0xa6, 0x23, 0x81, 0x07, 0x6d, 0xa7,
+ 0xd4, 0xaf, 0x02, 0x41, 0x1b, 0x11, 0x3a, 0xb2, 0x88, 0x9f, 0x9f, 0x0d,
+ 0x9f, 0x7d, 0x36, 0xdc, 0xee, 0x3b, 0x24, 0x9d, 0xc1, 0xc0, 0x2c, 0xdd,
+ 0xfd, 0xc3, 0xc0, 0xf1, 0x4c, 0x6c, 0xa5, 0x47, 0x5f, 0x41, 0x7d, 0x01,
+ 0x2a, 0x7a, 0x42, 0xeb, 0x31, 0x95, 0xfc, 0x5f, 0xb2, 0x80, 0x9a, 0x26,
+ 0x56, 0x05, 0xf6, 0x04, 0x3e, 0x97, 0x3f, 0x8a, 0x2f, 0x1f, 0xb4, 0xf4,
+ 0x96, 0xae, 0xa3, 0xc1, 0x7b, 0xc3, 0xe8, 0xf6, 0x92, 0x7f, 0x2f, 0xb3,
+ 0x9e, 0xd6, 0xa9, 0xda, 0x79, 0xb5, 0x6b, 0x14, 0x8e, 0xcf, 0x87, 0xdb,
+ 0xc3, 0x9d, 0xad, 0x4f, 0x75, 0x65, 0x3b, 0x5f, 0x36, 0xdf, 0x7a, 0x92,
+ 0x5e, 0xe7, 0xe8, 0x68, 0x8b, 0x75, 0x91, 0x98, 0x0f, 0x88, 0xde, 0x52,
+ 0x26, 0xee, 0x69, 0x25, 0x54, 0x14, 0x6b, 0xb1, 0x1c, 0xcf, 0xa7, 0x2f,
+ 0x92, 0xd7, 0xe6, 0x47, 0x18, 0xa4, 0x7d, 0x60, 0x5d, 0x86, 0xa8, 0x03,
+ 0x4e, 0x87, 0x48, 0x12, 0x0b, 0x59, 0xdc, 0xa4, 0x5f, 0x9f, 0xed, 0x9a,
+ 0xa6, 0xef, 0x53, 0x2d, 0x39, 0x34, 0xcd, 0xaf, 0xf2, 0x26, 0x9a, 0xe8,
+ 0x21, 0xaf, 0x3a, 0x07, 0x17, 0xed, 0xfc, 0xce, 0xee, 0xe7, 0xc9, 0x38,
+ 0x6f, 0x92, 0x77, 0x87, 0x2f, 0xb8, 0xe4, 0x7d, 0xbd, 0x9c, 0x2b, 0x7d,
+ 0x6a, 0x85, 0x18, 0x14, 0xef, 0x5a, 0xef, 0x5e, 0x14, 0x66, 0xe0, 0xb3,
+ 0x7c, 0x42, 0x49, 0x83, 0xfd, 0x56, 0xf9, 0xa8, 0x4b, 0x35, 0x68, 0x7a,
+ 0xd5, 0x98, 0xec, 0x49, 0xa2, 0x96, 0xc4, 0xa0, 0x1a, 0x51, 0xd5, 0xcd,
+ 0x1a, 0x98, 0xee, 0x6b, 0x2d, 0x95, 0xdd, 0x52, 0x0f, 0x3f, 0x6b, 0x9b,
+ 0x3d, 0x38, 0x26, 0x58, 0x11, 0x36, 0x07, 0x46, 0xfa, 0xbb, 0x0a, 0xa2,
+ 0x64, 0xe5, 0xde, 0x3e, 0xc6, 0xa3, 0x9c, 0x91, 0x20, 0x8f, 0x9f, 0xe0,
+ 0x71, 0x8b, 0x62, 0xe0, 0xb9, 0x30, 0xe8, 0x7c, 0xe6, 0x93, 0xe5, 0x8c,
+ 0x4a, 0x57, 0x86, 0x02, 0x0c, 0x22, 0x3e, 0x89, 0x2a, 0x15, 0x31, 0xa4,
+ 0x5a, 0x72, 0x85, 0xc3, 0xfd, 0x05, 0x45, 0xc5, 0x25, 0x3b, 0xc3, 0xfb,
+ 0xbe, 0x5f, 0x9e, 0x5b, 0x8a, 0x69, 0x51, 0x11, 0xee, 0xe0, 0xb2, 0x80,
+ 0x69, 0xbb, 0x33, 0x20, 0x6a, 0x9a, 0xc3, 0x11, 0x67, 0xe4, 0xda, 0xa9,
+ 0xf8, 0x4e, 0xdb, 0x35, 0x97, 0xc3, 0x55, 0x8a, 0x7a, 0x8c, 0x1e, 0xf5,
+ 0xe4, 0x7d, 0x60, 0x3d, 0x41, 0x04, 0x59, 0x31, 0x71, 0x91, 0x4f, 0x14,
+ 0xc9, 0x42, 0x8f, 0xa1, 0xc8, 0x2b, 0x12, 0x49, 0xab, 0x59, 0x44, 0xde,
+ 0x13, 0x61, 0x0d, 0x71, 0x6a, 0x07, 0x06, 0x21, 0xb0, 0x15, 0x8e, 0x2d,
+ 0x92, 0x45, 0x18, 0x90, 0x1c, 0xd1, 0x27, 0x59, 0xd4, 0x0a, 0x0e, 0x2e,
+ 0x8a, 0x18, 0x8d, 0x86, 0xc9, 0x02, 0x48, 0x62, 0xd1, 0x20, 0xe0, 0xe1,
+ 0xd0, 0x9b, 0xd5, 0xb1, 0x8a, 0x63, 0xb1, 0x29, 0x51, 0x9d, 0x9f, 0xad,
+ 0xb7, 0xc7, 0x27, 0x47, 0x9b, 0xc9, 0xdb, 0x0c, 0x08, 0x5e, 0x9d, 0x99,
+ 0x11, 0x03, 0xfc, 0x03, 0x7f, 0xa2, 0x3b, 0x24, 0x6a, 0x64, 0x2c, 0x87,
+ 0xca, 0x9a, 0x50, 0x21, 0x06, 0xf3, 0xb6, 0x41, 0xe0, 0xe5, 0x3c, 0x9f,
+ 0x12, 0xe1, 0x88, 0x5a, 0xcc, 0x49, 0x9d, 0x95, 0xd1, 0x15, 0x42, 0x94,
+ 0x96, 0xab, 0xda, 0xf6, 0xbd, 0x14, 0x74, 0x24, 0x80, 0x52, 0x0d, 0x5e,
+ 0x31, 0x3b, 0x4b, 0x23, 0x97, 0x78, 0x3b, 0xf5, 0x65, 0x72, 0xb9, 0xd3,
+ 0xd8, 0x59, 0xe0, 0x2a, 0xe4, 0xf9, 0x3f, 0x38, 0x3e, 0x19, 0x51, 0x21,
+ 0xf3, 0x72, 0x6a, 0x01, 0xbb, 0xb9, 0xb8, 0x1a, 0xcd, 0xd7, 0x67, 0x28,
+ 0x1e, 0x28, 0x59, 0x2c, 0x85, 0xf5, 0x8c, 0xf1, 0xc9, 0xe1, 0xb6, 0xf1,
+ 0x23, 0x0d, 0x58, 0x00, 0x77, 0x4a, 0x98, 0x6d, 0x66, 0x68, 0x63, 0xf7,
+ 0xb2, 0xa2, 0x89, 0xd0, 0x85, 0x0f, 0x0a, 0xd6, 0xf7, 0xfd, 0x01, 0x66,
+ 0xb6, 0x38, 0xea, 0x1c, 0x36, 0xb8, 0x5f, 0x68, 0x4c, 0x91, 0x54, 0x73,
+ 0xe0, 0x2c, 0xa5, 0xa0, 0x36, 0x63, 0x24, 0xee, 0x4b, 0xb8, 0xb9, 0x37,
+ 0x33, 0x23, 0xcb, 0x6f, 0xef, 0xed, 0xf8, 0xa5, 0x17, 0x0b, 0x29, 0x2b,
+ 0x4c, 0xf1, 0x58, 0x5b, 0xbf, 0x5f, 0xe4, 0xcd, 0xdf, 0x88, 0x34, 0xff,
+ 0xb6, 0x2c, 0x6e, 0x0c, 0x6d, 0xd5, 0x44, 0xc1, 0x83, 0x78, 0xf9, 0x67,
+ 0x39, 0x7d, 0xdf, 0x5b, 0xdf, 0x4b, 0xb7, 0x4e, 0x48, 0xab, 0xc2, 0x7d,
+ 0x2a, 0x3e, 0x7b, 0xa6, 0x8b, 0xd5, 0xd9, 0x44, 0x4e, 0xac, 0xc9, 0xc9,
+ 0xe3, 0x6b, 0x26, 0x4c, 0xb5, 0x84, 0x49, 0xf3, 0xeb, 0xc9, 0x70, 0x6c,
+ 0xb5, 0x63, 0x57, 0xc1, 0x3c, 0x66, 0x33, 0xa3, 0x0a, 0xe2, 0x2c, 0x14,
+ 0x5f, 0xdb, 0xfa, 0x83, 0xd0, 0x07, 0xc4, 0xab, 0x42, 0xf2, 0x21, 0x91,
+ 0xb3, 0x11, 0x41, 0x12, 0x6d, 0x99, 0x42, 0xa2, 0xe8, 0x9e, 0xa7, 0xf5,
+ 0xe8, 0xdc, 0x96, 0x9c, 0xbf, 0xa7, 0x85, 0x9c, 0x6a, 0x85, 0x2d, 0xd4,
+ 0x11, 0x26, 0xdd, 0xc1, 0x09, 0xf0, 0x09, 0xa4, 0x96, 0xf5, 0xe0, 0x5c,
+ 0x4e, 0x66, 0x25, 0xed, 0x0e, 0x59, 0x62, 0xbd, 0x95, 0xff, 0x77, 0x16,
+ 0x44, 0xe8, 0x32, 0x92, 0x93, 0x3e, 0x88, 0x44, 0x78, 0xf9, 0xd1, 0xed,
+ 0x9a, 0x82, 0x85, 0xfc, 0x26, 0x48, 0x38, 0xa7, 0x5e, 0x1b, 0x1c, 0xb8,
+ 0x6b, 0xb3, 0xb4, 0xe4, 0xc2, 0x8a, 0x02, 0x7b, 0x0e, 0xbc, 0x12, 0xbf,
+ 0x96, 0x5b, 0x1f, 0x9a, 0x63, 0x5b, 0xd6, 0x39, 0x2b, 0xc5, 0x2e, 0xfc,
+ 0xce, 0x53, 0xc2, 0xc3, 0x08, 0x1b, 0xcd, 0x4c, 0xb6, 0x60, 0x2f, 0x1c,
+ 0xe4, 0xa9, 0x96, 0x64, 0x0a, 0xd9, 0x88, 0x64, 0xfe, 0xc1, 0xec, 0x86,
+ 0x60, 0x07, 0x0f, 0x54, 0xd5, 0x5c, 0xf5, 0x64, 0xe9, 0xf8, 0x93, 0xa1,
+ 0x43, 0xa3, 0x71, 0x16, 0x54, 0xda, 0x68, 0xe3, 0x21, 0x6b, 0x36, 0x6d,
+ 0x4c, 0xb6, 0x04, 0xb5, 0xc5, 0xea, 0xf6, 0xf0, 0x49, 0xed, 0xe4, 0x61,
+ 0x92, 0x02, 0x2a, 0x2f, 0x31, 0x6a, 0x22, 0x5d, 0xd7, 0x15, 0x72, 0x95,
+ 0xc9, 0x4b, 0x22, 0x88, 0xd4, 0xab, 0x9a, 0xf3, 0x2f, 0xa5, 0x1b, 0xbe,
+ 0x94, 0xea, 0x58, 0xa8, 0x97, 0xe6, 0x9c, 0xf9, 0x26, 0x05, 0x2f, 0xfe,
+ 0x55, 0x74, 0x3e, 0x5b, 0x91, 0x4b, 0x78, 0x55, 0x4f, 0x5b, 0xeb, 0x75,
+ 0x05, 0xcf, 0xd1, 0x89, 0x9f, 0xe0, 0xcc, 0x66, 0x51, 0x07, 0xaa, 0xb9,
+ 0x6f, 0x8e, 0x46, 0xf0, 0x08, 0xe5, 0x78, 0xf0, 0x3a, 0x06, 0xd3, 0xd1,
+ 0xfc, 0xbe, 0xb9, 0x21, 0x2f, 0xb5, 0x9e, 0xb7, 0xaa, 0xc6, 0x74, 0x52,
+ 0xeb, 0x38, 0x5b, 0x12, 0x3b, 0x9e, 0x52, 0xd6, 0x44, 0xf7, 0x98, 0x3d,
+ 0x38, 0x78, 0x30, 0xce, 0x3e, 0x41, 0xdc, 0x3b, 0x9f, 0x58, 0x7f, 0x4c,
+ 0x7e, 0x85, 0xb8, 0xd5, 0x93, 0x45, 0xa5, 0x6d, 0x75, 0x44, 0xb7, 0x16,
+ 0x39, 0x74, 0x44, 0x7b, 0x02, 0xbe, 0x35, 0x60, 0x32, 0x96, 0x16, 0x6a,
+ 0x99, 0x33, 0x76, 0x17, 0x2a, 0x31, 0x8b, 0x81, 0x1f, 0x69, 0xf1, 0x1c,
+ 0xfa, 0x99, 0xd8, 0x9a, 0xb8, 0x2b, 0x4a, 0xdd, 0x22, 0xcf, 0xf3, 0x3a,
+ 0xbd, 0xbf, 0x1f, 0xd6, 0x19, 0x97, 0x6c, 0xad, 0xeb, 0x19, 0x72, 0x4a,
+ 0xdb, 0x35, 0x6e, 0x07, 0xdf, 0x4a, 0x81, 0xeb, 0xcb, 0xfc, 0x8a, 0x42,
+ 0x13, 0xf1, 0x6f, 0x2c, 0x83, 0x5e, 0x73, 0xe7, 0xa5, 0x4e, 0xb0, 0x7b,
+ 0xd0, 0xb1, 0x4b, 0xe0, 0x57, 0x49, 0x7c, 0x16, 0x73, 0x4d, 0x01, 0xc5,
+ 0x9b, 0x84, 0xa9, 0x39, 0xf4, 0xb6, 0xa4, 0x60, 0xe4, 0x5e, 0x9a, 0x01,
+ 0x76, 0xca, 0xf6, 0xc1, 0xd7, 0x3e, 0x96, 0xc3, 0xb5, 0xcb, 0xb2, 0x7e,
+ 0x57, 0x05, 0x94, 0xd2, 0xe8, 0x2a, 0x1c, 0x64, 0x45, 0xdb, 0x94, 0xc1,
+ 0xcc, 0x92, 0x35, 0x30, 0x4a, 0x1a, 0xd0, 0xe7, 0x55, 0x29, 0xef, 0xaa,
+ 0x80, 0x5c, 0xff, 0xd3, 0x1f, 0x41, 0xb0, 0x6f, 0xa7, 0x0b, 0x2d, 0xf7,
+ 0xc8, 0xda, 0x78, 0x5e, 0x39, 0xff, 0x41, 0x6d, 0xd5, 0x6b, 0xc7, 0x96,
+ 0xfc, 0xa2, 0x68, 0x2b, 0x16, 0x04, 0xf3, 0xe7, 0xb2, 0x68, 0x0e, 0x86,
+ 0x6e, 0x8c, 0x35, 0x37, 0x32, 0xa5, 0x11, 0x5d, 0x21, 0x91, 0xb0, 0x6a,
+ 0xae, 0x80, 0x22, 0x02, 0x85, 0x5f, 0xc7, 0xf3, 0x56, 0x4e, 0x28, 0x3f,
+ 0xd7, 0xda, 0x05, 0x19, 0xa3, 0x61, 0x02, 0xa9, 0x22, 0x04, 0xaa, 0x73,
+ 0xc5, 0x9e, 0xcd, 0x58, 0x62, 0x4c, 0xc4, 0x8f, 0xf6, 0x51, 0x04, 0x30,
+ 0x0e, 0x7c, 0x36, 0x52, 0x65, 0x7d, 0x2d, 0x81, 0xc8, 0x66, 0x9d, 0x6b,
+ 0x29, 0x50, 0xcf, 0x63, 0x8d, 0x80, 0xfe, 0xf2, 0x90, 0x13, 0x87, 0x02,
+ 0x53, 0x4b, 0xb0, 0xbd, 0xb7, 0x5f, 0xd6, 0xec, 0x5a, 0x0f, 0x59, 0x38,
+ 0xc8, 0x9c, 0x6c, 0xd0, 0x9d, 0x6c, 0xdb, 0x2c, 0x0d, 0xd3, 0x98, 0x91,
+ 0xc9, 0xef, 0x4a, 0x19, 0x17, 0xa7, 0x87, 0x92, 0x9b, 0x4d, 0x3b, 0x01,
+ 0xab, 0x7e, 0x62, 0x74, 0x76, 0x70, 0x36, 0x1d, 0xc7, 0x1b, 0x03, 0x66,
+ 0xda, 0xd4, 0x6e, 0xcb, 0xe3, 0x59, 0x94, 0x99, 0xe7, 0x53, 0xe2, 0xb0,
+ 0x4d, 0x75, 0x40, 0xf8, 0x7b, 0xda, 0x7e, 0x4e, 0x48, 0x27, 0x2c, 0xe8,
+ 0xc7, 0x77, 0xae, 0x04, 0x94, 0x73, 0x2c, 0x3a, 0x81, 0xd4, 0xf1, 0xdf,
+ 0xba, 0x13, 0x89, 0x06, 0xa9, 0x4b, 0x94, 0x90, 0x56, 0x7a, 0xe9, 0x36,
+ 0xc7, 0x30, 0x3c, 0x89, 0xbb, 0x9a, 0xc0, 0x75, 0x5d, 0xda, 0xf4, 0x5e,
+ 0x92, 0xfc, 0xf4, 0x53, 0x3f, 0x21, 0x08, 0xa0, 0x9f, 0x8c, 0x82, 0xf0,
+ 0x93, 0x21, 0xb9, 0x9f, 0xb8, 0x34, 0xcd, 0x4f, 0xb7, 0x86, 0x6b, 0xaf,
+ 0x0a, 0x58, 0xf7, 0xaa, 0x90, 0xa0, 0x62, 0x20, 0xb8, 0x95, 0x14, 0x60,
+ 0x22, 0x8b, 0x32, 0xa7, 0x88, 0xfa, 0x40, 0x44, 0x31, 0xdc, 0x64, 0xb3,
+ 0x33, 0xcb, 0x79, 0xc1, 0xe2, 0xba, 0xb0, 0x1a, 0x70, 0x01, 0xb0, 0x8a,
+ 0xf5, 0x3f, 0xae, 0xbb, 0xbd, 0xf1, 0x6a, 0x3a, 0x89, 0x52, 0x43, 0x0f,
+ 0x06, 0x06, 0x22, 0x66, 0x05, 0x0d, 0x17, 0x5b, 0x65, 0x0b, 0x0f, 0x1d,
+ 0x6e, 0x68, 0x01, 0xa7, 0x64, 0x8d, 0xb9, 0x43, 0x1d, 0x36, 0x50, 0x0e,
+ 0x6f, 0x30, 0x19, 0x92, 0x16, 0xd7, 0x0f, 0x10, 0xc2, 0x02, 0x01, 0xb8,
+ 0xc8, 0xda, 0xa7, 0x25, 0x9e, 0xd3, 0xa4, 0x2c, 0xd3, 0xe5, 0x9b, 0x59,
+ 0xbc, 0x91, 0x16, 0xdb, 0x35, 0xc3, 0x59, 0x1f, 0xac, 0xb7, 0x71, 0x00,
+ 0x57, 0x14, 0xe0, 0x73, 0x90, 0x3e, 0x5c, 0x80, 0x2f, 0x9a, 0xd6, 0xc0,
+ 0x0e, 0x3e, 0x4e, 0x7c, 0x1b, 0x33, 0x83, 0xb6, 0x66, 0x6b, 0x78, 0x15,
+ 0x54, 0xb1, 0x94, 0xfe, 0x55, 0xd7, 0x09, 0xcd, 0xb8, 0x30, 0x0e, 0x31,
+ 0x84, 0xbf, 0xce, 0x25, 0x6f, 0xfc, 0x0c, 0xc0, 0x01, 0x79, 0x74, 0xac,
+ 0xdb, 0x0d, 0xe5, 0xf1, 0x4a, 0x4e, 0x74, 0xc9, 0x8d, 0x1a, 0xf1, 0x10,
+ 0xe1, 0xd2, 0xfa, 0x26, 0x8d, 0xa3, 0x64, 0x8b, 0x24, 0xb9, 0xf3, 0xc1,
+ 0x62, 0x93, 0x51, 0xd9, 0xe7, 0xe2, 0x15, 0x56, 0xf7, 0x48, 0x5c, 0xc5,
+ 0xad, 0xa6, 0x8c, 0xb8, 0xfc, 0x02, 0x45, 0x84, 0xc6, 0xf3, 0x26, 0xe9,
+ 0xad, 0xbc, 0x06, 0x7b, 0xd1, 0xfa, 0x6e, 0x2a, 0xff, 0x53, 0x42, 0xe7,
+ 0x8d, 0xa0, 0xdc, 0x89, 0x84, 0xbc, 0xa1, 0xd7, 0xf9, 0xdf, 0xf5, 0x0a,
+ 0xdf, 0x14, 0x0b, 0x0c, 0xdb, 0xbd, 0x56, 0xa0, 0xa3, 0xf9, 0x37, 0xa4,
+ 0xc5, 0xa4, 0xc8, 0xe1, 0x01, 0x30, 0xef, 0x2d, 0x8b, 0xa9, 0xea, 0xf3,
+ 0x16, 0x4e, 0x6d, 0x35, 0xe3, 0xa5, 0xdc, 0x4c, 0xea, 0x51, 0x4c, 0x6d,
+ 0x9a, 0x4e, 0x62, 0x8b, 0x38, 0xc1, 0xac, 0x25, 0xa9, 0x1f, 0x24, 0x2d,
+ 0x12, 0x42, 0x53, 0xb0, 0x30, 0x3b, 0x9b, 0x36, 0xe9, 0x1c, 0x35, 0x84,
+ 0x11, 0x43, 0x9e, 0x8b, 0x25, 0xb9, 0x77, 0x5d, 0x32, 0x72, 0x44, 0x6f,
+ 0x2f, 0x39, 0x6e, 0xc4, 0x3d, 0xe4, 0xcd, 0x32, 0xbc, 0x22, 0x81, 0xcb,
+ 0xf1, 0xcd, 0xe9, 0xbb, 0x23, 0x1b, 0xcc, 0xca, 0x5a, 0x3e, 0x7d, 0x12,
+ 0xc5, 0x0e, 0x1a, 0x22, 0x26, 0x41, 0xd3, 0x81, 0xfb, 0x61, 0xc9, 0x12,
+ 0x5e, 0x22, 0xa3, 0xcb, 0x2f, 0xee, 0x96, 0xf9, 0x74, 0x03, 0x19, 0xdb,
+ 0x1f, 0xde, 0x1f, 0xff, 0x30, 0x80, 0x15, 0x83, 0x91, 0xb5, 0x6a, 0x4d,
+ 0x5a, 0xd6, 0x94, 0x67, 0x36, 0x56, 0xcd, 0x23, 0xb9, 0xff, 0x72, 0xab,
+ 0xf9, 0xd0, 0x57, 0xc8, 0xbf, 0xc8, 0x0b, 0x76, 0x88, 0x70, 0x83, 0x9b,
+ 0x74, 0xfe, 0x0d, 0x0f, 0x05, 0x6e, 0x07, 0x67, 0x53, 0x47, 0x02, 0x73,
+ 0xdb, 0x2b, 0x91, 0xec, 0x9f, 0x9d, 0x1d, 0xee, 0x5f, 0xec, 0xdb, 0xb9,
+ 0x01, 0x27, 0x03, 0x4c, 0x05, 0xba, 0x29, 0xc9, 0x6d, 0x52, 0xc1, 0x73,
+ 0xfd, 0x4f, 0x94, 0xb3, 0xd1, 0xbd, 0xeb, 0xcf, 0xce, 0x4f, 0xc9, 0xc6,
+ 0xf0, 0xa7, 0x9f, 0xf6, 0x5d, 0x35, 0x5a, 0x54, 0x9b, 0x0b, 0x6b, 0x82,
+ 0xee, 0x6e, 0xd2, 0xf8, 0xee, 0xec, 0xf8, 0xc4, 0xc9, 0xcf, 0xd9, 0xd1,
+ 0xc9, 0x47, 0xda, 0xd0, 0x6a, 0x62, 0x05, 0x27, 0x5d, 0x0d, 0x2c, 0x00,
+ 0x2a, 0x31, 0xac, 0x9e, 0x48, 0xe9, 0x98, 0x98, 0xc2, 0x86, 0xe8, 0x62,
+ 0xcd, 0x8c, 0xbc, 0x6f, 0x84, 0xd6, 0x06, 0xdc, 0x83, 0x02, 0xa3, 0x88,
+ 0xbe, 0xa6, 0xb4, 0x52, 0x5d, 0x70, 0xac, 0xee, 0xf6, 0x38, 0x78, 0x48,
+ 0x66, 0x00, 0x1c, 0xcc, 0x59, 0x72, 0x8d, 0xa1, 0xa1, 0x8c, 0xd6, 0x55,
+ 0x19, 0x0a, 0xce, 0x0e, 0x7b, 0x23, 0x0c, 0x9d, 0x2b, 0x3d, 0x0e, 0x43,
+ 0xbb, 0xf1, 0x60, 0x30, 0x50, 0xab, 0x32, 0x4f, 0xdc, 0x7c, 0x10, 0x3c,
+ 0xd4, 0x68, 0x25, 0x15, 0xe5, 0xf3, 0x71, 0x36, 0xe1, 0xf3, 0x87, 0xae,
+ 0x2c, 0x2f, 0xf8, 0x01, 0xf2, 0x14, 0x6a, 0x32, 0x22, 0xff, 0x30, 0x34,
+ 0x37, 0xaa, 0x35, 0xde, 0x3c, 0x5a, 0x2f, 0xc9, 0x5e, 0x43, 0x7f, 0x6d,
+ 0xed, 0x0c, 0xb7, 0x7b, 0xe1, 0xe8, 0x11, 0xcc, 0x0a, 0xa3, 0x98, 0x02,
+ 0x86, 0x32, 0x06, 0x6c, 0xf9, 0xf4, 0x00, 0x99, 0x81, 0x19, 0x89, 0x74,
+ 0x61, 0x3a, 0x88, 0x8e, 0x65, 0x70, 0x1a, 0x18, 0x2f, 0xd9, 0x2b, 0xe0,
+ 0x38, 0x62, 0x51, 0x22, 0x6d, 0x36, 0x25, 0x6d, 0x08, 0x86, 0x98, 0x5e,
+ 0x7c, 0x81, 0x8b, 0x29, 0x3b, 0x36, 0x3b, 0xeb, 0xfc, 0x28, 0x4a, 0xf5,
+ 0xea, 0x8c, 0x32, 0x4b, 0x03, 0xf6, 0xe3, 0x95, 0xdc, 0xae, 0x65, 0x79,
+ 0xbf, 0xc9, 0x8c, 0x14, 0x38, 0x43, 0xfa, 0x14, 0xd9, 0xd1, 0x5e, 0x73,
+ 0xe1, 0xd0, 0x10, 0xff, 0xdb, 0x8f, 0x25, 0xc9, 0x24, 0x7a, 0x16, 0x6f,
+ 0xa4, 0xbe, 0x16, 0x97, 0x08, 0x46, 0x0c, 0x6e, 0xb4, 0x2a, 0xa3, 0xa0,
+ 0x4e, 0x73, 0x46, 0xa6, 0x41, 0x96, 0xb6, 0x04, 0x8a, 0x5a, 0xe7, 0xb0,
+ 0x1d, 0x05, 0x69, 0xdf, 0x63, 0x91, 0x73, 0x6d, 0x17, 0x2a, 0x1d, 0x9a,
+ 0x33, 0x9a, 0x1b, 0xd5, 0x7c, 0x19, 0xc8, 0x0b, 0xdd, 0xd7, 0x87, 0xc4,
+ 0x62, 0xf3, 0xda, 0xcf, 0x09, 0x82, 0x49, 0x87, 0x9e, 0x28, 0xad, 0xc5,
+ 0x0f, 0xc5, 0xf9, 0x70, 0xa8, 0x02, 0x23, 0xe6, 0xa5, 0x60, 0x93, 0xe1,
+ 0x12, 0xbf, 0x38, 0x38, 0xfb, 0xf8, 0xed, 0xd1, 0xd1, 0xd9, 0xf1, 0xe1,
+ 0xc9, 0x91, 0x54, 0xd6, 0xb1, 0x1f, 0xbd, 0xbf, 0xf8, 0xee, 0xc4, 0xe1,
+ 0x93, 0x89, 0x6b, 0xa8, 0xab, 0xee, 0x53, 0xc8, 0x11, 0x35, 0x77, 0x92,
+ 0x17, 0xcb, 0x7b, 0x2a, 0x97, 0x35, 0x21, 0x5a, 0xde, 0x3f, 0xfe, 0xa1,
+ 0x9f, 0x7c, 0x73, 0x36, 0xf8, 0xf0, 0x43, 0x80, 0x02, 0xe1, 0x05, 0xf9,
+ 0x1a, 0x26, 0xd4, 0x15, 0x2c, 0x6d, 0xcc, 0x2f, 0x6a, 0x4a, 0xb8, 0xb9,
+ 0xab, 0xfe, 0x1b, 0x29, 0xb3, 0xf8, 0x5b, 0x9b, 0x02, 0xc3, 0x30, 0x8d,
+ 0xc2, 0x03, 0xb0, 0xf5, 0xa4, 0x78, 0xb9, 0x7b, 0x41, 0x9e, 0x2f, 0xb7,
+ 0xa5, 0x2c, 0x6d, 0x87, 0x00, 0x1f, 0x92, 0xd7, 0xe6, 0x47, 0x0c, 0x98,
+ 0x67, 0x6b, 0x34, 0xfa, 0x86, 0xaa, 0xd9, 0x3b, 0x14, 0x48, 0x6b, 0x6b,
+ 0x19, 0x6a, 0x80, 0x1f, 0x99, 0x69, 0xc8, 0x4a, 0xe2, 0xac, 0x36, 0x15,
+ 0x61, 0x07, 0x86, 0x4e, 0x5a, 0x1f, 0x47, 0x32, 0xb7, 0xda, 0x4f, 0x16,
+ 0x97, 0x2c, 0x7f, 0xc3, 0x34, 0x45, 0xd3, 0xe9, 0x93, 0x00, 0x72, 0xe1,
+ 0x1c, 0xe9, 0xd9, 0x61, 0xc7, 0x26, 0x80, 0x56, 0x30, 0x41, 0x5e, 0xb6,
+ 0x48, 0x39, 0x57, 0x06, 0x15, 0x6a, 0xe1, 0x66, 0x9a, 0xd3, 0x70, 0x78,
+ 0x74, 0xde, 0x67, 0x50, 0x39, 0x1f, 0x50, 0xce, 0x41, 0x28, 0x8a, 0xb6,
+ 0x10, 0x96, 0xb2, 0xf0, 0x36, 0xf5, 0x9f, 0x87, 0x25, 0x77, 0x53, 0x8d,
+ 0x93, 0xd7, 0x33, 0xf3, 0xe2, 0x6c, 0x45, 0x06, 0x27, 0x17, 0xfa, 0x72,
+ 0x05, 0xcb, 0x3a, 0xb0, 0x21, 0x22, 0x0c, 0xb2, 0x69, 0x04, 0xed, 0xac,
+ 0xd4, 0xf8, 0x1a, 0x58, 0x9b, 0xe8, 0x85, 0x20, 0xdb, 0x6d, 0x1d, 0x41,
+ 0xa6, 0xeb, 0xfd, 0x64, 0x9d, 0xb0, 0x51, 0xe8, 0x5f, 0x30, 0x54, 0xa9,
+ 0xf2, 0xb6, 0xde, 0x0f, 0xb5, 0xda, 0x75, 0x59, 0xf6, 0x75, 0xaa, 0xb7,
+ 0x25, 0xf1, 0x14, 0x70, 0xb1, 0x23, 0x59, 0x80, 0x80, 0x2c, 0x31, 0x16,
+ 0x0e, 0x53, 0x61, 0x07, 0xb9, 0x8b, 0x31, 0xa9, 0x03, 0x6c, 0x70, 0xdb,
+ 0x5c, 0x3b, 0xd5, 0x30, 0x58, 0xb0, 0x08, 0x87, 0xb6, 0xf8, 0xf5, 0xa9,
+ 0xc3, 0x44, 0x6e, 0xe1, 0xd6, 0x6b, 0x4d, 0xba, 0xe7, 0x96, 0x08, 0xe2,
+ 0x25, 0x56, 0x38, 0xf4, 0xbe, 0xe1, 0x14, 0x39, 0xba, 0xe7, 0x29, 0xb2,
+ 0x1b, 0x80, 0x9d, 0xdf, 0x91, 0x7a, 0xa5, 0x0e, 0x2c, 0x86, 0x63, 0x94,
+ 0xd8, 0x9b, 0x0a, 0x02, 0x4e, 0x04, 0xdb, 0x09, 0x00, 0xf8, 0x79, 0xf3,
+ 0x3b, 0x92, 0xce, 0x0c, 0x80, 0xf1, 0x79, 0xdd, 0x0c, 0xc8, 0x1f, 0xb4,
+ 0x3a, 0x8d, 0x5a, 0x32, 0x03, 0xd4, 0x23, 0xe5, 0x01, 0xb6, 0x32, 0x6b,
+ 0xe0, 0xaa, 0x38, 0x08, 0xa1, 0xaa, 0xb5, 0xb6, 0xec, 0x20, 0x86, 0xc8,
+ 0x6f, 0xce, 0x5b, 0x76, 0xd7, 0x72, 0x9b, 0x7a, 0x00, 0x37, 0xd6, 0x4f,
+ 0x9a, 0x5f, 0xda, 0x32, 0x49, 0x15, 0x10, 0x64, 0x23, 0xc8, 0x43, 0xf3,
+ 0x74, 0x72, 0x6d, 0xe4, 0xb2, 0x01, 0x22, 0x31, 0x7d, 0x04, 0x14, 0x84,
+ 0x7d, 0x76, 0x07, 0x4a, 0xf9, 0x72, 0x12, 0xde, 0x15, 0x2f, 0x13, 0xe7,
+ 0xa5, 0x41, 0xd0, 0x10, 0x6d, 0x3c, 0x19, 0x83, 0x12, 0xda, 0x44, 0x58,
+ 0x28, 0x80, 0x65, 0x65, 0xc1, 0x0d, 0xad, 0xbf, 0x2e, 0xe2, 0x91, 0x12,
+ 0xe4, 0x42, 0x8f, 0xb9, 0x0b, 0x9c, 0x4d, 0x9a, 0xbc, 0x3f, 0x19, 0xb9,
+ 0x24, 0x10, 0xd6, 0x8b, 0xa5, 0x20, 0x9e, 0x20, 0x7f, 0x46, 0x3d, 0x0a,
+ 0x7e, 0xf8, 0xd3, 0xc9, 0x71, 0xa4, 0xe2, 0x26, 0xe9, 0xda, 0x7b, 0xe6,
+ 0x2c, 0x41, 0xde, 0x46, 0x00, 0xb8, 0xfa, 0x32, 0x15, 0x13, 0x96, 0xf6,
+ 0x80, 0xdd, 0xc4, 0x2c, 0x68, 0xe7, 0x95, 0x9f, 0x09, 0xd4, 0x6d, 0xce,
+ 0x8c, 0xf2, 0x2f, 0x6c, 0xa2, 0x94, 0x00, 0x13, 0x8d, 0x5b, 0xab, 0x97,
+ 0xe3, 0x81, 0x97, 0x9a, 0xcb, 0x0c, 0x01, 0xd0, 0x31, 0xf9, 0x84, 0x14,
+ 0xe7, 0x9b, 0x30, 0xda, 0x63, 0xe3, 0xec, 0xf4, 0xec, 0x99, 0x90, 0x93,
+ 0xe4, 0x51, 0xb7, 0x9c, 0x87, 0x93, 0x84, 0xa4, 0x1f, 0x41, 0x6a, 0xa2,
+ 0x67, 0x6d, 0xf4, 0x27, 0x53, 0x57, 0xac, 0x48, 0x17, 0xa3, 0xb4, 0xd3,
+ 0x52, 0x74, 0x16, 0x53, 0x5c, 0x00, 0xed, 0x88, 0x31, 0xca, 0xea, 0xb4,
+ 0x61, 0x84, 0x11, 0x34, 0x0c, 0x75, 0xde, 0x2b, 0x19, 0x4a, 0x74, 0x7a,
+ 0x8b, 0x08, 0xf5, 0xd8, 0x7a, 0xc3, 0xa6, 0xb0, 0x99, 0x20, 0x2b, 0x83,
+ 0xaa, 0x67, 0xe7, 0x53, 0xce, 0xac, 0xae, 0xdb, 0xa9, 0xd5, 0x9c, 0x27,
+ 0x80, 0x22, 0x17, 0xe4, 0xa3, 0x05, 0x08, 0xd9, 0xaa, 0x9d, 0xd4, 0xe4,
+ 0x78, 0x0a, 0xe5, 0x24, 0xbb, 0x07, 0x07, 0x72, 0xfe, 0xc0, 0x0e, 0x29,
+ 0x8e, 0x19, 0xb4, 0xc9, 0xfb, 0x7d, 0x9f, 0x29, 0x44, 0xe0, 0xdb, 0xbd,
+ 0xe2, 0x5b, 0x9c, 0x8a, 0x64, 0x74, 0x59, 0x23, 0xa1, 0xd9, 0x95, 0x93,
+ 0x95, 0x12, 0x17, 0x8f, 0xcc, 0x9b, 0xfc, 0x3b, 0xe6, 0x97, 0x98, 0x0f,
+ 0x1c, 0xdb, 0x45, 0x3e, 0xa6, 0x65, 0x91, 0xff, 0x9d, 0xe2, 0xb9, 0x98,
+ 0xd5, 0x5f, 0x52, 0x58, 0x9d, 0xba, 0x80, 0x10, 0x84, 0x90, 0x37, 0xeb,
+ 0x35, 0x62, 0x8b, 0x64, 0x51, 0x22, 0x47, 0xf9, 0x26, 0xf3, 0xe3, 0x20,
+ 0xdb, 0x02, 0xd9, 0xee, 0x4e, 0x2b, 0x59, 0xbe, 0x55, 0xe3, 0x22, 0xea,
+ 0xea, 0x47, 0x15, 0x84, 0x4d, 0xb5, 0x76, 0xca, 0xa2, 0x73, 0x3c, 0x45,
+ 0xed, 0x42, 0xcd, 0xa5, 0x2f, 0x0e, 0xb2, 0xbf, 0xca, 0x80, 0x49, 0xd5,
+ 0x1d, 0x17, 0xf2, 0x03, 0x10, 0x74, 0xa9, 0x48, 0x48, 0x4d, 0x62, 0xcb,
+ 0x6b, 0x6c, 0x90, 0x74, 0x3d, 0xf1, 0xc3, 0xd4, 0xba, 0x45, 0x2e, 0x22,
+ 0x38, 0x12, 0x69, 0xf2, 0xec, 0x87, 0x1f, 0x92, 0x16, 0x34, 0xd7, 0x66,
+ 0x6b, 0xe3, 0x3c, 0x6f, 0xad, 0xd8, 0x46, 0xcc, 0x85, 0x1b, 0xe5, 0x09,
+ 0x4a, 0x00, 0x42, 0x5c, 0xe4, 0x74, 0x85, 0x56, 0x3c, 0xb4, 0x51, 0xc0,
+ 0x4d, 0x79, 0x95, 0x61, 0x1b, 0x98, 0x6c, 0xfc, 0xb0, 0x8f, 0xf0, 0x32,
+ 0x76, 0xf1, 0x13, 0x7d, 0x1b, 0xb8, 0xc8, 0x6e, 0x66, 0x44, 0xa3, 0xe8,
+ 0x62, 0xd1, 0x5a, 0xd5, 0xf6, 0x3a, 0x31, 0x42, 0xc0, 0x5d, 0x31, 0x8c,
+ 0x55, 0x25, 0xe9, 0x88, 0x18, 0x36, 0x00, 0x58, 0x22, 0x7e, 0xb8, 0x3c,
+ 0x0b, 0x0a, 0xaa, 0x90, 0xbd, 0xcd, 0xab, 0x06, 0x2b, 0xb1, 0xc6, 0x41,
+ 0xc0, 0x00, 0x1b, 0xf7, 0x29, 0x34, 0x00, 0x13, 0xa4, 0x84, 0x1a, 0xe6,
+ 0x40, 0x49, 0x03, 0xff, 0x98, 0x7a, 0xff, 0xfc, 0xbd, 0xc2, 0xe3, 0x31,
+ 0xa3, 0xc3, 0x1d, 0x4a, 0x87, 0x30, 0x2a, 0xa7, 0xd8, 0x23, 0x11, 0x26,
+ 0x20, 0x99, 0x1a, 0x4c, 0xfc, 0x7f, 0x76, 0xe5, 0x40, 0x6d, 0xc8, 0x1b,
+ 0x93, 0x5e, 0x90, 0x5d, 0x41, 0x2e, 0xfd, 0xa6, 0x5a, 0x62, 0x85, 0x48,
+ 0x0f, 0xa1, 0x1c, 0xaf, 0xd2, 0xe1, 0xf2, 0x90, 0x48, 0xa9, 0xe1, 0x10,
+ 0x00, 0xbe, 0xe7, 0x38, 0xe3, 0x39, 0x20, 0x48, 0x42, 0x87, 0xaf, 0xce,
+ 0x8c, 0x41, 0x15, 0x60, 0x53, 0x6b, 0x3b, 0x14, 0x07, 0x83, 0x79, 0x7a,
+ 0x3f, 0xc0, 0x63, 0x75, 0x00, 0xc1, 0xdc, 0x0a, 0xa3, 0x67, 0xf0, 0xbb,
+ 0x72, 0x26, 0x65, 0x58, 0xec, 0x9a, 0xa9, 0xba, 0x68, 0x23, 0xd9, 0x25,
+ 0xfe, 0x90, 0x48, 0xc8, 0x9c, 0xba, 0xaf, 0x8f, 0x2e, 0xba, 0x47, 0x0b,
+ 0xf9, 0x3c, 0xa2, 0x7b, 0x23, 0x84, 0x9c, 0x8a, 0x7b, 0x7c, 0xb8, 0xd8,
+ 0x74, 0xf6, 0x95, 0x69, 0xd9, 0x31, 0x02, 0xda, 0xb0, 0xe6, 0x10, 0x86,
+ 0x90, 0x83, 0xb6, 0x85, 0xc3, 0x02, 0x67, 0xd0, 0x9e, 0x09, 0x2a, 0x1a,
+ 0xf4, 0x6c, 0x7b, 0xa7, 0x6f, 0x7e, 0xec, 0xc2, 0x8c, 0xf5, 0x6c, 0xfb,
+ 0x99, 0xf5, 0xb7, 0xe8, 0x53, 0x81, 0x75, 0x7e, 0xca, 0x2f, 0x3a, 0x0b,
+ 0xff, 0xb3, 0xfb, 0x7b, 0x7c, 0xdc, 0xef, 0x66, 0xa2, 0xd6, 0x52, 0x65,
+ 0xe8, 0x11, 0x57, 0x84, 0x0e, 0xdc, 0xad, 0x38, 0xec, 0x51, 0xcb, 0x82,
+ 0xe3, 0x68, 0xc8, 0x96, 0x80, 0xb8, 0xf0, 0xe1, 0x6a, 0x8c, 0xa6, 0xa6,
+ 0x95, 0xfb, 0x49, 0x6b, 0xeb, 0xa3, 0x34, 0x19, 0x72, 0xa1, 0xf9, 0x6b,
+ 0x3f, 0x12, 0x65, 0x1e, 0x30, 0x46, 0x7a, 0x46, 0xf2, 0x18, 0xcd, 0x2a,
+ 0xdc, 0xbb, 0x35, 0xb2, 0x00, 0x57, 0x32, 0x11, 0xc3, 0x2c, 0x85, 0x15,
+ 0xa9, 0x4a, 0xbd, 0x0a, 0xfd, 0x6c, 0x8f, 0x22, 0x2b, 0xcd, 0xa9, 0xc0,
+ 0x0a, 0xeb, 0xaf, 0xbb, 0x1c, 0xb5, 0xc9, 0x7f, 0x3c, 0xf3, 0x55, 0x0b,
+ 0x2d, 0xe5, 0x14, 0x85, 0x30, 0xdf, 0xe7, 0xc2, 0x42, 0x9d, 0x50, 0x7f,
+ 0x3a, 0x83, 0xb4, 0x0b, 0x94, 0x02, 0x42, 0x82, 0xb4, 0x24, 0x11, 0x3b,
+ 0xbf, 0x25, 0x2b, 0x55, 0x91, 0x52, 0x01, 0xb4, 0x43, 0x40, 0x8a, 0xd3,
+ 0x0a, 0x52, 0x03, 0x9e, 0xe3, 0x41, 0x22, 0x5e, 0x67, 0xde, 0x66, 0x71,
+ 0x94, 0x4a, 0x4e, 0x02, 0x7b, 0x6c, 0x57, 0xe0, 0x9c, 0x30, 0x98, 0xb3,
+ 0x91, 0xed, 0x6f, 0xd3, 0x19, 0x03, 0xf3, 0xd8, 0xe8, 0xea, 0x4a, 0xc7,
+ 0xc4, 0x51, 0xb9, 0x2e, 0xa8, 0x89, 0xde, 0xfb, 0xc3, 0x93, 0x19, 0x0d,
+ 0x4f, 0x09, 0xdd, 0x2e, 0x34, 0x27, 0x06, 0x29, 0xd4, 0x12, 0xc7, 0x1f,
+ 0x4d, 0xd2, 0x04, 0xbb, 0x18, 0x40, 0xef, 0x7e, 0x6d, 0x44, 0x8e, 0x6c,
+ 0xba, 0xca, 0x0b, 0x8e, 0x28, 0xc8, 0xf4, 0x3e, 0x9f, 0x2f, 0xe7, 0x2e,
+ 0xc1, 0x0e, 0xef, 0xd9, 0x6a, 0x96, 0x0e, 0xe0, 0x95, 0x2b, 0xa1, 0xc6,
+ 0x68, 0x04, 0xc8, 0x6c, 0x2e, 0xdb, 0x17, 0xaa, 0x21, 0xe0, 0xc3, 0x14,
+ 0xa0, 0x42, 0xa2, 0xe2, 0x64, 0x01, 0x44, 0x4e, 0xa2, 0x2e, 0x10, 0x13,
+ 0x94, 0x06, 0x72, 0x30, 0x95, 0xf9, 0x30, 0xd7, 0x46, 0xbe, 0xc8, 0x74,
+ 0xdb, 0xd7, 0xa7, 0x2c, 0x1e, 0x63, 0x13, 0xec, 0x50, 0x51, 0x49, 0x94,
+ 0x23, 0x6a, 0xf0, 0x05, 0x5d, 0x07, 0x41, 0x20, 0xc8, 0xd8, 0x34, 0x71,
+ 0x97, 0x4f, 0x9b, 0x6b, 0x00, 0x2e, 0x6a, 0x4c, 0x13, 0x50, 0x40, 0xac,
+ 0xb0, 0x11, 0x49, 0xba, 0x89, 0x22, 0x63, 0xcb, 0x16, 0x61, 0x51, 0x13,
+ 0xc6, 0x36, 0xa1, 0xb0, 0x6f, 0xec, 0x03, 0x22, 0x26, 0xb7, 0xd8, 0xf8,
+ 0x62, 0xd3, 0xf8, 0x8d, 0xcc, 0xb7, 0xbc, 0x24, 0x24, 0xc5, 0x40, 0x7a,
+ 0xd4, 0x3c, 0x99, 0xa1, 0x9e, 0x09, 0x24, 0xe5, 0xdd, 0x30, 0x98, 0xd9,
+ 0xb7, 0xa2, 0x8f, 0x32, 0xe0, 0x14, 0x8e, 0x3f, 0x67, 0x69, 0x90, 0x7d,
+ 0x3e, 0xb9, 0xc9, 0x67, 0x81, 0x4d, 0x02, 0xbd, 0x9b, 0x6b, 0x6b, 0x7d,
+ 0xce, 0x29, 0x6e, 0xef, 0xd6, 0x25, 0x06, 0x84, 0x30, 0xd1, 0x32, 0x89,
+ 0xe7, 0xec, 0x0b, 0x36, 0xe2, 0xfa, 0x15, 0x77, 0xf3, 0xb5, 0x7b, 0xa8,
+ 0xd3, 0x9c, 0x0b, 0x01, 0x55, 0x23, 0x75, 0xbd, 0x97, 0xec, 0x6e, 0x6f,
+ 0x7f, 0x6b, 0x58, 0xec, 0x1c, 0x9b, 0xb2, 0xf3, 0x75, 0x74, 0x85, 0x78,
+ 0x81, 0x40, 0x43, 0x02, 0x4b, 0x92, 0xde, 0xc2, 0x94, 0x2c, 0x8b, 0xc6,
+ 0x05, 0x44, 0x0d, 0x03, 0x98, 0x2e, 0x3d, 0xeb, 0x5f, 0x74, 0xe3, 0x6c,
+ 0xd2, 0x29, 0x19, 0x1a, 0xbb, 0x18, 0x0b, 0x73, 0xa4, 0x1f, 0xd0, 0xce,
+ 0x5f, 0x9b, 0xdf, 0x32, 0x8f, 0x28, 0xd0, 0x4f, 0x24, 0xe7, 0xdc, 0xc8,
+ 0x1d, 0x84, 0x5e, 0xb7, 0xac, 0xa8, 0x54, 0x22, 0x02, 0x2c, 0x01, 0xfd,
+ 0x04, 0xe3, 0x67, 0xde, 0xb0, 0xdb, 0xa6, 0x28, 0x19, 0x4b, 0x04, 0x64,
+ 0xd1, 0xb4, 0xa6, 0x13, 0xb1, 0xc7, 0x11, 0x05, 0xe3, 0x86, 0xd7, 0x18,
+ 0xe4, 0xc1, 0x5f, 0x89, 0x3f, 0x62, 0x00, 0x7c, 0x08, 0xad, 0x4f, 0x91,
+ 0x21, 0xda, 0xfc, 0x9c, 0xb4, 0xee, 0x64, 0x89, 0x2e, 0xa5, 0x84, 0x09,
+ 0x69, 0x9d, 0xb0, 0x56, 0x62, 0x8e, 0x84, 0xd5, 0xbb, 0x10, 0x40, 0x4b,
+ 0x1a, 0x08, 0xb7, 0x0c, 0xc3, 0xea, 0x8c, 0x1e, 0x98, 0x91, 0x46, 0x5d,
+ 0x06, 0x89, 0x30, 0xb3, 0x05, 0x2c, 0xb6, 0xf6, 0x32, 0xf2, 0x06, 0x45,
+ 0x19, 0xbe, 0x13, 0xa0, 0x85, 0x53, 0xa2, 0xc8, 0xef, 0x68, 0x64, 0x02,
+ 0xae, 0x1d, 0xc3, 0x68, 0xbc, 0x36, 0x04, 0xfc, 0xc5, 0x8f, 0x54, 0x3c,
+ 0xf0, 0xe7, 0x48, 0x99, 0xc4, 0x54, 0x32, 0xa5, 0xe8, 0x28, 0x69, 0x3e,
+ 0x52, 0xe5, 0xaa, 0x78, 0xa0, 0x1d, 0x4e, 0xe7, 0xd5, 0x62, 0x85, 0xae,
+ 0xf8, 0x49, 0x3c, 0xd6, 0x56, 0x8d, 0xe5, 0x1b, 0x35, 0x81, 0xc6, 0xb4,
+ 0x80, 0xf2, 0x18, 0xff, 0x4b, 0x1b, 0xa2, 0x7b, 0xb1, 0x60, 0xf6, 0x84,
+ 0x80, 0xad, 0x2e, 0xd5, 0x4c, 0x52, 0xba, 0x45, 0x6c, 0x10, 0x13, 0x9a,
+ 0xd0, 0xf9, 0x8e, 0x97, 0xf5, 0x03, 0x61, 0x02, 0xb1, 0x73, 0xa0, 0x2e,
+ 0x2d, 0x30, 0x22, 0x16, 0x10, 0xc3, 0x0f, 0xe3, 0xbe, 0x08, 0xb6, 0x86,
+ 0x83, 0x7c, 0x9b, 0xd2, 0xdc, 0xf2, 0x69, 0x55, 0x19, 0x51, 0x4d, 0xb6,
+ 0x5a, 0x92, 0xd4, 0xcc, 0xd8, 0x49, 0xf5, 0x81, 0x39, 0xc8, 0x5a, 0xfd,
+ 0x4d, 0xdb, 0xcb, 0x45, 0x24, 0x50, 0x8b, 0xb2, 0x56, 0x03, 0xa8, 0xb0,
+ 0x56, 0x4a, 0xb8, 0xaa, 0x1f, 0x2a, 0x6e, 0x3e, 0xa6, 0x01, 0x9d, 0x10,
+ 0x97, 0x6d, 0x2b, 0x4c, 0x92, 0x14, 0xc7, 0xc2, 0x90, 0xa0, 0x82, 0xab,
+ 0x4f, 0x61, 0x45, 0x16, 0x72, 0xf2, 0x67, 0x87, 0x7e, 0xc7, 0x45, 0x53,
+ 0x20, 0x56, 0x7b, 0xaa, 0x54, 0x4d, 0x81, 0x0a, 0xa4, 0x29, 0x3a, 0x91,
+ 0xbc, 0x8c, 0x62, 0x59, 0xd3, 0x33, 0x25, 0x2b, 0x95, 0x6c, 0x4d, 0x68,
+ 0xaa, 0x72, 0xba, 0x9c, 0xc0, 0xc2, 0x42, 0x21, 0x69, 0x54, 0xe9, 0x7c,
+ 0xcc, 0x60, 0x5c, 0x9a, 0x1a, 0x4e, 0x4d, 0x5b, 0x79, 0xb8, 0xd3, 0x1c,
+ 0x6c, 0x85, 0x52, 0xa9, 0x08, 0x0f, 0xe2, 0x0f, 0x36, 0xfd, 0xd2, 0x3d,
+ 0x43, 0x3e, 0x3f, 0x8b, 0xdb, 0xda, 0x85, 0x4a, 0x2e, 0x2e, 0x57, 0x80,
+ 0x4f, 0xb3, 0x77, 0x91, 0xd4, 0x81, 0xfb, 0xc6, 0xc6, 0x54, 0xa4, 0x5c,
+ 0xb0, 0x1b, 0x92, 0xea, 0x57, 0x14, 0x07, 0xdb, 0x69, 0xcf, 0x87, 0x54,
+ 0x9e, 0xf7, 0x45, 0x40, 0x7f, 0xd4, 0x41, 0xf4, 0x4e, 0xef, 0x6a, 0xf0,
+ 0xac, 0x42, 0x2d, 0xfd, 0xbc, 0xaa, 0xcc, 0x8d, 0x14, 0x2a, 0xc2, 0x4c,
+ 0xa9, 0x24, 0x21, 0xc7, 0xc9, 0x28, 0x91, 0xc8, 0x03, 0xc3, 0x73, 0x86,
+ 0x1e, 0x5a, 0x96, 0xdc, 0xcd, 0x24, 0xb5, 0x13, 0x0e, 0x10, 0x8d, 0x54,
+ 0xeb, 0x22, 0x8c, 0x29, 0x47, 0x22, 0xf9, 0x5b, 0x39, 0x16, 0x05, 0x8f,
+ 0xe4, 0xd2, 0x58, 0x02, 0xd9, 0x25, 0x42, 0xb1, 0x0d, 0x8f, 0x35, 0xfc,
+ 0x9d, 0x43, 0x36, 0x68, 0x40, 0x45, 0xd6, 0x10, 0xb7, 0x41, 0xa0, 0x36,
+ 0x2c, 0x3d, 0x89, 0x94, 0xa5, 0x46, 0xe4, 0x2d, 0xf1, 0x00, 0xb2, 0xb4,
+ 0x75, 0x9a, 0xfb, 0x6c, 0xf8, 0x6c, 0x97, 0xd2, 0x7b, 0x7c, 0x66, 0x94,
+ 0x4e, 0x48, 0xdb, 0xaa, 0x13, 0x4d, 0x3f, 0x41, 0x56, 0x98, 0x70, 0x73,
+ 0xa9, 0x01, 0xbf, 0x14, 0x1e, 0x35, 0x08, 0xfd, 0xa0, 0xa2, 0x72, 0x64,
+ 0x84, 0x17, 0x57, 0x63, 0x01, 0x4d, 0x7b, 0xcb, 0x2a, 0x9d, 0x3c, 0x28,
+ 0x16, 0xad, 0x0b, 0xc1, 0xa2, 0x26, 0x4a, 0xa0, 0x47, 0xf0, 0xd3, 0x01,
+ 0xc4, 0x7a, 0x61, 0x07, 0x41, 0x5c, 0x3b, 0xaf, 0x19, 0xca, 0xa6, 0x53,
+ 0xf6, 0x46, 0x8e, 0xef, 0x40, 0x5b, 0x5b, 0xa1, 0x77, 0xfd, 0xa6, 0x2c,
+ 0xf7, 0x2a, 0x2f, 0x06, 0x2a, 0xd0, 0xbf, 0x96, 0x5f, 0x1e, 0x13, 0x00,
+ 0xf1, 0x86, 0x55, 0x01, 0x84, 0xaf, 0xca, 0xed, 0xac, 0xd6, 0xa7, 0x16,
+ 0xdd, 0x3e, 0xa2, 0xc1, 0x58, 0xc4, 0x1e, 0x69, 0xd5, 0x69, 0x16, 0x5e,
+ 0xf4, 0x0e, 0x0a, 0x4a, 0x4e, 0xca, 0x99, 0x35, 0x87, 0x45, 0x43, 0xd0,
+ 0x85, 0xaa, 0xb9, 0x5e, 0x14, 0xaf, 0x87, 0x0c, 0xaa, 0x33, 0x9a, 0x64,
+ 0xbf, 0x01, 0x2c, 0xb8, 0x64, 0x27, 0x06, 0x26, 0xe9, 0xe3, 0x77, 0xfb,
+ 0x67, 0x46, 0x30, 0x22, 0xf3, 0x20, 0x6e, 0xd5, 0xd1, 0x3b, 0x82, 0xc4,
+ 0x61, 0x53, 0x79, 0x7b, 0xf2, 0x8c, 0x62, 0x07, 0x01, 0xc0, 0x2b, 0xda,
+ 0xd4, 0x95, 0xdb, 0xc6, 0x1a, 0x3c, 0xd8, 0x5e, 0x38, 0xa9, 0x42, 0x46,
+ 0xb6, 0x3e, 0x82, 0xad, 0xdb, 0x7d, 0xf6, 0xf9, 0xf3, 0x3e, 0x7e, 0x7b,
+ 0xb1, 0xfd, 0x6a, 0x57, 0x3c, 0x9a, 0xc7, 0x47, 0x17, 0x6f, 0xbb, 0x1a,
+ 0x47, 0x65, 0x94, 0x35, 0xfe, 0x39, 0xc8, 0xd2, 0xea, 0x3a, 0xad, 0x1a,
+ 0x0a, 0x46, 0x1a, 0xd4, 0xf3, 0x66, 0x31, 0xd8, 0xde, 0x1e, 0x36, 0x86,
+ 0xa1, 0xb4, 0xea, 0xd0, 0x3e, 0x1f, 0x6e, 0x6f, 0xfe, 0x9e, 0x04, 0x44,
+ 0x16, 0xba, 0x01, 0x2d, 0x71, 0xf2, 0x7a, 0x45, 0x5d, 0xe3, 0x0d, 0x5a,
+ 0xc1, 0x4d, 0x2f, 0x30, 0x2c, 0x55, 0x68, 0x39, 0xbf, 0x8a, 0x74, 0x5e,
+ 0xb7, 0x63, 0x57, 0x1d, 0x01, 0x44, 0x2e, 0xec, 0xae, 0x73, 0x49, 0xf2,
+ 0x3a, 0x36, 0xd8, 0x3c, 0xd8, 0x3c, 0x6c, 0x72, 0x69, 0xb2, 0x54, 0x21,
+ 0xdf, 0x21, 0x41, 0x8a, 0x79, 0x30, 0x9a, 0xa0, 0x5c, 0x0b, 0xca, 0x41,
+ 0x95, 0x11, 0xb2, 0x0f, 0x5f, 0x42, 0x12, 0xa8, 0xa0, 0x05, 0x76, 0xbb,
+ 0xb3, 0xf2, 0xcd, 0x87, 0x2f, 0xda, 0xb5, 0x9f, 0xb1, 0x26, 0xe0, 0x7b,
+ 0xbf, 0x60, 0x4d, 0xda, 0x4b, 0xe2, 0x6e, 0x3e, 0x16, 0x29, 0x61, 0xb7,
+ 0x16, 0x7f, 0x58, 0x88, 0x67, 0x50, 0x2b, 0x86, 0xf6, 0xe3, 0xc3, 0xdc,
+ 0xee, 0x0e, 0xf3, 0x1e, 0x15, 0xb6, 0x60, 0x23, 0x7e, 0x0d, 0xf1, 0xfd,
+ 0x53, 0x34, 0x3f, 0x3c, 0xbe, 0xa1, 0x1a, 0xcc, 0xa6, 0x07, 0x02, 0x8d,
+ 0xbb, 0x51, 0x15, 0x3b, 0xf8, 0x2f, 0x63, 0xc2, 0x16, 0x1e, 0x75, 0xd6,
+ 0xbe, 0xbc, 0x9d, 0x4e, 0x06, 0xba, 0x04, 0x9f, 0xee, 0xb7, 0x81, 0x5c,
+ 0x22, 0x42, 0x30, 0xea, 0x6c, 0x51, 0xe6, 0x07, 0x8e, 0x8b, 0x9f, 0xe6,
+ 0x87, 0x82, 0x0b, 0x30, 0x49, 0x66, 0xf7, 0x08, 0xad, 0x33, 0x4a, 0xfd,
+ 0xcb, 0x67, 0xa1, 0x09, 0xfc, 0xf4, 0xe2, 0x68, 0x0f, 0x7a, 0x88, 0x4b,
+ 0x68, 0x52, 0x33, 0x15, 0xc7, 0xc1, 0x51, 0x3e, 0x35, 0x41, 0x8f, 0x10,
+ 0x30, 0xa9, 0x3f, 0x3b, 0xae, 0xb9, 0x14, 0xc1, 0xa3, 0x41, 0x3d, 0x68,
+ 0x76, 0x7f, 0x34, 0x2b, 0xb1, 0xc1, 0xb4, 0xc4, 0xb0, 0x35, 0x2e, 0x34,
+ 0xb1, 0x22, 0x8e, 0x97, 0x9c, 0xd5, 0x8b, 0x44, 0x59, 0x26, 0xcf, 0x60,
+ 0xa1, 0x98, 0x38, 0x58, 0x05, 0xb6, 0x2e, 0x2f, 0x2a, 0xfc, 0x9a, 0x55,
+ 0x41, 0xc8, 0x03, 0xd4, 0x6e, 0xf2, 0xd8, 0xd0, 0x62, 0x41, 0xca, 0x70,
+ 0x09, 0x09, 0x5d, 0xe2, 0xad, 0x26, 0x8b, 0xe6, 0x29, 0xe2, 0x1d, 0xd9,
+ 0xe8, 0xca, 0x36, 0xe9, 0xf6, 0x1d, 0xca, 0x31, 0x4b, 0x62, 0x1c, 0xff,
+ 0x06, 0xef, 0x50, 0xac, 0x3a, 0x28, 0x5b, 0x11, 0xc5, 0x9d, 0xc2, 0xfe,
+ 0x1a, 0x50, 0xbb, 0x8e, 0x4e, 0x83, 0x5d, 0x27, 0xf9, 0x22, 0xf7, 0x30,
+ 0x50, 0x6d, 0x70, 0x67, 0x98, 0xf9, 0x4d, 0x5e, 0x11, 0x34, 0x61, 0x0f,
+ 0x53, 0xe9, 0xd2, 0xc7, 0xb9, 0xed, 0x72, 0xf8, 0xc8, 0xd1, 0xf0, 0x07,
+ 0xe6, 0x8f, 0xab, 0x48, 0x6c, 0x8b, 0x5c, 0x54, 0xc8, 0x9a, 0x9e, 0x37,
+ 0xbe, 0x3b, 0x7f, 0xfb, 0x57, 0x9b, 0xb3, 0xb7, 0xd9, 0x8f, 0x1b, 0xd3,
+ 0x75, 0x06, 0x7e, 0xe1, 0x75, 0x2b, 0x41, 0x88, 0x48, 0xd1, 0x5a, 0x3b,
+ 0xf7, 0x47, 0x48, 0x6c, 0xd3, 0x12, 0x91, 0x3c, 0x1b, 0x54, 0xf3, 0x94,
+ 0x0a, 0x30, 0x8b, 0xd8, 0xff, 0x6c, 0xf8, 0x02, 0x8e, 0xa8, 0xb7, 0x07,
+ 0x2f, 0x9e, 0xed, 0xee, 0x6c, 0x0e, 0xc3, 0xdb, 0xe0, 0xc9, 0x69, 0xb6,
+ 0xb7, 0x2c, 0xbb, 0x5f, 0x10, 0xc1, 0x6c, 0x1c, 0xfd, 0x70, 0xf6, 0xde,
+ 0x9b, 0xa0, 0xdd, 0x93, 0x40, 0xac, 0xf3, 0x67, 0xc8, 0x5e, 0x47, 0x3b,
+ 0x47, 0x67, 0xec, 0x0c, 0xa8, 0x82, 0xd3, 0xee, 0x43, 0xc4, 0x87, 0xde,
+ 0xdb, 0x2a, 0xa7, 0x43, 0xd0, 0xa3, 0xf5, 0xe8, 0x9d, 0x18, 0xf9, 0xd5,
+ 0x28, 0x26, 0xa7, 0x04, 0xfa, 0x94, 0xf5, 0xba, 0x35, 0xd7, 0x9f, 0x87,
+ 0xfc, 0x4d, 0x0c, 0xd8, 0x50, 0x27, 0x23, 0x8a, 0xa4, 0xf2, 0x34, 0x07,
+ 0x6a, 0x61, 0x35, 0x01, 0x52, 0x80, 0xac, 0xf1, 0xb6, 0x16, 0x4d, 0xc6,
+ 0x86, 0x65, 0x18, 0x95, 0x27, 0x00, 0x81, 0xb1, 0x6e, 0x1b, 0xb9, 0x4f,
+ 0xfb, 0x8f, 0x40, 0x6a, 0xaa, 0xc4, 0xec, 0x4a, 0xc7, 0x84, 0xb5, 0xc6,
+ 0xac, 0x89, 0xdb, 0x0e, 0xa8, 0xa6, 0x1c, 0x1c, 0x23, 0x52, 0xd4, 0xcb,
+ 0x6a, 0xba, 0x9c, 0x9b, 0xf9, 0x7f, 0x65, 0x13, 0x79, 0x24, 0xf7, 0x80,
+ 0x35, 0xf6, 0x48, 0xb2, 0x40, 0xc6, 0x8e, 0xdf, 0x17, 0xdb, 0xad, 0xf6,
+ 0x86, 0x58, 0x05, 0x7f, 0x98, 0x14, 0xa6, 0xbd, 0x63, 0xa3, 0xb2, 0x49,
+ 0xfb, 0x87, 0x75, 0xb0, 0x6b, 0x73, 0xa3, 0x5b, 0xfb, 0xf7, 0x94, 0x2a,
+ 0xb2, 0x26, 0x25, 0xc9, 0xff, 0x89, 0xec, 0xf7, 0xc6, 0x87, 0xab, 0x64,
+ 0x2f, 0x3d, 0x97, 0x8c, 0x45, 0x9d, 0x2b, 0xba, 0xff, 0x85, 0x41, 0x12,
+ 0x3c, 0x50, 0x48, 0x5b, 0xef, 0xa4, 0x17, 0xcd, 0xc9, 0xd9, 0x00, 0x8b,
+ 0xb4, 0x29, 0xc0, 0x2c, 0xff, 0x3d, 0x4f, 0x36, 0x20, 0x96, 0x7d, 0xfe,
+ 0xe2, 0xf9, 0x26, 0x54, 0x7e, 0x1b, 0xa1, 0xb3, 0x19, 0x71, 0xbe, 0x61,
+ 0xd5, 0x96, 0xb5, 0x4d, 0x36, 0x9e, 0xe7, 0x28, 0xbb, 0x04, 0x3a, 0x77,
+ 0x69, 0x0c, 0xc8, 0xa4, 0x36, 0x27, 0x00, 0x16, 0x25, 0x89, 0x44, 0x08,
+ 0xec, 0x59, 0x08, 0x07, 0xe2, 0xaa, 0x4d, 0xc9, 0x86, 0x1c, 0x0e, 0x77,
+ 0x63, 0xd8, 0x34, 0x6f, 0x8e, 0x3d, 0xc7, 0xf5, 0x60, 0xd3, 0x18, 0x36,
+ 0xc9, 0x06, 0x16, 0xb3, 0x07, 0x43, 0xd7, 0xf0, 0xea, 0xa1, 0xa1, 0xf2,
+ 0x57, 0xe9, 0x5d, 0x44, 0xec, 0x0a, 0x10, 0x8b, 0xbf, 0xdc, 0x75, 0x49,
+ 0x0c, 0xb2, 0xd0, 0xc8, 0xaf, 0x9c, 0x89, 0x41, 0xb7, 0xa7, 0x5d, 0x48,
+ 0x0e, 0xc9, 0x05, 0x2c, 0x14, 0xed, 0xbf, 0xb6, 0x20, 0xf1, 0x3c, 0xae,
+ 0xfe, 0x58, 0x60, 0x6d, 0x9b, 0x67, 0x73, 0x85, 0x08, 0xe6, 0x5b, 0xbd,
+ 0xac, 0x5c, 0x19, 0x17, 0xb6, 0xe7, 0xf0, 0x15, 0x8d, 0xe0, 0xc0, 0x55,
+ 0x78, 0x0b, 0xae, 0x0a, 0xb0, 0x80, 0x03, 0xb4, 0x06, 0xb6, 0xa2, 0x6c,
+ 0x83, 0x25, 0x36, 0x3f, 0x6b, 0x57, 0xdc, 0x50, 0x88, 0x15, 0xd5, 0xdf,
+ 0x2d, 0x51, 0x86, 0xc5, 0x4c, 0xb8, 0xd3, 0xce, 0x32, 0xac, 0x18, 0x3c,
+ 0xd7, 0x33, 0x41, 0xba, 0x35, 0x54, 0x9b, 0x41, 0x98, 0x06, 0x92, 0x6c,
+ 0x60, 0xbc, 0x5b, 0x5b, 0x9b, 0x4f, 0x8e, 0x59, 0x1e, 0x7c, 0x6a, 0x8c,
+ 0x67, 0xac, 0x6e, 0xd0, 0xe2, 0x66, 0x0e, 0x95, 0xc7, 0x0d, 0x82, 0x3a,
+ 0xcd, 0x91, 0x18, 0x4b, 0xf4, 0xc3, 0xf1, 0x82, 0x36, 0xe0, 0xda, 0x48,
+ 0x42, 0xa1, 0x5d, 0x8a, 0xa7, 0xcc, 0xb3, 0x6b, 0x4f, 0x5c, 0x04, 0x57,
+ 0xce, 0x01, 0x17, 0x9e, 0xa0, 0x59, 0x10, 0x64, 0xbe, 0x9e, 0x05, 0x35,
+ 0xb9, 0x8a, 0x4e, 0x5d, 0x0a, 0x6f, 0x7e, 0xac, 0x09, 0x39, 0xa7, 0x32,
+ 0x1f, 0x0b, 0xc6, 0xbc, 0x50, 0xe7, 0x73, 0xc8, 0x8a, 0xf5, 0xe9, 0x4e,
+ 0x91, 0xb6, 0x10, 0xe1, 0x89, 0x1f, 0xa4, 0xc3, 0xa3, 0x0e, 0xe9, 0x90,
+ 0x36, 0x05, 0x6d, 0x42, 0x2b, 0x69, 0x71, 0x9b, 0x46, 0xcb, 0xbf, 0x71,
+ 0xf3, 0x66, 0xac, 0x36, 0xcd, 0x04, 0x73, 0x99, 0xf8, 0xc8, 0xea, 0x8c,
+ 0x03, 0x16, 0x58, 0xea, 0xc6, 0x9a, 0x69, 0x05, 0x32, 0x7c, 0xda, 0x5a,
+ 0xce, 0x3e, 0x1f, 0x52, 0xc4, 0xb0, 0xc7, 0x84, 0x60, 0x20, 0xe2, 0x3f,
+ 0x2a, 0xf6, 0x03, 0xf5, 0xc4, 0x0c, 0xab, 0x5d, 0x40, 0x9c, 0xb3, 0x86,
+ 0xc6, 0x76, 0xa1, 0x25, 0x28, 0x6d, 0xe8, 0xdd, 0xa0, 0x05, 0x59, 0x99,
+ 0x8a, 0xac, 0xa9, 0x26, 0x81, 0x61, 0x09, 0xe9, 0xa2, 0xec, 0xec, 0xa9,
+ 0xd9, 0x19, 0x49, 0x8b, 0x34, 0xc4, 0xc3, 0xa6, 0xfb, 0x8f, 0xf2, 0x4b,
+ 0x69, 0xb3, 0x0c, 0x36, 0xfd, 0x43, 0x11, 0x09, 0x26, 0x5f, 0xaf, 0x6d,
+ 0xf4, 0xbb, 0x04, 0x49, 0x11, 0x93, 0x64, 0x9d, 0x59, 0x25, 0xa0, 0xc4,
+ 0x79, 0xcb, 0x2d, 0x90, 0xf9, 0xc3, 0x22, 0x08, 0x2b, 0x9d, 0xd8, 0x48,
+ 0x2f, 0xce, 0x1c, 0x01, 0xc0, 0x01, 0x67, 0x55, 0xb8, 0xc0, 0x05, 0x28,
+ 0x07, 0x24, 0x05, 0xfb, 0xf8, 0x20, 0x5c, 0x88, 0x2b, 0x32, 0xba, 0xc0,
+ 0x88, 0x40, 0x86, 0x1b, 0xcc, 0x71, 0xc3, 0xdc, 0x0a, 0xc4, 0xcd, 0x9b,
+ 0xc5, 0xc6, 0xce, 0x26, 0xba, 0xd3, 0x9a, 0x24, 0x2b, 0xb2, 0x2c, 0xf9,
+ 0xaa, 0xd1, 0xe0, 0x2e, 0x2a, 0x43, 0xaa, 0x9e, 0x63, 0x78, 0x70, 0x09,
+ 0x8b, 0x9c, 0xe4, 0x3a, 0x90, 0x51, 0x2a, 0xd9, 0xa1, 0x1a, 0x29, 0x46,
+ 0xfe, 0xaf, 0x08, 0x71, 0x32, 0xb6, 0xd2, 0x82, 0xb2, 0x08, 0x6a, 0xae,
+ 0x0e, 0xb7, 0x91, 0x5b, 0x39, 0x99, 0xaf, 0x07, 0x2d, 0x99, 0x6a, 0x56,
+ 0x6f, 0x36, 0x1d, 0x20, 0x8d, 0xf2, 0xaa, 0x2a, 0x43, 0x0c, 0x4c, 0xca,
+ 0xc0, 0x92, 0x1b, 0x84, 0x3d, 0x58, 0xd1, 0x32, 0xb5, 0x3d, 0x4a, 0x78,
+ 0xe9, 0xd9, 0x1b, 0xde, 0xcb, 0xa9, 0xe9, 0xfa, 0x15, 0x5a, 0x5b, 0x1a,
+ 0x90, 0xe9, 0x7e, 0xf2, 0xf7, 0x65, 0x6e, 0xc8, 0x9a, 0xf6, 0x16, 0xe1,
+ 0x8c, 0xc8, 0x9f, 0xc8, 0x6c, 0x10, 0x80, 0xe1, 0x1e, 0x14, 0xe7, 0xc0,
+ 0xb9, 0x58, 0x64, 0xcf, 0x86, 0x4e, 0xaf, 0x54, 0x16, 0x29, 0xc7, 0x0b,
+ 0x63, 0xb3, 0x0a, 0x04, 0x80, 0xbf, 0x2d, 0x45, 0xdc, 0x44, 0x24, 0x1f,
+ 0xc7, 0x76, 0xb0, 0xe4, 0x4c, 0xac, 0x9d, 0xa9, 0x60, 0x55, 0x51, 0x96,
+ 0xf5, 0xf9, 0x03, 0x5d, 0x64, 0xeb, 0xed, 0xea, 0x2c, 0xeb, 0x35, 0x19,
+ 0x04, 0x9b, 0x75, 0x5d, 0x5f, 0x84, 0xeb, 0x3d, 0x52, 0xe0, 0x69, 0x55,
+ 0xd7, 0x4c, 0xda, 0xdc, 0x85, 0x6b, 0x9d, 0x1b, 0x77, 0x47, 0xf0, 0x7d,
+ 0x9f, 0x23, 0xca, 0xc7, 0x4b, 0x0a, 0x38, 0xe9, 0x34, 0x7d, 0xc8, 0xdc,
+ 0x9a, 0xa5, 0x02, 0x7e, 0x42, 0x8a, 0xc7, 0x21, 0x20, 0x90, 0x33, 0x39,
+ 0x6a, 0xca, 0xff, 0x9b, 0x0f, 0xa9, 0x04, 0xa3, 0x20, 0x2f, 0xa2, 0xee,
+ 0x6b, 0x1d, 0x0a, 0x75, 0x4b, 0xae, 0x05, 0xdf, 0x6f, 0x03, 0x6b, 0x77,
+ 0xa2, 0x13, 0xb9, 0x1b, 0x8a, 0x41, 0xf1, 0x9b, 0x8f, 0x39, 0xc7, 0xf1,
+ 0x3a, 0x3c, 0xb6, 0xf0, 0x90, 0xb3, 0xe6, 0xcb, 0x37, 0x8f, 0x98, 0x56,
+ 0xa5, 0x09, 0x0b, 0x69, 0x4f, 0x90, 0x82, 0xd7, 0xcb, 0xe2, 0xc6, 0x0c,
+ 0x21, 0x0c, 0x7b, 0x56, 0x27, 0x47, 0x4e, 0x67, 0xdb, 0x10, 0x08, 0xc0,
+ 0xcc, 0x1c, 0x5c, 0x03, 0xb7, 0x40, 0x60, 0x54, 0xb7, 0x10, 0x4b, 0x82,
+ 0x12, 0x21, 0xb1, 0xd1, 0xc9, 0x75, 0xc7, 0xa3, 0xb2, 0x0b, 0xf8, 0x58,
+ 0x7e, 0xa1, 0x57, 0x3f, 0xa1, 0xc8, 0xae, 0x10, 0x0e, 0x21, 0xf2, 0x28,
+ 0x67, 0x39, 0x2a, 0xcc, 0x0a, 0x14, 0x05, 0x35, 0x74, 0x06, 0x47, 0x76,
+ 0x59, 0x73, 0x4d, 0x33, 0xd9, 0x56, 0xa2, 0x52, 0x1f, 0x1d, 0x30, 0x32,
+ 0x12, 0xe1, 0xc3, 0x83, 0x48, 0x75, 0xbd, 0x8b, 0x2e, 0x0a, 0x62, 0xed,
+ 0xe3, 0xc3, 0xe2, 0xb5, 0x7e, 0x0b, 0x21, 0x96, 0x91, 0x06, 0x39, 0x34,
+ 0xbf, 0x89, 0x60, 0x26, 0x9b, 0x23, 0xb1, 0x61, 0x74, 0x8c, 0x72, 0xb6,
+ 0xe4, 0xb2, 0x4e, 0x64, 0x14, 0xa3, 0x34, 0x8d, 0x4d, 0x3d, 0x4d, 0x7c,
+ 0xfe, 0xd8, 0x70, 0xc1, 0x35, 0xd2, 0xf8, 0x22, 0x88, 0x81, 0x76, 0x22,
+ 0xe8, 0xdb, 0xb7, 0xf9, 0x72, 0x8c, 0xae, 0x6a, 0xef, 0xa4, 0x04, 0x78,
+ 0xcd, 0x2d, 0x10, 0x81, 0x7a, 0x5b, 0x2a, 0x9b, 0x0d, 0x2c, 0x48, 0xaa,
+ 0x4c, 0xf8, 0xeb, 0x61, 0x6d, 0xaa, 0x24, 0x1a, 0xb8, 0x9a, 0x49, 0x7e,
+ 0xd9, 0x00, 0x28, 0x1c, 0xd4, 0xd9, 0xa3, 0x41, 0x12, 0x8f, 0xc4, 0x04,
+ 0x46, 0xd7, 0xda, 0x15, 0xc9, 0x46, 0x38, 0x8a, 0x88, 0xfd, 0x32, 0x34,
+ 0x91, 0xd6, 0x1f, 0x30, 0xaa, 0xf9, 0x92, 0x1c, 0x0d, 0x81, 0xad, 0xd9,
+ 0xec, 0xca, 0x6c, 0xc9, 0xe8, 0xdb, 0xe4, 0xb4, 0x76, 0x22, 0x7a, 0x3a,
+ 0xa6, 0xcd, 0x19, 0x3f, 0xd8, 0x79, 0x6a, 0xea, 0x3a, 0x12, 0xcd, 0x55,
+ 0x9f, 0x0e, 0xc9, 0x43, 0x1f, 0xeb, 0xf4, 0xf3, 0x9d, 0xf0, 0xd6, 0x80,
+ 0x2c, 0xd8, 0x11, 0xe2, 0x63, 0x6d, 0xdc, 0x08, 0x3b, 0x51, 0x26, 0xbb,
+ 0x8c, 0xd8, 0x4c, 0xed, 0x60, 0x54, 0x5c, 0x27, 0x9b, 0x40, 0xaa, 0xc5,
+ 0xb6, 0xd9, 0x95, 0xc1, 0xaf, 0x6b, 0xc6, 0x49, 0xd9, 0x4e, 0x70, 0x32,
+ 0x47, 0xa7, 0x04, 0xbc, 0x75, 0x1c, 0x24, 0xe5, 0x48, 0xea, 0x61, 0xbe,
+ 0xd7, 0xc7, 0x92, 0x8d, 0xd1, 0xd9, 0xfb, 0xa3, 0xaf, 0x4f, 0x37, 0x9f,
+ 0x72, 0x2d, 0x90, 0x6a, 0x0e, 0x97, 0x1d, 0x82, 0x51, 0x70, 0xac, 0x70,
+ 0xc0, 0x23, 0x2d, 0xb1, 0xdb, 0xaa, 0xbc, 0x7f, 0xf0, 0xda, 0x8c, 0x05,
+ 0xdd, 0xf5, 0x39, 0xcd, 0x93, 0xcf, 0x2b, 0x03, 0xc6, 0xd9, 0xe1, 0xff,
+ 0xd2, 0x80, 0x7f, 0x96, 0xc0, 0x70, 0xe9, 0x7c, 0x3d, 0x1a, 0x0d, 0xf6,
+ 0xcf, 0x8e, 0x71, 0x13, 0x8f, 0x46, 0xe6, 0x97, 0x55, 0x88, 0xd4, 0xe0,
+ 0x65, 0x14, 0x4a, 0xf3, 0x5d, 0x3f, 0xf1, 0xc2, 0xfb, 0xe5, 0x4e, 0xcc,
+ 0x58, 0x60, 0xb6, 0x21, 0xfe, 0x2e, 0xa8, 0x9f, 0x3a, 0xe8, 0x5e, 0xb7,
+ 0x67, 0xc7, 0x5b, 0xe8, 0x0b, 0x7e, 0x0d, 0xac, 0x43, 0x3c, 0xa6, 0x6f,
+ 0x19, 0xd6, 0x57, 0xa2, 0x55, 0x45, 0xc6, 0x06, 0xe8, 0x53, 0xd9, 0x47,
+ 0x6a, 0xc4, 0x4f, 0x72, 0x00, 0x2f, 0x31, 0xb6, 0x48, 0x15, 0x56, 0x2f,
+ 0x62, 0x8b, 0xf1, 0xcd, 0x15, 0x74, 0xbd, 0x63, 0xc2, 0x87, 0x85, 0xd6,
+ 0xd6, 0x22, 0x37, 0xe2, 0x15, 0xfb, 0x8b, 0xbb, 0xc6, 0xbd, 0xf5, 0xc1,
+ 0x32, 0xd9, 0x43, 0x89, 0xcb, 0xac, 0xa0, 0xe2, 0xb5, 0x2d, 0xab, 0x99,
+ 0xb0, 0x60, 0x28, 0x0c, 0xf6, 0x42, 0x75, 0x69, 0x97, 0x66, 0x84, 0xcb,
+ 0xf8, 0xe8, 0xcc, 0x09, 0x25, 0xe9, 0x8a, 0xbd, 0x81, 0x1c, 0x9c, 0x3d,
+ 0xfd, 0xa7, 0x00, 0xce, 0xfa, 0x47, 0xc2, 0xcb, 0x1a, 0x7b, 0xec, 0x9a,
+ 0x17, 0x26, 0xe3, 0x32, 0xcc, 0xc4, 0xad, 0x61, 0x23, 0xc0, 0x2f, 0x0e,
+ 0xce, 0xbc, 0x30, 0x80, 0x7e, 0x68, 0xf5, 0x70, 0xe0, 0x2f, 0x92, 0xf5,
+ 0x5a, 0xd8, 0xd6, 0xe7, 0xc3, 0xc7, 0x2a, 0x06, 0x36, 0x9a, 0x50, 0xb1,
+ 0xea, 0xf6, 0xf3, 0x2f, 0x3f, 0x89, 0x45, 0x5d, 0x7d, 0xf5, 0xb9, 0x19,
+ 0x78, 0xb7, 0x9f, 0xfd, 0xb0, 0xb3, 0x34, 0x82, 0xd3, 0x94, 0x4f, 0xa3,
+ 0x99, 0x5a, 0xb2, 0x40, 0x5a, 0x64, 0x44, 0x96, 0x88, 0xf0, 0x75, 0x14,
+ 0x0b, 0xeb, 0xf8, 0xd0, 0x0c, 0x86, 0xe4, 0x30, 0x52, 0x40, 0xbf, 0x7a,
+ 0xb0, 0xf9, 0xe7, 0xa1, 0x00, 0xe9, 0xe2, 0x88, 0xf8, 0x3e, 0x41, 0x45,
+ 0x6c, 0xaf, 0x5c, 0x3a, 0x21, 0xe9, 0x79, 0x88, 0xd7, 0x12, 0x21, 0x25,
+ 0x38, 0x6c, 0x71, 0x00, 0x57, 0x22, 0x0e, 0x04, 0x1d, 0x5e, 0x2f, 0xb9,
+ 0x1e, 0xa6, 0xa0, 0xfc, 0xd8, 0x4a, 0x74, 0x55, 0x06, 0x47, 0x28, 0x0d,
+ 0xd8, 0x1b, 0x71, 0x50, 0xdc, 0x8e, 0x55, 0x72, 0x73, 0xe6, 0xe7, 0x92,
+ 0x82, 0x30, 0xae, 0xca, 0x1b, 0x73, 0x5a, 0xe9, 0x3d, 0xc8, 0xcd, 0xb4,
+ 0xf6, 0x2c, 0xc3, 0xa9, 0x6e, 0x69, 0x6e, 0x94, 0xa9, 0x75, 0x8c, 0x46,
+ 0x22, 0x50, 0x09, 0xd5, 0x5f, 0x92, 0xf5, 0x9c, 0x2c, 0xc4, 0x70, 0xeb,
+ 0xc8, 0xa7, 0x57, 0x80, 0x4e, 0x58, 0xd0, 0xa9, 0xae, 0xb4, 0x77, 0x4d,
+ 0x86, 0x1e, 0x6e, 0xc1, 0xc9, 0xff, 0xe7, 0xd1, 0x90, 0x25, 0x0b, 0x9f,
+ 0x86, 0x22, 0x7b, 0xde, 0x22, 0x26, 0x66, 0xfa, 0xaf, 0x0d, 0x55, 0x31,
+ 0x37, 0x27, 0xd3, 0x5c, 0xd7, 0x36, 0x8c, 0x92, 0x13, 0x03, 0x07, 0x47,
+ 0x03, 0x33, 0x35, 0xb4, 0x11, 0x8a, 0x4a, 0xe1, 0x20, 0x8e, 0xa9, 0xab,
+ 0x90, 0x23, 0x30, 0xa0, 0x7d, 0x66, 0xc6, 0xa1, 0x98, 0x81, 0x14, 0x13,
+ 0x7b, 0x6b, 0xb3, 0x66, 0x05, 0x26, 0x41, 0xfb, 0x03, 0x24, 0xb2, 0xdc,
+ 0xab, 0xb3, 0xf6, 0xaf, 0x3e, 0xd0, 0x07, 0xfa, 0x0a, 0x54, 0x0a, 0xc6,
+ 0x8d, 0xb7, 0x71, 0x32, 0x1c, 0xee, 0x6a, 0xf3, 0x69, 0xa9, 0x66, 0x8b,
+ 0xcf, 0x33, 0x18, 0xa3, 0x34, 0x39, 0xa2, 0xa0, 0x97, 0x88, 0x9e, 0xc3,
+ 0x15, 0xb5, 0x72, 0x9b, 0xc1, 0x93, 0x0b, 0xc6, 0x25, 0x3b, 0x25, 0x44,
+ 0x71, 0x4c, 0xd5, 0xe1, 0x60, 0xa1, 0x90, 0xb8, 0x9e, 0x6a, 0x4c, 0xe7,
+ 0xab, 0x1b, 0xb6, 0xe8, 0x0b, 0x70, 0x80, 0x7e, 0x60, 0xf1, 0xe2, 0xdf,
+ 0xba, 0x38, 0xef, 0x7e, 0xc2, 0x26, 0x24, 0xa8, 0x44, 0x1c, 0x4c, 0x19,
+ 0x9b, 0x6c, 0xe2, 0x3d, 0xe6, 0xbf, 0xb2, 0xf7, 0xf9, 0x76, 0x5f, 0x38,
+ 0x3e, 0x59, 0xed, 0xfc, 0x67, 0x10, 0x84, 0x14, 0xaa, 0x11, 0x80, 0xe4,
+ 0x2b, 0x1b, 0xfb, 0x64, 0xb7, 0xd0, 0xc3, 0xab, 0xe1, 0xf3, 0xcd, 0x16,
+ 0xbd, 0x34, 0xb3, 0x79, 0x57, 0x2e, 0x49, 0xde, 0x5f, 0x9c, 0xbc, 0x4b,
+ 0x02, 0x9b, 0x00, 0x2b, 0xcc, 0xb1, 0xef, 0x02, 0x63, 0x27, 0x62, 0xb1,
+ 0x29, 0x98, 0xdc, 0x08, 0x8f, 0xf9, 0x55, 0xc1, 0x80, 0x47, 0xef, 0xf2,
+ 0x49, 0x55, 0xd6, 0xe5, 0x25, 0xbb, 0x33, 0x55, 0xb9, 0x36, 0x5f, 0x1c,
+ 0x1f, 0x8f, 0x92, 0xbb, 0x6c, 0xac, 0x99, 0x56, 0x41, 0x68, 0x61, 0xc3,
+ 0xe4, 0x43, 0xd7, 0x67, 0x95, 0x67, 0x0d, 0x49, 0x1a, 0x6a, 0xd4, 0xa3,
+ 0xcc, 0x66, 0x7a, 0x27, 0x1b, 0x64, 0x85, 0xd1, 0x37, 0x33, 0xa8, 0x6e,
+ 0x84, 0xdf, 0x3f, 0x03, 0x57, 0x32, 0x02, 0x77, 0x19, 0xb1, 0xec, 0xf2,
+ 0x00, 0x94, 0xa5, 0x08, 0xd8, 0x3b, 0xdd, 0x15, 0xe3, 0xb4, 0xb6, 0xa0,
+ 0x4e, 0x39, 0x8a, 0x6f, 0x90, 0xac, 0x21, 0xe6, 0x98, 0x9b, 0x1c, 0xe9,
+ 0xf3, 0x41, 0x5a, 0xb9, 0xd4, 0x75, 0xec, 0xd8, 0x23, 0x8a, 0x69, 0x59,
+ 0xc1, 0x49, 0xe2, 0x81, 0x14, 0x03, 0xdf, 0x7f, 0x89, 0xf0, 0x4f, 0x70,
+ 0xcd, 0x87, 0x88, 0xc4, 0x7e, 0x5d, 0x0a, 0x66, 0x06, 0xaf, 0x34, 0x31,
+ 0x26, 0x4e, 0x0d, 0x44, 0x62, 0x86, 0xe0, 0xbe, 0x72, 0x3d, 0x21, 0xe5,
+ 0x24, 0x4f, 0x48, 0x78, 0xba, 0x1f, 0x2e, 0x3b, 0x49, 0x8c, 0xed, 0x87,
+ 0xf9, 0xd5, 0x0a, 0xe8, 0x79, 0x1b, 0xef, 0xec, 0x89, 0x98, 0x34, 0x1a,
+ 0x61, 0x97, 0x2a, 0x59, 0x06, 0x05, 0x4e, 0x62, 0x30, 0x1b, 0x2d, 0xc9,
+ 0xd2, 0x50, 0xdb, 0xf0, 0x71, 0xa5, 0xe3, 0x71, 0xb1, 0x12, 0x97, 0x9e,
+ 0x64, 0x8f, 0x6a, 0x52, 0x68, 0x60, 0x1d, 0x7d, 0x24, 0x45, 0xd4, 0xc9,
+ 0x8f, 0x34, 0x9f, 0xe1, 0x3f, 0xa3, 0x60, 0x9b, 0x3b, 0x6c, 0x25, 0x19,
+ 0x3b, 0xc4, 0x28, 0x10, 0xcd, 0x06, 0xf8, 0x9e, 0xf1, 0x8a, 0xc4, 0x6c,
+ 0x50, 0xca, 0x43, 0x7e, 0x02, 0x5e, 0xdd, 0x4c, 0xcb, 0x65, 0x63, 0x41,
+ 0xc3, 0xe9, 0x06, 0xe7, 0xcb, 0xfb, 0x3f, 0xfe, 0x2b, 0xcc, 0x47, 0xfa,
+ 0xf1, 0x67, 0x98, 0xae, 0x80, 0x4b, 0x61, 0x21, 0x1a, 0x94, 0x6c, 0x6a,
+ 0x57, 0x50, 0x83, 0x76, 0x88, 0xf0, 0x97, 0xc4, 0x29, 0x47, 0x12, 0x1f,
+ 0x65, 0x47, 0x74, 0x85, 0x53, 0x8d, 0xb9, 0xd6, 0x0a, 0x85, 0x32, 0x3a,
+ 0x65, 0xfc, 0xa8, 0xf2, 0x93, 0x7a, 0x56, 0x34, 0x55, 0x3e, 0x05, 0xa1,
+ 0x79, 0xba, 0x0a, 0xe0, 0x5b, 0x81, 0x5c, 0x04, 0x22, 0x59, 0xf1, 0x58,
+ 0x08, 0x41, 0x83, 0xfd, 0x3e, 0x98, 0x01, 0x5d, 0x2c, 0x88, 0xc6, 0xcc,
+ 0x8b, 0x10, 0xa7, 0x94, 0xf7, 0x56, 0xfc, 0x1b, 0xff, 0x61, 0x36, 0xa3,
+ 0xdf, 0xdc, 0x95, 0xff, 0x35, 0xa4, 0x88, 0x46, 0x70, 0xde, 0x41, 0xc9,
+ 0xb5, 0xab, 0x3f, 0xfe, 0x71, 0x87, 0x42, 0x88, 0x7a, 0x61, 0x4d, 0x6a,
+ 0x2c, 0x82, 0xee, 0xb3, 0x85, 0xb7, 0x59, 0x01, 0x8b, 0xda, 0xee, 0x8e,
+ 0x7a, 0xe9, 0xd3, 0x25, 0xf0, 0x5f, 0x43, 0xfa, 0xf9, 0xe3, 0xce, 0xe0,
+ 0xc5, 0xcf, 0xb6, 0xd7, 0x3f, 0xee, 0x7c, 0xfc, 0xe3, 0x6e, 0x2f, 0x16,
+ 0x22, 0x26, 0x79, 0x81, 0xed, 0x80, 0xbe, 0x1a, 0x45, 0x41, 0x25, 0x82,
+ 0x56, 0x84, 0x7f, 0xe7, 0xbc, 0x45, 0xc5, 0x93, 0x48, 0xda, 0x07, 0x59,
+ 0xa1, 0xe2, 0x10, 0x84, 0x52, 0xf5, 0x9d, 0xa3, 0xef, 0x5c, 0x79, 0x5c,
+ 0xcf, 0x1b, 0x2a, 0xd5, 0x62, 0x9d, 0x2b, 0x47, 0xcc, 0x99, 0x81, 0xe5,
+ 0x94, 0x92, 0x54, 0xa7, 0x0f, 0xe6, 0xa2, 0x63, 0x04, 0x53, 0x0b, 0x14,
+ 0xa0, 0xa2, 0xa3, 0x90, 0xad, 0xe0, 0x5e, 0x6d, 0xb8, 0x28, 0x28, 0xe0,
+ 0xb5, 0x6d, 0xc6, 0x2c, 0x13, 0xce, 0x24, 0xe4, 0x68, 0x7e, 0x2c, 0x32,
+ 0x29, 0x1d, 0x5e, 0x26, 0x76, 0x77, 0x80, 0xba, 0x30, 0xa2, 0xd1, 0xe3,
+ 0xe3, 0xb5, 0x95, 0xfa, 0xde, 0x29, 0x2e, 0x07, 0x24, 0x59, 0xc5, 0x99,
+ 0x7a, 0xd0, 0x18, 0x03, 0x2f, 0x23, 0xf9, 0xb5, 0x7b, 0xef, 0x6c, 0x9c,
+ 0x3a, 0x3d, 0x67, 0x96, 0xb5, 0xc0, 0xe3, 0xfd, 0x97, 0x3d, 0x6f, 0x78,
+ 0x96, 0x68, 0x95, 0x71, 0x43, 0x21, 0x4d, 0x88, 0xf0, 0x31, 0xdc, 0x8c,
+ 0x66, 0x51, 0x28, 0xd2, 0x37, 0x9b, 0xce, 0x2d, 0x9c, 0x98, 0x04, 0x74,
+ 0x27, 0x35, 0x17, 0xab, 0x21, 0xa5, 0x90, 0x61, 0x4c, 0xc9, 0xee, 0x2f,
+ 0xd0, 0xa5, 0x41, 0x9e, 0x82, 0x54, 0xa0, 0xed, 0x5b, 0xe8, 0xe4, 0x6c,
+ 0x56, 0x87, 0xb4, 0x71, 0x40, 0xae, 0x1e, 0xc2, 0x88, 0x6b, 0x90, 0x36,
+ 0xde, 0x77, 0xb3, 0xb4, 0x69, 0x89, 0xe9, 0xad, 0x73, 0xe1, 0xd8, 0x23,
+ 0xaa, 0x51, 0xf2, 0xab, 0x32, 0xbf, 0x87, 0x9d, 0xdb, 0xc3, 0x46, 0x1e,
+ 0xa5, 0xb6, 0x4c, 0x94, 0x4b, 0x2d, 0x74, 0x29, 0xf0, 0xb1, 0x64, 0x56,
+ 0xd4, 0x0f, 0x00, 0x87, 0xe2, 0xa4, 0x2f, 0x1d, 0x82, 0x8c, 0xc0, 0x73,
+ 0xa4, 0x08, 0xb0, 0x0b, 0x3d, 0xcb, 0x48, 0x5f, 0xf1, 0xc2, 0x04, 0xc2,
+ 0x6d, 0x42, 0x2c, 0xda, 0xcb, 0x59, 0x7a, 0xf5, 0x87, 0x28, 0xfc, 0xab,
+ 0xf8, 0x07, 0x89, 0x13, 0x01, 0xf6, 0x15, 0xfd, 0x02, 0x3f, 0xc1, 0x73,
+ 0x6d, 0x31, 0x32, 0x88, 0x99, 0x76, 0xce, 0x25, 0x3e, 0xfe, 0xb4, 0xbb,
+ 0x1d, 0xb2, 0x62, 0x07, 0x0a, 0xa4, 0x25, 0x7e, 0x88, 0x9c, 0x6a, 0xa5,
+ 0x27, 0x96, 0x27, 0x5d, 0x2d, 0x81, 0x0c, 0x39, 0x43, 0xe4, 0xd2, 0x1f,
+ 0x10, 0x31, 0x05, 0x3a, 0xae, 0xeb, 0x38, 0x1a, 0x7c, 0xfa, 0x6b, 0x59,
+ 0xcb, 0x53, 0x9c, 0xc5, 0xdc, 0x5e, 0x74, 0xe3, 0xef, 0x0e, 0xc6, 0x99,
+ 0xb9, 0x79, 0xba, 0x73, 0xdc, 0xe0, 0xd0, 0x52, 0x4e, 0x3c, 0x6f, 0xc7,
+ 0x50, 0x51, 0x5f, 0x5f, 0xe1, 0x9d, 0xe4, 0x02, 0x3a, 0x1d, 0xd1, 0xf5,
+ 0x29, 0x55, 0x0a, 0x4f, 0x76, 0x87, 0xdb, 0x22, 0xf8, 0x3d, 0x9a, 0xfe,
+ 0xca, 0xc8, 0x1a, 0xad, 0x36, 0xf4, 0x76, 0x46, 0xa5, 0x9e, 0xe2, 0x6f,
+ 0xcb, 0xa2, 0x0d, 0x77, 0x1f, 0x73, 0x73, 0x61, 0xbf, 0x45, 0xc2, 0xe7,
+ 0x78, 0x95, 0x56, 0x80, 0x92, 0x1e, 0x71, 0x31, 0xa7, 0x00, 0x06, 0x0f,
+ 0x16, 0xac, 0xc1, 0x32, 0x94, 0x32, 0xd0, 0xe0, 0xaa, 0xc2, 0x0c, 0x38,
+ 0xd7, 0x32, 0x5a, 0x19, 0xae, 0x62, 0x84, 0x68, 0xc4, 0x53, 0x95, 0x89,
+ 0x97, 0xac, 0xe9, 0x16, 0x7c, 0x3a, 0x7f, 0x7b, 0xd0, 0x69, 0xee, 0xe5,
+ 0x67, 0x2f, 0xb6, 0x7f, 0xcf, 0x78, 0x94, 0x56, 0xa1, 0x88, 0xc7, 0x0b,
+ 0xf1, 0xfc, 0x9a, 0x3a, 0x3c, 0x2b, 0x0b, 0xf1, 0x88, 0xe6, 0xf6, 0x29,
+ 0x75, 0x78, 0x6c, 0x19, 0x9e, 0x38, 0xfa, 0x40, 0x37, 0x4b, 0xd1, 0x45,
+ 0xfb, 0xf8, 0x35, 0x86, 0x50, 0x00, 0xb1, 0xf6, 0x6c, 0xa3, 0x88, 0xf8,
+ 0x5a, 0x16, 0x11, 0x1f, 0xab, 0x98, 0xc0, 0x21, 0xe9, 0xd9, 0xca, 0xcc,
+ 0x07, 0xa7, 0xef, 0xdf, 0x1f, 0x1d, 0xd8, 0xac, 0xd3, 0x9a, 0xa7, 0x69,
+ 0xf9, 0x5d, 0x6a, 0x11, 0x7e, 0xe2, 0x85, 0x78, 0x10, 0xc7, 0x2a, 0x4e,
+ 0x06, 0xee, 0xdf, 0xfc, 0x71, 0x27, 0x11, 0xba, 0xfa, 0x25, 0x13, 0x9f,
+ 0x84, 0xee, 0xcb, 0xdd, 0x10, 0x51, 0x41, 0xe3, 0xf5, 0x57, 0xc4, 0xa9,
+ 0xc5, 0xc9, 0xef, 0x60, 0xa1, 0x61, 0x0d, 0x16, 0x08, 0x8e, 0x5e, 0x05,
+ 0x16, 0xe9, 0xfb, 0xff, 0x4b, 0xf5, 0x57, 0xbe, 0x91, 0xe8, 0x85, 0x0e,
+ 0xc6, 0x6c, 0xa4, 0x54, 0x1a, 0x57, 0x27, 0x1a, 0x67, 0x5e, 0x5c, 0x43,
+ 0x18, 0x41, 0x61, 0xc9, 0xc1, 0x25, 0xe4, 0x51, 0x60, 0x6d, 0xed, 0xfc,
+ 0xde, 0xe3, 0xcc, 0xee, 0xef, 0xaa, 0x9a, 0x2a, 0x21, 0xea, 0x1a, 0xba,
+ 0x5d, 0x81, 0xbb, 0xf6, 0x2b, 0x4a, 0x9f, 0xac, 0x0e, 0xa1, 0xa0, 0xc2,
+ 0x31, 0x56, 0x40, 0x1b, 0x2c, 0xfa, 0xca, 0x11, 0x1a, 0xca, 0xbd, 0x9a,
+ 0xc5, 0x2c, 0xe8, 0x66, 0x74, 0x08, 0xb1, 0x65, 0x2a, 0x56, 0xd6, 0xb3,
+ 0x31, 0xb8, 0xb7, 0xef, 0xc6, 0x30, 0x19, 0x10, 0x93, 0x12, 0xc4, 0xc6,
+ 0x14, 0x03, 0x34, 0x65, 0x75, 0x7a, 0x2d, 0xee, 0x22, 0x98, 0xeb, 0x7c,
+ 0x26, 0x30, 0x12, 0x22, 0xe6, 0x0a, 0x76, 0x71, 0x77, 0x84, 0x02, 0x63,
+ 0x8f, 0xd5, 0x95, 0xe6, 0xe6, 0x06, 0x9f, 0x69, 0xce, 0x7f, 0xde, 0x48,
+ 0x3d, 0x53, 0xd4, 0xa7, 0xc0, 0x81, 0xb6, 0xb9, 0x40, 0xb5, 0x20, 0x5a,
+ 0x9b, 0x4e, 0x06, 0x81, 0x57, 0x76, 0x86, 0xdc, 0xd4, 0xaa, 0xa4, 0x03,
+ 0x04, 0xc9, 0x0e, 0x18, 0xe5, 0xee, 0x78, 0x78, 0xcb, 0xd0, 0xe1, 0x0e,
+ 0x91, 0xa0, 0x56, 0xab, 0xdc, 0xda, 0xf0, 0x77, 0x71, 0xd1, 0x30, 0xba,
+ 0x80, 0xa4, 0x7e, 0x89, 0x79, 0x5b, 0x39, 0x85, 0x88, 0x87, 0xa4, 0xb6,
+ 0xc6, 0x35, 0x32, 0x16, 0x70, 0x14, 0x5e, 0x45, 0x96, 0x4a, 0x57, 0xaa,
+ 0x29, 0x3d, 0x46, 0xdf, 0xae, 0xe5, 0xbd, 0x32, 0x00, 0x9a, 0x21, 0xaf,
+ 0xce, 0xd9, 0xb2, 0x52, 0xdb, 0x04, 0x79, 0x36, 0xaa, 0x4b, 0xe9, 0xd6,
+ 0xb2, 0xda, 0x42, 0xd0, 0x5f, 0x41, 0x39, 0xd2, 0x25, 0xe9, 0x4a, 0x5c,
+ 0xef, 0xba, 0x8c, 0xac, 0x21, 0x23, 0xef, 0x63, 0xc9, 0x4c, 0xd3, 0xc2,
+ 0xc2, 0xc5, 0xac, 0x31, 0x77, 0xd0, 0x13, 0x02, 0x5a, 0xc5, 0x98, 0x79,
+ 0x5a, 0xf5, 0xf6, 0xb8, 0x7b, 0xd8, 0x16, 0x40, 0xf2, 0x9f, 0xb8, 0x3a,
+ 0x1e, 0x0d, 0xfb, 0xc8, 0x51, 0x6d, 0x80, 0x87, 0xea, 0x0a, 0xd8, 0xea,
+ 0x52, 0x12, 0x94, 0x71, 0x1c, 0x16, 0x63, 0x32, 0xa3, 0x88, 0xde, 0x75,
+ 0x9f, 0x17, 0x68, 0x10, 0x34, 0xe2, 0x22, 0xcc, 0x42, 0x69, 0x9e, 0x70,
+ 0xab, 0x58, 0x7d, 0x5a, 0xdf, 0xd4, 0xab, 0x61, 0x86, 0x5a, 0x21, 0x1d,
+ 0x66, 0x74, 0x5e, 0x75, 0x0e, 0x6d, 0x95, 0x51, 0x5f, 0x1b, 0x7f, 0x94,
+ 0xb4, 0x57, 0xed, 0xe6, 0xec, 0x16, 0x05, 0x60, 0x61, 0x81, 0x56, 0x6a,
+ 0x8b, 0x74, 0x04, 0xda, 0x2a, 0x7f, 0x3d, 0xcc, 0x92, 0x1e, 0x95, 0xef,
+ 0xe8, 0xf9, 0xc9, 0x47, 0x92, 0xaf, 0xa7, 0xaf, 0x12, 0x16, 0x8d, 0x19,
+ 0xaa, 0x0b, 0x03, 0x0f, 0x25, 0x42, 0xbd, 0x1e, 0xc4, 0x3a, 0x44, 0x5b,
+ 0xb6, 0xf1, 0xa1, 0xc8, 0xef, 0xc1, 0x7f, 0x43, 0xd4, 0x3f, 0x3b, 0xef,
+ 0x47, 0x46, 0xa5, 0x05, 0xa1, 0x76, 0xb6, 0x87, 0x3b, 0xad, 0xd1, 0xe1,
+ 0x52, 0xa7, 0x50, 0x08, 0xbf, 0x9d, 0xc8, 0x5d, 0x18, 0xb3, 0xfa, 0xfa,
+ 0x1d, 0xcc, 0x1f, 0x86, 0x5e, 0x78, 0x4a, 0xd0, 0x85, 0x84, 0xb0, 0x74,
+ 0x5b, 0x1e, 0x78, 0xda, 0x88, 0x90, 0xda, 0x82, 0xa2, 0x79, 0x62, 0x25,
+ 0xd8, 0x35, 0xcd, 0xc6, 0xab, 0xbc, 0x3e, 0x8d, 0x0f, 0x68, 0x75, 0x39,
+ 0x76, 0xdb, 0xff, 0xff, 0x86, 0x60, 0xa7, 0x9e, 0xfe, 0xc3, 0xdc, 0xa5,
+ 0x5b, 0xc0, 0x18, 0xc3, 0x07, 0x03, 0x07, 0xac, 0xe4, 0xca, 0xed, 0x02,
+ 0x69, 0xc3, 0xec, 0x20, 0xad, 0x6f, 0x87, 0xd6, 0xcf, 0x04, 0xff, 0xa5,
+ 0xab, 0x78, 0xd1, 0xa9, 0xd0, 0x81, 0x7a, 0xef, 0x1d, 0xc4, 0x23, 0xdb,
+ 0xa6, 0xc5, 0x58, 0x19, 0x0c, 0xc4, 0x44, 0x3f, 0xc8, 0x16, 0x70, 0xf2,
+ 0xe2, 0x35, 0x30, 0x50, 0xb3, 0x42, 0x5e, 0xa8, 0x00, 0xbd, 0xf6, 0xe7,
+ 0x3f, 0x3b, 0x1e, 0xd5, 0x2e, 0x69, 0xb6, 0xf3, 0x6a, 0xf8, 0xc2, 0x19,
+ 0xaa, 0x18, 0x24, 0x20, 0xe9, 0xed, 0xfd, 0x88, 0xb4, 0x98, 0x9f, 0x07,
+ 0x3f, 0x9a, 0x3f, 0x7f, 0xee, 0x59, 0x46, 0x89, 0x38, 0xb1, 0x76, 0xf9,
+ 0x3d, 0x9b, 0xb4, 0x41, 0xcf, 0xd8, 0x70, 0x6a, 0xc8, 0x5c, 0xe4, 0x49,
+ 0xc4, 0x41, 0xe4, 0xc4, 0x6a, 0x9e, 0xa9, 0x18, 0xb1, 0x38, 0xbf, 0x1e,
+ 0xae, 0x76, 0xa2, 0x14, 0xbb, 0x96, 0x9a, 0xe0, 0xc5, 0x49, 0xd3, 0x78,
+ 0xb1, 0xaf, 0x3e, 0x58, 0xb2, 0x36, 0xdc, 0x31, 0xdb, 0x49, 0x35, 0x0d,
+ 0x9f, 0x39, 0xf4, 0x30, 0xd9, 0x57, 0x63, 0x08, 0x7f, 0xb0, 0x66, 0x41,
+ 0x74, 0x28, 0x0d, 0x54, 0x6a, 0xc5, 0x73, 0xb8, 0x02, 0xcb, 0x41, 0x99,
+ 0x8d, 0x24, 0xb2, 0x19, 0x97, 0x32, 0xc5, 0xfa, 0x86, 0x66, 0x28, 0x99,
+ 0xce, 0x09, 0x83, 0xb2, 0xad, 0x79, 0x42, 0x30, 0x46, 0xa6, 0xe9, 0xc1,
+ 0x04, 0x16, 0xae, 0x41, 0xd3, 0x2d, 0x79, 0x9f, 0x0a, 0x9a, 0xbd, 0x5e,
+ 0x5c, 0x57, 0xa6, 0xe1, 0x47, 0x40, 0x30, 0xcd, 0x53, 0xfc, 0x8c, 0xa5,
+ 0x5a, 0x0f, 0xe5, 0xf1, 0xf7, 0x54, 0x47, 0x18, 0x5d, 0x65, 0x45, 0x25,
+ 0xd0, 0x0b, 0xe6, 0xf4, 0x0e, 0x8a, 0xa3, 0x02, 0x00, 0x5e, 0xc3, 0x89,
+ 0x86, 0x2f, 0x77, 0x5e, 0x6e, 0x19, 0x46, 0xf2, 0x6c, 0xb8, 0x6b, 0xc3,
+ 0x37, 0xcc, 0x11, 0x33, 0x63, 0xe8, 0x5e, 0x9e, 0x7e, 0xa9, 0x59, 0x94,
+ 0xbd, 0x2b, 0x13, 0x0f, 0x50, 0x46, 0xae, 0x33, 0x97, 0xa6, 0x60, 0x36,
+ 0xdd, 0x0c, 0xc9, 0xe5, 0x4f, 0x04, 0x79, 0x21, 0xce, 0x45, 0x42, 0x22,
+ 0x0d, 0x8d, 0x45, 0x7d, 0x03, 0x4b, 0x29, 0x3d, 0x3d, 0xce, 0xcd, 0xed,
+ 0xdf, 0x94, 0x4b, 0xf8, 0x1f, 0xc9, 0xe1, 0xa1, 0x75, 0x7b, 0x08, 0x30,
+ 0x2c, 0x26, 0xcd, 0x5b, 0xfc, 0x15, 0x9e, 0x01, 0x8c, 0xda, 0xe3, 0x07,
+ 0x0f, 0x5d, 0x9c, 0x66, 0x4f, 0x2c, 0x0d, 0xc5, 0x07, 0xb8, 0x98, 0x09,
+ 0x5d, 0xc9, 0x93, 0x87, 0xee, 0x3d, 0xf2, 0x8d, 0xa1, 0xcc, 0x5b, 0x12,
+ 0xd9, 0xb5, 0xf8, 0xa9, 0x24, 0x9b, 0xb3, 0x8b, 0x34, 0xe5, 0xc5, 0x40,
+ 0xcd, 0x0f, 0x38, 0xc1, 0xe4, 0x03, 0x8e, 0x96, 0x8f, 0xd5, 0x8b, 0xf4,
+ 0xb3, 0x2c, 0xda, 0x00, 0xb2, 0x0c, 0x03, 0x42, 0xd8, 0xb3, 0xc0, 0x21,
+ 0x64, 0x05, 0xea, 0x4e, 0x0a, 0x12, 0x43, 0x19, 0x7c, 0x34, 0xb7, 0xe4,
+ 0xb1, 0xb2, 0x73, 0x82, 0xb4, 0xf3, 0xdf, 0x8f, 0x2c, 0x76, 0xff, 0x7f,
+ 0xb2, 0xf8, 0x67, 0x92, 0xc5, 0xab, 0x18, 0x59, 0x3c, 0xfb, 0xef, 0x47,
+ 0x16, 0xcf, 0xfe, 0x7f, 0xb2, 0xf8, 0x27, 0x92, 0xc5, 0xee, 0xcb, 0x76,
+ 0x7a, 0x1c, 0xd4, 0x49, 0x73, 0xc9, 0xa9, 0x56, 0x19, 0xc0, 0x8b, 0x33,
+ 0x61, 0x74, 0x21, 0x9d, 0x24, 0xcd, 0x4c, 0x60, 0x0d, 0x9d, 0x4a, 0x8a,
+ 0x5a, 0x4d, 0x04, 0xb4, 0xa7, 0x40, 0x7a, 0xa1, 0x45, 0x82, 0x00, 0x39,
+ 0xd3, 0xd9, 0x30, 0x39, 0xb3, 0x6f, 0x91, 0x91, 0x8f, 0x3e, 0x5b, 0x72,
+ 0x94, 0x45, 0x76, 0x09, 0x81, 0x0a, 0x72, 0x4a, 0x1f, 0x5f, 0x42, 0x8e,
+ 0x22, 0xab, 0xd1, 0x20, 0xc8, 0x8e, 0xa2, 0x57, 0xd4, 0xf9, 0x8f, 0x76,
+ 0x48, 0x03, 0x4d, 0x5d, 0x3a, 0x8b, 0x26, 0x51, 0xae, 0x1b, 0x69, 0x8a,
+ 0xa0, 0x81, 0x5d, 0xf1, 0x9f, 0x45, 0x95, 0x85, 0x85, 0x88, 0xee, 0xd9,
+ 0x31, 0xfe, 0x8f, 0xac, 0x2a, 0x13, 0x4d, 0xeb, 0x17, 0x2c, 0x36, 0x54,
+ 0xec, 0x52, 0x31, 0xc1, 0x7d, 0x48, 0xbd, 0x06, 0x5a, 0xc6, 0x9f, 0x51,
+ 0xc8, 0x90, 0xf1, 0xf7, 0x08, 0xe6, 0xc3, 0x26, 0xd7, 0x20, 0x4d, 0x3d,
+ 0x57, 0xab, 0x9b, 0x5b, 0x38, 0x95, 0x88, 0x11, 0xbe, 0x1f, 0x9c, 0x03,
+ 0x12, 0x5a, 0xc8, 0x70, 0xe0, 0x07, 0x1e, 0x5b, 0x45, 0xf3, 0x92, 0x01,
+ 0x88, 0x78, 0x38, 0xb6, 0x4e, 0xc7, 0x30, 0x22, 0xa7, 0x1f, 0x66, 0xc5,
+ 0x83, 0x06, 0x79, 0xb8, 0xd0, 0x00, 0x68, 0xce, 0xb7, 0xa2, 0xfd, 0xdb,
+ 0x62, 0x6f, 0x1a, 0xeb, 0x62, 0x87, 0x18, 0x0e, 0xa9, 0x3d, 0xe6, 0x26,
+ 0x12, 0x2d, 0xf7, 0xc6, 0x2e, 0x83, 0x04, 0xc3, 0xf9, 0x6b, 0xb1, 0x81,
+ 0x74, 0x1c, 0xf5, 0x8b, 0xa1, 0x3f, 0x6d, 0xf1, 0xd1, 0x65, 0xe0, 0xbc,
+ 0x5a, 0xb6, 0x6f, 0xd4, 0xcb, 0xf1, 0xdf, 0x88, 0x4b, 0x81, 0x30, 0x67,
+ 0x29, 0xb2, 0xd6, 0x5a, 0x25, 0x28, 0xa9, 0x1c, 0xcb, 0x72, 0x2c, 0x5e,
+ 0x9c, 0xb0, 0x39, 0xf3, 0x21, 0x3c, 0x76, 0xb6, 0xa2, 0x8d, 0xd0, 0x99,
+ 0x17, 0xf0, 0x13, 0x4c, 0xca, 0x8b, 0x5b, 0x09, 0xf6, 0x5d, 0xcf, 0x13,
+ 0xa9, 0x0b, 0xb5, 0x44, 0x28, 0xf8, 0x9b, 0x65, 0x57, 0x53, 0xa4, 0x58,
+ 0x8d, 0xcf, 0xa1, 0xc7, 0x57, 0xb6, 0x65, 0xa8, 0xb5, 0x4f, 0x5e, 0xd4,
+ 0xba, 0xff, 0x67, 0xfa, 0x27, 0xae, 0x30, 0xb5, 0xc0, 0x8f, 0x35, 0x98,
+ 0x8f, 0x1e, 0xc7, 0xd1, 0xc0, 0xeb, 0xab, 0x3a, 0x78, 0x43, 0xdf, 0x72,
+ 0x0f, 0x8f, 0xb7, 0x0d, 0x37, 0xe9, 0x2f, 0xe8, 0xe0, 0x43, 0xa1, 0x89,
+ 0xf3, 0x4a, 0xe6, 0x0b, 0x0b, 0xc3, 0x63, 0x54, 0xe3, 0xaa, 0xe0, 0x48,
+ 0x3c, 0x36, 0xe9, 0x89, 0x71, 0x27, 0xa1, 0x0c, 0x28, 0x42, 0x6b, 0x09,
+ 0x13, 0x3b, 0x08, 0xed, 0x9b, 0x18, 0x1f, 0xec, 0x55, 0xb4, 0xb7, 0x9c,
+ 0xee, 0x28, 0xb0, 0x9a, 0x1a, 0xb9, 0xb6, 0x28, 0x1b, 0x75, 0xd8, 0x25,
+ 0x53, 0xd2, 0x3c, 0x2a, 0xba, 0x1c, 0x22, 0x80, 0xec, 0xba, 0x11, 0x5a,
+ 0xda, 0x8b, 0x9a, 0xa5, 0x06, 0x97, 0x0b, 0xc2, 0x4d, 0x12, 0xa8, 0x0f,
+ 0x66, 0x68, 0x02, 0x01, 0xa5, 0x94, 0xcb, 0x3d, 0x77, 0x23, 0x5c, 0x10,
+ 0x7e, 0x81, 0x2b, 0xcf, 0x22, 0x84, 0xde, 0x96, 0x39, 0xe0, 0x6f, 0x91,
+ 0xbf, 0x39, 0xfc, 0xd4, 0x2a, 0xce, 0x6d, 0x33, 0x66, 0xdf, 0xab, 0x0a,
+ 0x97, 0xd6, 0x7e, 0x1a, 0x45, 0x18, 0x5e, 0x66, 0x75, 0x6e, 0xa3, 0x2b,
+ 0x51, 0xfe, 0xbf, 0x21, 0xe2, 0x22, 0xb5, 0x65, 0x87, 0xdc, 0x36, 0x60,
+ 0x94, 0x5c, 0x04, 0x85, 0x52, 0x3a, 0x26, 0x59, 0x04, 0x1b, 0xd4, 0xa1,
+ 0x49, 0x3f, 0x05, 0x27, 0xb1, 0x1b, 0xdc, 0x27, 0x9c, 0x70, 0xfd, 0xf4,
+ 0xad, 0x12, 0xb9, 0x54, 0xe4, 0x4e, 0xf1, 0x38, 0xa3, 0xc0, 0x52, 0xea,
+ 0xe5, 0x88, 0xac, 0xab, 0x15, 0x94, 0xcc, 0x40, 0x42, 0x77, 0xfe, 0xdb,
+ 0x15, 0x22, 0x2b, 0x18, 0xe9, 0x25, 0xc2, 0xa1, 0x9e, 0x98, 0xca, 0xfd,
+ 0xc3, 0x20, 0x2d, 0x1e, 0xc8, 0xc7, 0x16, 0x9d, 0x80, 0x4d, 0x3a, 0x46,
+ 0xfa, 0x92, 0x21, 0x9a, 0x9c, 0xeb, 0xc6, 0x74, 0xc2, 0x9a, 0x35, 0xd2,
+ 0x4b, 0x31, 0x96, 0xe7, 0xcb, 0xc0, 0xf8, 0x87, 0x47, 0xe9, 0x22, 0x67,
+ 0x14, 0xf8, 0xc6, 0xc1, 0x06, 0xaa, 0xf7, 0x47, 0x8e, 0x09, 0x63, 0x7e,
+ 0x09, 0xe8, 0x17, 0x68, 0x8b, 0xfc, 0x3e, 0x71, 0x4b, 0xfb, 0x96, 0x4d,
+ 0x57, 0xac, 0xa8, 0xea, 0xd2, 0xc0, 0xf0, 0xba, 0x45, 0x07, 0xf4, 0xeb,
+ 0x59, 0x6c, 0xca, 0xa8, 0xbf, 0xfa, 0xe8, 0x84, 0xa9, 0xf3, 0x95, 0x10,
+ 0x55, 0x89, 0x3f, 0x53, 0x9d, 0xd9, 0x2a, 0xbf, 0x09, 0x4f, 0x52, 0xe6,
+ 0xf8, 0x81, 0xd3, 0x61, 0xd0, 0x26, 0x60, 0x60, 0x89, 0xcd, 0xd0, 0xb2,
+ 0x78, 0x7d, 0x31, 0x04, 0x72, 0x30, 0x61, 0x18, 0x7f, 0x19, 0xb4, 0x97,
+ 0x9f, 0x93, 0xe3, 0xe0, 0xe4, 0xba, 0xee, 0x20, 0x65, 0x57, 0x62, 0x98,
+ 0xf8, 0xe0, 0xdb, 0xe8, 0x88, 0x06, 0x96, 0xb7, 0xd3, 0x16, 0x78, 0x8d,
+ 0xa6, 0x88, 0x0a, 0x7b, 0x84, 0xac, 0xfd, 0x55, 0xe2, 0x10, 0xb2, 0xee,
+ 0x08, 0xc4, 0x12, 0xfc, 0xeb, 0x16, 0x89, 0xfb, 0x8f, 0xac, 0x92, 0xf4,
+ 0x15, 0x85, 0xc2, 0xf5, 0x97, 0x29, 0x98, 0xd1, 0xaa, 0x74, 0x8c, 0xe8,
+ 0x59, 0x45, 0x57, 0x4f, 0x66, 0x66, 0x60, 0x8a, 0x41, 0x62, 0xb3, 0x37,
+ 0xe1, 0x47, 0xa7, 0x68, 0x07, 0xd4, 0x9a, 0x65, 0x57, 0x08, 0x5f, 0x31,
+ 0x10, 0x41, 0xca, 0x6e, 0x11, 0xc6, 0xa3, 0x5a, 0xb3, 0x8d, 0xbc, 0xfb,
+ 0xf4, 0xe9, 0x53, 0xac, 0xdf, 0x6f, 0xb9, 0xa7, 0x88, 0x32, 0x6d, 0xed,
+ 0x28, 0xba, 0x68, 0x4d, 0xe5, 0x51, 0x1f, 0xa7, 0x4c, 0x63, 0x67, 0xb8,
+ 0x0d, 0xde, 0x7b, 0xff, 0x80, 0x48, 0xab, 0x3d, 0xba, 0xc9, 0x7e, 0xee,
+ 0xb2, 0xe0, 0x0f, 0x56, 0x8c, 0xf7, 0xca, 0x07, 0xb3, 0x8b, 0x89, 0xde,
+ 0xd7, 0x91, 0x69, 0x29, 0x47, 0x07, 0xa3, 0x28, 0xd8, 0x38, 0xab, 0xeb,
+ 0x91, 0xe4, 0x8d, 0x57, 0x8e, 0x84, 0xf2, 0xc0, 0xf1, 0xf2, 0xce, 0xf6,
+ 0xe7, 0xdb, 0xd1, 0x00, 0x00, 0x08, 0x14, 0x1a, 0xef, 0x32, 0xc9, 0xbc,
+ 0x8a, 0x93, 0xb9, 0xab, 0x36, 0xe4, 0xf9, 0x8f, 0xd4, 0xf7, 0x47, 0x6e,
+ 0xb4, 0xd8, 0x3d, 0x00, 0xa7, 0x5a, 0x2e, 0xc6, 0x66, 0x31, 0xd0, 0x5a,
+ 0x88, 0x32, 0x75, 0x3e, 0x59, 0xbf, 0x8f, 0x75, 0x2e, 0x45, 0x92, 0xaa,
+ 0x9d, 0xa3, 0x9d, 0xfb, 0xa7, 0x75, 0xf1, 0x44, 0x79, 0x6b, 0xd3, 0xf5,
+ 0x25, 0x3c, 0x79, 0x70, 0xa7, 0xb5, 0x29, 0xcb, 0xf1, 0x23, 0xb5, 0x74,
+ 0xc8, 0x84, 0xc8, 0xf1, 0xaa, 0x8f, 0x96, 0xd1, 0xb1, 0xd9, 0x36, 0x1c,
+ 0xa6, 0x29, 0x31, 0xae, 0x41, 0xb9, 0xa5, 0x7f, 0x7e, 0x19, 0x9d, 0xbf,
+ 0xdb, 0xc4, 0x18, 0x4e, 0x83, 0xb1, 0xf8, 0x14, 0x14, 0xf2, 0xe9, 0x4a,
+ 0x7b, 0x96, 0x9e, 0x88, 0x6d, 0xf1, 0x99, 0xb5, 0xe8, 0x5a, 0x90, 0x5b,
+ 0xee, 0x97, 0x10, 0xf4, 0xdd, 0xc3, 0xa8, 0xb6, 0x2b, 0x21, 0x22, 0x02,
+ 0x97, 0x8e, 0x70, 0x25, 0xbf, 0xa6, 0x64, 0x04, 0xdf, 0x53, 0xb3, 0xb1,
+ 0x65, 0x10, 0xb1, 0x42, 0x85, 0x75, 0x96, 0x56, 0x46, 0xc6, 0xa2, 0xd0,
+ 0x34, 0x6f, 0x72, 0xff, 0x83, 0xda, 0x45, 0x59, 0x51, 0x57, 0xff, 0x20,
+ 0xe2, 0x07, 0xdc, 0x1a, 0xb1, 0x33, 0x70, 0x04, 0x98, 0x6a, 0xb2, 0xc1,
+ 0x57, 0xe3, 0xbc, 0xa9, 0x52, 0xa9, 0xcd, 0x22, 0xf5, 0x22, 0x3c, 0x37,
+ 0x25, 0xb2, 0xd1, 0xab, 0x84, 0x5e, 0x8b, 0xba, 0xc6, 0x86, 0xc9, 0xff,
+ 0x40, 0xa7, 0xf2, 0x36, 0x0b, 0x32, 0xf0, 0x8d, 0x7f, 0x75, 0xf4, 0xf6,
+ 0xf4, 0xfc, 0xa8, 0x8d, 0x8a, 0xc5, 0xc0, 0xf4, 0x8c, 0xca, 0xdf, 0x1d,
+ 0xdd, 0xdf, 0x28, 0x5d, 0xab, 0x85, 0xe8, 0xa1, 0x10, 0xf7, 0x67, 0xdf,
+ 0x1f, 0x7a, 0x1e, 0x0a, 0xad, 0x64, 0xe2, 0x01, 0x2e, 0x95, 0x91, 0xc2,
+ 0x3c, 0xe4, 0x67, 0xda, 0x74, 0xa0, 0xc8, 0x76, 0x7c, 0x0c, 0x45, 0x8b,
+ 0x48, 0x09, 0x95, 0xd8, 0x90, 0x2a, 0x52, 0xd7, 0x64, 0xb2, 0xb0, 0x8d,
+ 0x06, 0x5e, 0xca, 0x8c, 0x70, 0x8e, 0x91, 0x75, 0xa4, 0xb2, 0x4f, 0xca,
+ 0xa1, 0x90, 0x14, 0x1f, 0x39, 0x4c, 0xc2, 0x8e, 0x34, 0x46, 0x00, 0xbd,
+ 0xc4, 0x0c, 0x3c, 0x14, 0x5d, 0xc6, 0xd1, 0x70, 0xcc, 0x3a, 0x82, 0x50,
+ 0xb8, 0x7e, 0xf2, 0x37, 0x2e, 0x3a, 0x74, 0xc9, 0xa8, 0xbd, 0x6e, 0x21,
+ 0x23, 0x57, 0x95, 0xe9, 0x73, 0xa3, 0x26, 0x95, 0xd3, 0x1b, 0xaa, 0xfd,
+ 0x26, 0x51, 0xde, 0xbc, 0xfe, 0xe7, 0x75, 0xa7, 0x9d, 0x73, 0xc9, 0x81,
+ 0x78, 0x1e, 0x9f, 0x03, 0x23, 0xd8, 0x7c, 0x2a, 0xa0, 0x47, 0x67, 0x3c,
+ 0xd4, 0x7a, 0xb1, 0x71, 0x1f, 0xaa, 0x56, 0x83, 0x54, 0x5f, 0x87, 0xd6,
+ 0x37, 0x14, 0xbe, 0xa4, 0xad, 0xf0, 0x59, 0x63, 0xc8, 0x64, 0xf8, 0xf4,
+ 0x03, 0x53, 0x8a, 0x0b, 0x40, 0x40, 0xf1, 0x54, 0x29, 0x3f, 0xf5, 0x57,
+ 0xcd, 0xf8, 0x03, 0x74, 0x56, 0xfd, 0x50, 0x34, 0xf0, 0x2b, 0x33, 0xb8,
+ 0xc2, 0xa4, 0xac, 0xe0, 0x8a, 0x4f, 0x42, 0x32, 0xb6, 0xfb, 0x05, 0xf0,
+ 0x69, 0xb2, 0xdc, 0xbd, 0x7a, 0xf1, 0x8a, 0x0e, 0x1e, 0x42, 0x56, 0x24,
+ 0x2f, 0x5f, 0x52, 0x19, 0x90, 0x23, 0xd2, 0x1e, 0xf3, 0x20, 0x08, 0x76,
+ 0xa4, 0xb6, 0x44, 0x39, 0x18, 0x67, 0x33, 0xae, 0x7b, 0x30, 0xf2, 0x1a,
+ 0x19, 0x3e, 0x1a, 0x1b, 0xb2, 0x2a, 0xec, 0x83, 0x19, 0x9d, 0x94, 0xd7,
+ 0x31, 0xfb, 0x90, 0xde, 0x48, 0x74, 0x99, 0x9c, 0x06, 0x6e, 0xbc, 0xaf,
+ 0xbb, 0xff, 0xc8, 0xe8, 0x84, 0x14, 0x28, 0x84, 0xd0, 0x10, 0x26, 0x39,
+ 0xa0, 0x36, 0xfe, 0x75, 0xb3, 0x5d, 0xd8, 0x96, 0x9c, 0x99, 0x79, 0xb1,
+ 0xcc, 0x5a, 0xc8, 0x6f, 0xab, 0x9a, 0xbb, 0x04, 0xc3, 0x32, 0x8b, 0xd7,
+ 0xcd, 0xd4, 0xe3, 0x12, 0x93, 0x4d, 0xb9, 0x48, 0x52, 0xad, 0x56, 0x2a,
+ 0x7b, 0x1f, 0x06, 0x37, 0xa3, 0x34, 0x0f, 0xd2, 0x42, 0xc6, 0x8c, 0x91,
+ 0xaf, 0xd7, 0x97, 0x11, 0x39, 0x0a, 0x84, 0x77, 0x08, 0x35, 0x0a, 0xfe,
+ 0x05, 0x5c, 0xdc, 0x66, 0xae, 0xe6, 0xc2, 0x8c, 0xb0, 0xa6, 0xbf, 0xb7,
+ 0x59, 0x92, 0x20, 0xfc, 0xc8, 0x39, 0xd2, 0x28, 0x36, 0x1c, 0x65, 0x61,
+ 0x76, 0x96, 0x99, 0x19, 0x0a, 0x09, 0x53, 0xd6, 0xb9, 0x24, 0xb7, 0x60,
+ 0x75, 0xa2, 0x6d, 0x2a, 0xf6, 0x65, 0xc4, 0xad, 0x41, 0xdd, 0x3c, 0xb0,
+ 0x52, 0x9f, 0xcd, 0x09, 0x0c, 0x05, 0xa5, 0xa2, 0x11, 0xe7, 0x24, 0x25,
+ 0x9c, 0x90, 0x1a, 0x35, 0x08, 0x0b, 0x97, 0x33, 0x19, 0xbc, 0xb5, 0xf6,
+ 0x65, 0xd1, 0x01, 0xd4, 0x96, 0x45, 0x99, 0x52, 0x16, 0xb7, 0x89, 0x17,
+ 0x87, 0xa7, 0xb4, 0x92, 0xe2, 0x42, 0xe0, 0x9d, 0xeb, 0xab, 0x6a, 0xc1,
+ 0xa0, 0x19, 0x49, 0x24, 0x0b, 0xdf, 0x8f, 0x6b, 0xe4, 0x47, 0x95, 0x53,
+ 0xd8, 0xd2, 0x8c, 0xfc, 0xee, 0xf1, 0x61, 0x0b, 0x70, 0x89, 0xa3, 0xae,
+ 0xc7, 0x0f, 0xf1, 0xe6, 0x1c, 0xdc, 0x13, 0xc5, 0xe2, 0xb8, 0xbb, 0xc4,
+ 0x36, 0xe5, 0x24, 0xb8, 0xb1, 0x66, 0x5c, 0xe0, 0xbb, 0x78, 0x73, 0xd2,
+ 0x0a, 0x87, 0xf3, 0x70, 0x1b, 0xda, 0x30, 0x48, 0x45, 0x21, 0x6a, 0x89,
+ 0x18, 0x08, 0x68, 0x50, 0xbb, 0x09, 0x63, 0xe9, 0xae, 0xe7, 0xe5, 0x94,
+ 0xe3, 0x3c, 0x9e, 0x5c, 0x8b, 0x79, 0x39, 0xf5, 0xd8, 0xa6, 0x98, 0x2b,
+ 0x6b, 0x1f, 0x0c, 0x12, 0xed, 0x8c, 0x73, 0x1b, 0xee, 0x1b, 0x6f, 0xce,
+ 0x4d, 0x15, 0x62, 0x0d, 0x9a, 0xc7, 0x9b, 0xfe, 0x14, 0x8a, 0xa4, 0x9c,
+ 0x34, 0xde, 0x0c, 0xe8, 0x81, 0x78, 0x73, 0xe2, 0x79, 0x0e, 0x67, 0x46,
+ 0x76, 0x2b, 0x84, 0xa1, 0x3e, 0x3e, 0x33, 0x7e, 0x30, 0xd8, 0x64, 0xf3,
+ 0x21, 0x33, 0xf1, 0x60, 0x87, 0x57, 0xcf, 0x2c, 0xb6, 0xc3, 0x18, 0x41,
+ 0x77, 0x83, 0x35, 0x46, 0xa1, 0x4a, 0xa2, 0x8c, 0xdc, 0xe1, 0x90, 0xf1,
+ 0xea, 0x48, 0x04, 0xee, 0x23, 0x1b, 0x2c, 0xbd, 0x04, 0xab, 0x30, 0x2b,
+ 0xa4, 0x1e, 0xc6, 0x47, 0x46, 0x79, 0x20, 0xdc, 0xc9, 0xe6, 0xe3, 0xe3,
+ 0x0b, 0x32, 0x2b, 0xb4, 0x46, 0x17, 0xf0, 0x84, 0x2c, 0xb3, 0x90, 0x04,
+ 0x8a, 0xb4, 0x5d, 0xbd, 0x4b, 0x50, 0xa2, 0x56, 0x90, 0xbd, 0xeb, 0xcf,
+ 0x15, 0x43, 0x5a, 0x94, 0x39, 0x23, 0x4c, 0xdb, 0x18, 0x50, 0x7f, 0x88,
+ 0x49, 0xac, 0x68, 0x8e, 0x97, 0xe4, 0x15, 0x4c, 0x71, 0x7e, 0x43, 0x86,
+ 0x2a, 0x2b, 0x1a, 0x7c, 0x5c, 0x1d, 0x22, 0x03, 0x3a, 0xe6, 0xc7, 0x1d,
+ 0x1d, 0xf3, 0xac, 0x6c, 0xec, 0x97, 0x0d, 0xb6, 0x7f, 0x7a, 0xb7, 0xdb,
+ 0x5d, 0xda, 0x33, 0xd9, 0x1d, 0xdf, 0xe2, 0x6e, 0xaa, 0x9d, 0xd3, 0xaf,
+ 0xda, 0xb1, 0x5f, 0x02, 0xda, 0x82, 0x74, 0x90, 0xe8, 0xca, 0x8d, 0x5d,
+ 0xaa, 0x60, 0xbd, 0x62, 0x29, 0xe2, 0x29, 0x02, 0x41, 0xe7, 0x15, 0x17,
+ 0x6d, 0x57, 0x10, 0x7b, 0x6c, 0xc7, 0xea, 0xc5, 0x91, 0xa7, 0xdd, 0x10,
+ 0x99, 0xbf, 0xfb, 0x58, 0x75, 0xe1, 0x02, 0xad, 0x66, 0x78, 0xd2, 0x6b,
+ 0xe7, 0x40, 0x4c, 0x33, 0xaa, 0x0f, 0x28, 0xa4, 0x40, 0x59, 0x24, 0xdc,
+ 0x90, 0xf2, 0xbd, 0xc7, 0x08, 0x69, 0xe5, 0x1a, 0x57, 0xf3, 0x27, 0x0e,
+ 0xb9, 0x79, 0xc0, 0xcd, 0x8a, 0x82, 0x48, 0xbd, 0x59, 0x05, 0x27, 0x53,
+ 0x8e, 0xf1, 0x8a, 0x95, 0x5f, 0x35, 0x82, 0x16, 0x15, 0x3e, 0x36, 0x12,
+ 0x7a, 0x30, 0x36, 0x18, 0xaf, 0xac, 0x20, 0x39, 0x35, 0x1e, 0x3c, 0x4e,
+ 0x19, 0x6f, 0x4e, 0x86, 0xeb, 0xde, 0x93, 0xe5, 0xe9, 0x5b, 0xf0, 0x14,
+ 0x51, 0xe4, 0x49, 0x7f, 0x0e, 0x69, 0x43, 0x0f, 0xf8, 0x2f, 0x62, 0x10,
+ 0xa4, 0xae, 0xcd, 0xbc, 0x43, 0x38, 0xa8, 0x90, 0x65, 0x82, 0xc0, 0xa2,
+ 0xd7, 0xf8, 0x27, 0x1a, 0x4e, 0xbf, 0xa5, 0x1a, 0xd6, 0x16, 0x41, 0xd5,
+ 0x21, 0xe6, 0x12, 0x5e, 0x44, 0x62, 0x27, 0x04, 0x3f, 0x2c, 0xa1, 0x49,
+ 0x1b, 0x14, 0xc5, 0xc6, 0xe1, 0xd3, 0x24, 0x23, 0x50, 0x0a, 0x5f, 0x70,
+ 0xa9, 0x9b, 0xb5, 0xd9, 0x94, 0x6a, 0x63, 0x50, 0xd5, 0xb7, 0x8c, 0xaa,
+ 0xde, 0x57, 0x6d, 0x4c, 0xe4, 0x25, 0x0d, 0x4e, 0xa4, 0x4f, 0x52, 0x49,
+ 0x33, 0x4e, 0x80, 0x92, 0xd7, 0xf5, 0x00, 0x9f, 0x53, 0xbf, 0x75, 0x98,
+ 0x24, 0x01, 0x6f, 0xaf, 0x93, 0xe4, 0x09, 0x43, 0x38, 0x58, 0xc0, 0xed,
+ 0xc1, 0xf3, 0x57, 0xaf, 0x5a, 0x57, 0x9a, 0xaf, 0x37, 0xbf, 0xd8, 0xde,
+ 0x66, 0x64, 0xe5, 0xee, 0x6b, 0xe6, 0x8b, 0xc1, 0x2b, 0xbc, 0xd8, 0x7e,
+ 0x8d, 0x51, 0xfd, 0x57, 0xbf, 0x37, 0xa0, 0x6f, 0x22, 0xdd, 0x41, 0xbb,
+ 0x5f, 0xf9, 0xd6, 0x2b, 0xea, 0x2e, 0xf2, 0x16, 0x1e, 0xe6, 0x75, 0x2c,
+ 0x2f, 0x2f, 0x09, 0x56, 0x94, 0x9e, 0xe4, 0x02, 0xdf, 0x65, 0x75, 0x97,
+ 0x56, 0xd3, 0x70, 0xba, 0xdb, 0xfd, 0xc1, 0xce, 0xaa, 0xe9, 0xc2, 0x22,
+ 0x40, 0x23, 0xc1, 0x76, 0x92, 0x02, 0x65, 0x84, 0xe7, 0x8d, 0x6f, 0x36,
+ 0x63, 0xb3, 0xff, 0x6c, 0x7b, 0xbb, 0xff, 0x92, 0xfe, 0x7d, 0xf5, 0x6a,
+ 0xa5, 0xbb, 0xca, 0xf5, 0xf1, 0x4c, 0xa7, 0xd6, 0x1a, 0xad, 0x69, 0x27,
+ 0xd2, 0xfa, 0x8e, 0x69, 0x75, 0xe7, 0xd5, 0xab, 0x3e, 0xf5, 0xf2, 0xe2,
+ 0x93, 0x5a, 0x6f, 0xee, 0x4a, 0x67, 0x67, 0xa1, 0xd7, 0x1d, 0x39, 0xd6,
+ 0x9d, 0x19, 0x90, 0x36, 0x40, 0x0e, 0x51, 0x42, 0x9b, 0x4e, 0x3c, 0x1c,
+ 0x29, 0x17, 0xf2, 0xed, 0x57, 0x11, 0x44, 0xd8, 0xc0, 0x02, 0xd8, 0x00,
+ 0x50, 0x30, 0x59, 0x61, 0x49, 0x5d, 0xc0, 0x85, 0x9a, 0xf6, 0x5d, 0x4a,
+ 0xd6, 0x29, 0xdb, 0xd1, 0xae, 0xf2, 0xc6, 0x21, 0x07, 0xd4, 0xc9, 0x86,
+ 0x21, 0x17, 0x46, 0x2c, 0x65, 0x48, 0x64, 0xf1, 0x74, 0xae, 0x23, 0x34,
+ 0x90, 0x41, 0xcd, 0xd6, 0x49, 0x99, 0xa0, 0xbc, 0xd6, 0x3c, 0x9b, 0x4d,
+ 0xad, 0x0b, 0x50, 0x13, 0x7c, 0xf8, 0xc9, 0x01, 0x3f, 0xc3, 0x07, 0x0d,
+ 0x5a, 0xe0, 0xbd, 0x54, 0xc7, 0xa3, 0xc0, 0x8c, 0x4e, 0xaf, 0x89, 0xc5,
+ 0xa4, 0x76, 0x39, 0x00, 0x5c, 0x88, 0x06, 0x81, 0x80, 0x6e, 0x9a, 0xeb,
+ 0xb5, 0x57, 0x8d, 0x4d, 0xad, 0x4b, 0x7e, 0xbd, 0xea, 0x69, 0xa6, 0x45,
+ 0x8e, 0x3a, 0x30, 0x7a, 0xf6, 0x7d, 0x36, 0xe1, 0x2c, 0xab, 0x0e, 0x12,
+ 0x10, 0x12, 0xbc, 0x34, 0x9f, 0x9c, 0xd3, 0x3b, 0x49, 0xab, 0xbd, 0x4b,
+ 0xab, 0x4c, 0x91, 0x30, 0x8c, 0xb2, 0xad, 0x1c, 0xc0, 0x56, 0x2f, 0x95,
+ 0xf4, 0x0a, 0xc1, 0x2b, 0x73, 0xe9, 0x33, 0x5a, 0x8b, 0x8a, 0xfd, 0x9e,
+ 0x5a, 0xba, 0x32, 0x95, 0x04, 0x1e, 0x8e, 0x80, 0x6c, 0x45, 0xe2, 0xd3,
+ 0x7d, 0x43, 0xcc, 0x43, 0x63, 0x1f, 0xb9, 0x4a, 0xc8, 0x5a, 0x27, 0xfc,
+ 0xfe, 0x2a, 0xe3, 0xf0, 0x76, 0x2e, 0xbb, 0xa1, 0x39, 0xc7, 0x6e, 0x16,
+ 0x60, 0x47, 0x80, 0xe9, 0xa1, 0xdf, 0x78, 0xf1, 0x5d, 0xc9, 0x2c, 0xb5,
+ 0x33, 0xc0, 0xbc, 0xca, 0x35, 0x4c, 0x80, 0x97, 0xd7, 0xda, 0x31, 0xb3,
+ 0x57, 0x96, 0x09, 0x9a, 0x4d, 0x4b, 0x36, 0xbc, 0x08, 0x08, 0xd0, 0x96,
+ 0xa7, 0x77, 0x6b, 0x75, 0x9b, 0x92, 0xdd, 0xf9, 0x9b, 0x43, 0x1e, 0x00,
+ 0x3c, 0x4d, 0xbc, 0x13, 0xc0, 0x33, 0xf4, 0xb7, 0x34, 0xbb, 0x6f, 0x50,
+ 0x90, 0x0a, 0x4f, 0xea, 0xbd, 0x34, 0x3a, 0xfe, 0x9f, 0x47, 0xc3, 0xdf,
+ 0x22, 0x4e, 0xb7, 0x63, 0x69, 0x3c, 0xf7, 0x72, 0x12, 0xe9, 0xb5, 0x28,
+ 0x84, 0x38, 0x67, 0x99, 0x7a, 0x67, 0xcb, 0xe9, 0xdf, 0x5e, 0xb4, 0x2e,
+ 0x68, 0x06, 0x09, 0xb5, 0x16, 0xa5, 0x34, 0x28, 0xad, 0xda, 0xa4, 0xf3,
+ 0x45, 0x24, 0x95, 0xb5, 0xaf, 0x00, 0x9f, 0x0a, 0x55, 0x4a, 0x36, 0x0e,
+ 0x1b, 0x17, 0x22, 0x81, 0xd0, 0xa1, 0x2c, 0xe2, 0xe5, 0xd8, 0xf2, 0xb6,
+ 0x53, 0x5d, 0x56, 0x12, 0x98, 0xb0, 0x00, 0xd4, 0x97, 0x6f, 0x32, 0xa6,
+ 0x9b, 0xd8, 0xe8, 0xa4, 0x78, 0x3c, 0x9a, 0x04, 0xcf, 0x98, 0x37, 0x7e,
+ 0xe6, 0xa0, 0x15, 0x87, 0x78, 0x7e, 0xb3, 0x4c, 0xe1, 0x39, 0xe0, 0x67,
+ 0xf1, 0x2b, 0x10, 0x45, 0xb2, 0x0f, 0x6a, 0x73, 0xe1, 0x57, 0x9c, 0xde,
+ 0xc7, 0x5d, 0x03, 0x49, 0x8f, 0x15, 0x08, 0x46, 0xe5, 0xab, 0x1d, 0xde,
+ 0x2a, 0x20, 0xa7, 0xb4, 0xb4, 0x21, 0x3f, 0x1e, 0xd4, 0xef, 0x26, 0x98,
+ 0x09, 0x18, 0x17, 0x08, 0x8b, 0xc0, 0x45, 0x6f, 0xd7, 0x61, 0xb9, 0x93,
+ 0xec, 0x6a, 0xea, 0x03, 0xb8, 0xb5, 0x57, 0xe1, 0xce, 0x86, 0xa8, 0xd9,
+ 0x02, 0xc8, 0x70, 0x30, 0xd8, 0xc8, 0x89, 0x74, 0x26, 0x56, 0x0b, 0x42,
+ 0x22, 0x83, 0xf1, 0xdd, 0xe6, 0xa0, 0xc2, 0x86, 0x16, 0xcc, 0xb4, 0x41,
+ 0xe2, 0x9b, 0x57, 0xfa, 0x0b, 0xa9, 0xa6, 0x48, 0x85, 0x82, 0x48, 0xaf,
+ 0x67, 0x53, 0x52, 0x2e, 0xc4, 0x34, 0x49, 0xa1, 0xc0, 0x28, 0x7a, 0x18,
+ 0xe0, 0x36, 0x98, 0x7e, 0x51, 0xab, 0xbc, 0x6f, 0x56, 0xe2, 0x2e, 0x28,
+ 0xb1, 0xd7, 0xf2, 0xae, 0x7a, 0xe9, 0xb4, 0x14, 0xd4, 0xf1, 0x58, 0x66,
+ 0x13, 0x1b, 0x30, 0xdb, 0xc1, 0x23, 0x29, 0x67, 0x6e, 0xd2, 0xa2, 0xd2,
+ 0xac, 0x6d, 0x16, 0x73, 0x1d, 0xb5, 0xd4, 0x4e, 0xb3, 0x54, 0xe1, 0x20,
+ 0xcc, 0xa6, 0x1a, 0x72, 0x0d, 0x53, 0x7a, 0xef, 0xb2, 0x2a, 0x73, 0x00,
+ 0xa9, 0x88, 0x9c, 0x32, 0xa7, 0x6f, 0x98, 0x8c, 0x4a, 0xf3, 0x7c, 0xa4,
+ 0x04, 0x92, 0x66, 0x33, 0xb4, 0x00, 0x13, 0x31, 0x1c, 0x57, 0xa4, 0x98,
+ 0x92, 0x77, 0xd9, 0x00, 0xdc, 0x9e, 0x6f, 0x04, 0x63, 0x89, 0x0c, 0xb5,
+ 0xe3, 0xcc, 0xee, 0xaa, 0xc5, 0x16, 0x63, 0x86, 0xd3, 0x1b, 0x18, 0x3a,
+ 0x1b, 0xf4, 0x24, 0xb3, 0x94, 0xe0, 0x9f, 0xbc, 0xe6, 0x1e, 0x4b, 0xd3,
+ 0xda, 0x79, 0xd5, 0x8e, 0x70, 0xa3, 0x2a, 0x5c, 0x33, 0xc3, 0xcf, 0x5f,
+ 0x93, 0x33, 0x0c, 0xbe, 0xb0, 0xbd, 0x15, 0x19, 0x3d, 0x67, 0xea, 0x61,
+ 0x49, 0xc9, 0x94, 0x6c, 0xf8, 0xe7, 0xdc, 0xcb, 0xf1, 0xb8, 0x64, 0x71,
+ 0xd0, 0x4e, 0x14, 0x19, 0x15, 0x36, 0x4b, 0x65, 0x91, 0xe6, 0xd5, 0x30,
+ 0xf0, 0xb0, 0x29, 0x7e, 0x9a, 0x8b, 0xcd, 0xb7, 0x15, 0x88, 0xc1, 0x90,
+ 0x34, 0x2e, 0x72, 0xa3, 0xde, 0x74, 0xb5, 0xe8, 0x57, 0xc9, 0xed, 0x76,
+ 0x24, 0x0c, 0x6d, 0x26, 0xc8, 0xf1, 0xb0, 0x36, 0xd8, 0x3a, 0x84, 0x8c,
+ 0xed, 0x39, 0x7b, 0x48, 0x64, 0xd2, 0x53, 0xaf, 0xf8, 0x41, 0x80, 0xc8,
+ 0x22, 0x3e, 0x14, 0xca, 0x72, 0xa7, 0xd3, 0x4f, 0xc7, 0xca, 0xcc, 0xaf,
+ 0xe4, 0xe4, 0xc3, 0xad, 0xac, 0x99, 0x6c, 0x31, 0xd0, 0x51, 0x02, 0x0a,
+ 0x2f, 0x52, 0x4e, 0x38, 0x52, 0xed, 0x20, 0x28, 0xba, 0xde, 0x31, 0x8d,
+ 0x93, 0x83, 0x87, 0xf9, 0x87, 0xef, 0x3b, 0x74, 0xf9, 0x39, 0x5e, 0x62,
+ 0x75, 0xc4, 0x40, 0xab, 0x91, 0xf4, 0x76, 0xb9, 0xad, 0xdf, 0x4d, 0xb1,
+ 0x84, 0xda, 0x85, 0x62, 0xe8, 0x05, 0x86, 0x4f, 0xe4, 0xa4, 0x84, 0x58,
+ 0x01, 0xaf, 0x22, 0xf3, 0xae, 0x1d, 0x1b, 0xf9, 0xd5, 0x86, 0x71, 0xb1,
+ 0x90, 0x76, 0xb2, 0x6c, 0x32, 0x8e, 0x20, 0x12, 0x69, 0x2e, 0x83, 0xe0,
+ 0x28, 0x2e, 0xcd, 0xd5, 0x07, 0x66, 0xca, 0xa7, 0xc7, 0xf9, 0xb8, 0x44,
+ 0x73, 0x4e, 0x55, 0x4c, 0xf8, 0x23, 0x6e, 0x59, 0xcc, 0xa3, 0xe1, 0xc6,
+ 0xc9, 0xd6, 0x3e, 0x1e, 0xca, 0xb2, 0x33, 0x7c, 0xd6, 0x3e, 0x03, 0xa4,
+ 0x12, 0xc6, 0xea, 0x1f, 0x1c, 0x73, 0x85, 0x1c, 0x70, 0x43, 0x2e, 0xda,
+ 0x80, 0x60, 0x25, 0xe2, 0xf7, 0x6c, 0x64, 0xc8, 0x24, 0x70, 0x85, 0x83,
+ 0x1a, 0xb0, 0x66, 0xb4, 0x4e, 0x5c, 0x29, 0x22, 0x08, 0xc4, 0x70, 0xde,
+ 0x23, 0x85, 0x77, 0xe5, 0xae, 0x71, 0x1d, 0x3b, 0x8d, 0x88, 0x67, 0x2d,
+ 0x96, 0x63, 0xe2, 0x64, 0x88, 0x7d, 0x59, 0x2e, 0x86, 0x61, 0x75, 0x86,
+ 0xc6, 0x15, 0x7c, 0x94, 0xf7, 0x4d, 0xf7, 0xdb, 0x7e, 0x42, 0x1c, 0x84,
+ 0x36, 0x89, 0x2c, 0xad, 0xbd, 0xe2, 0x6a, 0xe1, 0xbe, 0x09, 0x27, 0x25,
+ 0xff, 0x95, 0x9d, 0x2f, 0x4f, 0x97, 0x33, 0x59, 0x18, 0xe5, 0x6a, 0xcf,
+ 0x2c, 0x88, 0xd4, 0xde, 0xea, 0x73, 0x5e, 0x1a, 0xc4, 0xa0, 0xe7, 0xf7,
+ 0xf7, 0xe1, 0x4e, 0xb8, 0xea, 0xda, 0xc4, 0xa7, 0xd4, 0x51, 0xfc, 0xe2,
+ 0xfe, 0xbe, 0xfd, 0xe5, 0x63, 0x45, 0x93, 0x61, 0x93, 0xe3, 0xfa, 0x50,
+ 0xa5, 0xac, 0x56, 0x1a, 0x59, 0x47, 0x56, 0x94, 0xee, 0x52, 0x04, 0x53,
+ 0x86, 0xbe, 0x20, 0x68, 0x7f, 0xe2, 0x2d, 0x77, 0x77, 0x04, 0x01, 0x33,
+ 0x5d, 0x9b, 0x13, 0xc9, 0x15, 0x24, 0x84, 0xe2, 0xa5, 0x41, 0xb3, 0x6e,
+ 0x4b, 0xcd, 0x79, 0xea, 0x06, 0x29, 0xa4, 0xb9, 0x2c, 0x7b, 0x8e, 0x6a,
+ 0xc4, 0x4d, 0x3e, 0xa3, 0xd7, 0x50, 0x30, 0xcf, 0xb4, 0xb0, 0x63, 0x96,
+ 0x3f, 0x2f, 0x96, 0x4d, 0xa6, 0x20, 0x68, 0xe8, 0x53, 0xcf, 0x63, 0x6c,
+ 0xd9, 0x67, 0x30, 0xf2, 0xab, 0x5f, 0x1f, 0x95, 0x11, 0x3d, 0x94, 0x10,
+ 0x8c, 0x4b, 0x20, 0xf9, 0x34, 0x9e, 0x99, 0x49, 0x76, 0x80, 0x57, 0x63,
+ 0x87, 0xd9, 0x5e, 0x42, 0x12, 0xcf, 0x9a, 0xdd, 0x9b, 0xd5, 0xe6, 0xc0,
+ 0xbf, 0x04, 0x79, 0x8c, 0x46, 0xd3, 0x23, 0xce, 0x75, 0x55, 0x56, 0x66,
+ 0x53, 0xe7, 0x43, 0x0f, 0xe9, 0x25, 0x08, 0x1a, 0xe0, 0xae, 0x6c, 0x21,
+ 0x3d, 0xb3, 0x0d, 0xae, 0x76, 0x76, 0x53, 0x36, 0x22, 0xa4, 0xda, 0xe2,
+ 0x1f, 0x72, 0x17, 0xe8, 0xb8, 0x1f, 0xbb, 0x8a, 0x76, 0xfd, 0x63, 0xf8,
+ 0xdb, 0x67, 0x00, 0x79, 0x6b, 0xf4, 0x48, 0xf9, 0x3f, 0x97, 0x98, 0x57,
+ 0xcf, 0xb2, 0x6c, 0xa1, 0x2b, 0x26, 0x55, 0xc1, 0xe5, 0x34, 0xea, 0x61,
+ 0x84, 0x14, 0xc0, 0x54, 0x88, 0x63, 0xbf, 0xea, 0x80, 0xe3, 0xf6, 0x26,
+ 0xbf, 0x93, 0x66, 0x85, 0x47, 0xb9, 0x08, 0x20, 0xc8, 0xad, 0x30, 0xb3,
+ 0xfa, 0x44, 0xba, 0x2d, 0xc3, 0x58, 0xec, 0xb6, 0x59, 0xa2, 0x91, 0xc5,
+ 0xde, 0xec, 0xc6, 0xc5, 0xaf, 0x45, 0xa2, 0x5f, 0x21, 0x0e, 0xc2, 0x4e,
+ 0x78, 0x05, 0xb9, 0x47, 0xb8, 0x1f, 0xf2, 0x0e, 0xb9, 0xee, 0x2a, 0x22,
+ 0x07, 0xbc, 0xa2, 0x9b, 0xbc, 0x82, 0x21, 0xab, 0x45, 0x18, 0x78, 0x0b,
+ 0x2c, 0xc0, 0x65, 0xe0, 0xfa, 0x92, 0x99, 0x3f, 0x78, 0x1f, 0x4a, 0x2e,
+ 0x28, 0x4e, 0xf8, 0xcf, 0x21, 0x88, 0x27, 0x4b, 0x42, 0x5e, 0xc8, 0xb1,
+ 0xe3, 0xeb, 0x47, 0x98, 0x3d, 0x8a, 0xc3, 0x28, 0x4b, 0xf6, 0x51, 0xbb,
+ 0xec, 0x96, 0xab, 0x02, 0x15, 0x98, 0xc1, 0x84, 0xb3, 0xe8, 0xa8, 0x00,
+ 0xfe, 0x92, 0xd2, 0x34, 0x08, 0x9c, 0x61, 0x83, 0xd0, 0xc5, 0x64, 0x68,
+ 0x9b, 0xf4, 0xf1, 0xac, 0xa4, 0xb0, 0xdd, 0xda, 0x2a, 0x5e, 0x55, 0x80,
+ 0xa6, 0x02, 0x98, 0x7b, 0xe6, 0x36, 0x53, 0xbf, 0xc4, 0x95, 0x54, 0xb8,
+ 0x7a, 0x5f, 0x52, 0x66, 0xb3, 0xad, 0x5f, 0x61, 0xdb, 0x91, 0x37, 0x43,
+ 0x30, 0x7b, 0xb4, 0xe3, 0x95, 0xc6, 0xe9, 0xb7, 0x41, 0x38, 0x64, 0xd8,
+ 0x48, 0x59, 0x87, 0x27, 0xf7, 0x5a, 0x50, 0xa8, 0xe9, 0x8a, 0x8b, 0x14,
+ 0xac, 0x04, 0x53, 0x26, 0xbf, 0x25, 0x82, 0x1e, 0x68, 0x3a, 0x91, 0x72,
+ 0x5c, 0xd8, 0x00, 0xd3, 0x46, 0x5e, 0x4e, 0x11, 0x2e, 0x21, 0x35, 0x79,
+ 0x82, 0x52, 0xb1, 0x82, 0xfe, 0x24, 0x83, 0x59, 0x47, 0xea, 0x3c, 0x97,
+ 0x23, 0x42, 0x13, 0x7d, 0x81, 0x86, 0x6b, 0xd5, 0xfa, 0x1c, 0x26, 0xb6,
+ 0x62, 0x4f, 0x1c, 0xcb, 0xd6, 0xb0, 0x30, 0xd0, 0xae, 0x54, 0x84, 0xd7,
+ 0x4a, 0x92, 0x96, 0xd5, 0xfe, 0x13, 0x99, 0x54, 0x8d, 0xea, 0xc6, 0xf9,
+ 0x2c, 0x8c, 0xbf, 0x1f, 0xe5, 0x33, 0xd1, 0xc5, 0xfe, 0xbe, 0xcc, 0xa9,
+ 0x0c, 0x13, 0x52, 0xd9, 0x0f, 0x4b, 0xda, 0xfc, 0x5a, 0xc2, 0x78, 0xaf,
+ 0x20, 0x85, 0x71, 0x04, 0x11, 0x34, 0x01, 0xe1, 0x2b, 0xa6, 0xfb, 0x40,
+ 0x85, 0x25, 0xfc, 0xdb, 0x61, 0x62, 0xeb, 0x52, 0x00, 0x8e, 0x7c, 0x6e,
+ 0x6e, 0xa9, 0xa1, 0x45, 0xd5, 0x36, 0x3c, 0x21, 0x02, 0x38, 0x0f, 0xa4,
+ 0x8f, 0xfa, 0x26, 0x94, 0x40, 0xfb, 0xad, 0x60, 0x72, 0x38, 0xed, 0xc5,
+ 0x0d, 0xd1, 0x50, 0x7e, 0x82, 0xd1, 0xfc, 0xb6, 0x18, 0x7c, 0x4b, 0x0b,
+ 0x77, 0x53, 0x4b, 0x1a, 0xa7, 0xdc, 0x25, 0x9b, 0x56, 0x98, 0x5e, 0x9d,
+ 0xd6, 0xb3, 0x41, 0xde, 0x25, 0x7c, 0x46, 0x96, 0x74, 0x01, 0x3a, 0x5e,
+ 0xb9, 0x11, 0x4a, 0x45, 0x1a, 0xed, 0x13, 0x34, 0x6c, 0x80, 0x37, 0xf9,
+ 0x08, 0xbb, 0x79, 0xb6, 0xd3, 0x52, 0x85, 0x46, 0xd8, 0x0a, 0xb3, 0xb2,
+ 0x03, 0xac, 0x62, 0x1c, 0xf3, 0x59, 0xf9, 0xf9, 0x80, 0xab, 0x80, 0x3b,
+ 0x31, 0x0b, 0x5b, 0x02, 0x71, 0xc8, 0xed, 0x41, 0x0d, 0x90, 0x46, 0xb2,
+ 0x85, 0x04, 0xc5, 0xc0, 0x11, 0xbf, 0xd0, 0x9a, 0x73, 0x3d, 0xe3, 0x60,
+ 0x29, 0xa9, 0xab, 0xd9, 0xd7, 0x2a, 0x9b, 0x0c, 0x82, 0x74, 0x51, 0x3d,
+ 0x68, 0x90, 0x1e, 0xa5, 0xd6, 0x5e, 0x9c, 0x8c, 0xfc, 0x24, 0x70, 0x31,
+ 0x1f, 0x84, 0x9c, 0x87, 0x92, 0xd0, 0x58, 0x7e, 0x86, 0x25, 0x12, 0xd5,
+ 0x7d, 0xfd, 0x37, 0x6c, 0x7d, 0x5f, 0xb6, 0xab, 0x6a, 0x0d, 0x0d, 0x31,
+ 0x9b, 0x75, 0x29, 0x92, 0x3b, 0x1e, 0x26, 0x9e, 0x91, 0x82, 0x53, 0xbf,
+ 0xcd, 0xe0, 0x07, 0x9a, 0x8b, 0x4e, 0x2c, 0x02, 0xd3, 0x31, 0x3c, 0xed,
+ 0xef, 0xac, 0x3b, 0xb3, 0x0a, 0x30, 0x08, 0xac, 0x20, 0x4d, 0x42, 0x08,
+ 0x9b, 0x33, 0xb8, 0xb4, 0xb3, 0x62, 0x52, 0x3d, 0xb4, 0x40, 0xc1, 0xa7,
+ 0x9f, 0x50, 0x7e, 0xce, 0xbf, 0xee, 0x08, 0x2a, 0x94, 0x58, 0x12, 0xa1,
+ 0x63, 0x4b, 0x4d, 0x42, 0xf3, 0x89, 0x1d, 0xa0, 0x36, 0x06, 0x62, 0x31,
+ 0xe7, 0x7a, 0x07, 0x45, 0x3f, 0xbb, 0xcd, 0xf9, 0x25, 0xc5, 0x19, 0x44,
+ 0x0d, 0x81, 0x32, 0x7c, 0x34, 0xac, 0x6e, 0x32, 0x5e, 0x36, 0x1e, 0x32,
+ 0x21, 0xb9, 0x99, 0xd8, 0xab, 0xd1, 0xdd, 0xe4, 0x25, 0xcc, 0xa2, 0x92,
+ 0x47, 0xd7, 0xd9, 0x6d, 0x2c, 0x4f, 0x24, 0x58, 0x4e, 0xc1, 0xaf, 0xfc,
+ 0xdd, 0x37, 0x3b, 0xc9, 0x69, 0x73, 0x76, 0xf3, 0x35, 0xf3, 0xa2, 0x55,
+ 0x98, 0x3b, 0x98, 0x0e, 0x9f, 0xc3, 0xc6, 0xa5, 0xf4, 0x7d, 0xd2, 0xb6,
+ 0xdb, 0x8d, 0xfe, 0xe4, 0x3a, 0x99, 0x2b, 0x76, 0xc3, 0x6d, 0x87, 0xec,
+ 0x07, 0xa2, 0x9d, 0x1c, 0xc9, 0x80, 0x40, 0x92, 0x8d, 0x74, 0x1a, 0x47,
+ 0xc4, 0x41, 0xd5, 0xed, 0x17, 0x5c, 0x65, 0x25, 0x6d, 0x5a, 0x08, 0xc8,
+ 0xb4, 0x29, 0xbc, 0x27, 0x8f, 0x6c, 0x49, 0x08, 0xe1, 0x9b, 0x3e, 0xb1,
+ 0x25, 0x10, 0x61, 0x09, 0x98, 0x2c, 0x88, 0x5d, 0x67, 0x83, 0xa2, 0x3f,
+ 0xc1, 0xa6, 0x15, 0xf2, 0x4f, 0xf7, 0x08, 0x6a, 0x86, 0xa4, 0x48, 0x26,
+ 0xf0, 0x2b, 0x69, 0x13, 0x36, 0xdc, 0x5d, 0x38, 0x16, 0x5a, 0x7f, 0xd3,
+ 0x28, 0x17, 0x50, 0x33, 0xab, 0xed, 0x87, 0xcf, 0xd6, 0x8e, 0x7e, 0xbf,
+ 0x3a, 0xda, 0x1f, 0x5d, 0x0c, 0xbb, 0x57, 0x4e, 0x90, 0xdc, 0x42, 0xdb,
+ 0xe7, 0x10, 0x04, 0xc9, 0xaa, 0x48, 0x45, 0x5a, 0x2b, 0x8b, 0xe2, 0x86,
+ 0xc1, 0xf1, 0xd8, 0x6a, 0xbb, 0x1b, 0x64, 0xab, 0x8c, 0xc1, 0xe9, 0x40,
+ 0x44, 0x84, 0xc3, 0x73, 0x9c, 0xcf, 0x30, 0x05, 0x33, 0x30, 0xc3, 0x7b,
+ 0xe7, 0xb5, 0x84, 0xf4, 0x51, 0xbd, 0xf5, 0xa4, 0x9c, 0x91, 0x59, 0x24,
+ 0x02, 0xac, 0x1d, 0x14, 0xaf, 0xdc, 0x3f, 0x7f, 0x7f, 0xfc, 0xfe, 0xeb,
+ 0xbd, 0xd6, 0x9d, 0x39, 0x2b, 0xcb, 0x3a, 0x13, 0x1f, 0x3d, 0xa3, 0x90,
+ 0xf3, 0x72, 0xb1, 0xfd, 0xd8, 0x42, 0x40, 0x44, 0x2e, 0x71, 0x82, 0xda,
+ 0xd3, 0x5b, 0x89, 0x4d, 0x73, 0x52, 0xe8, 0x84, 0x24, 0x9e, 0xe1, 0xe3,
+ 0x55, 0x67, 0xeb, 0x72, 0x72, 0x53, 0x3f, 0x67, 0x63, 0xd7, 0x23, 0x91,
+ 0xdf, 0xed, 0xba, 0xd5, 0xa3, 0xd3, 0x83, 0x6f, 0x47, 0xcf, 0x9f, 0x0c,
+ 0xf9, 0xe6, 0x37, 0xc2, 0xa4, 0xc9, 0x27, 0x82, 0xbe, 0x1f, 0x29, 0x33,
+ 0x1f, 0x39, 0x56, 0xae, 0x9c, 0x06, 0xd9, 0x42, 0xc8, 0xcc, 0x95, 0x97,
+ 0x4b, 0x0b, 0xe7, 0xee, 0x41, 0x27, 0xf5, 0xf9, 0xb0, 0x11, 0xb4, 0x55,
+ 0xa4, 0x66, 0x9e, 0xd6, 0xda, 0xf0, 0xaa, 0x6b, 0x04, 0xd1, 0x71, 0x04,
+ 0x0a, 0xc1, 0xc6, 0x92, 0xcf, 0xfa, 0x5d, 0x71, 0xc7, 0x70, 0x0a, 0x23,
+ 0xff, 0xcd, 0x96, 0xd4, 0x37, 0xd0, 0x23, 0xac, 0x09, 0x6f, 0x55, 0xc9,
+ 0x51, 0x59, 0x79, 0x8d, 0x26, 0xa7, 0x2b, 0xd4, 0x0d, 0x56, 0x36, 0x3b,
+ 0x95, 0xa7, 0xf6, 0xb6, 0xb6, 0x9c, 0x45, 0x8b, 0x63, 0x0b, 0x87, 0xbf,
+ 0x9f, 0x56, 0xc0, 0x7d, 0xa6, 0xbf, 0x8a, 0x28, 0xd2, 0x4f, 0xa3, 0x8a,
+ 0x40, 0x4a, 0xfe, 0x85, 0x54, 0xf1, 0xf9, 0x2a, 0x66, 0x1b, 0x29, 0xb3,
+ 0xf2, 0x24, 0x5d, 0x48, 0xcd, 0x95, 0xff, 0x46, 0x54, 0x91, 0x26, 0x9f,
+ 0x46, 0x17, 0x69, 0x97, 0x30, 0x22, 0x19, 0xca, 0xbf, 0x27, 0xc2, 0x21,
+ 0x46, 0xf1, 0x62, 0x60, 0xb1, 0xda, 0x7f, 0x05, 0xc5, 0xbc, 0x90, 0x99,
+ 0x6e, 0xc0, 0x08, 0x2c, 0x0e, 0x4e, 0xc5, 0x11, 0x54, 0x5b, 0xfc, 0x0a,
+ 0xc0, 0x78, 0x96, 0x48, 0x36, 0xf5, 0x32, 0x58, 0xcd, 0x83, 0x22, 0xd4,
+ 0x15, 0x84, 0x33, 0xff, 0x72, 0x5a, 0xfb, 0x3f, 0x82, 0x03, 0xbd, 0x70,
+ 0x48, 0xfb, 0x9f, 0x42, 0x72, 0x2f, 0xae, 0x2d, 0xc9, 0xc5, 0x4a, 0x50,
+ 0x2a, 0x6f, 0xfa, 0xad, 0x49, 0xae, 0x23, 0x7b, 0x04, 0x72, 0x95, 0xae,
+ 0x3a, 0x80, 0x0e, 0x2a, 0xa3, 0x61, 0xd3, 0x2f, 0x1e, 0x96, 0x3b, 0x3b,
+ 0x41, 0x34, 0xe1, 0x24, 0xb0, 0xe8, 0x61, 0x6a, 0x36, 0xb3, 0xd7, 0x73,
+ 0x35, 0x30, 0x36, 0x92, 0x19, 0x41, 0x70, 0x67, 0xbe, 0x78, 0x92, 0xd8,
+ 0x83, 0x6c, 0x29, 0xa1, 0x77, 0x25, 0xee, 0x01, 0x97, 0x1b, 0x50, 0x1a,
+ 0xb7, 0x8e, 0x8a, 0x48, 0x4c, 0x21, 0x9c, 0xc1, 0xb3, 0xa7, 0xef, 0x5a,
+ 0x9f, 0xce, 0x2d, 0x1b, 0x4d, 0x02, 0xd8, 0xc8, 0xc7, 0x12, 0xac, 0xfe,
+ 0x4f, 0xe1, 0xa1, 0x2f, 0x3e, 0x8d, 0x9c, 0xff, 0x19, 0x37, 0xeb, 0x7f,
+ 0x23, 0xe2, 0x8d, 0x6d, 0xf3, 0x86, 0x20, 0x65, 0xb1, 0x72, 0xc8, 0x17,
+ 0xcb, 0x26, 0xe3, 0x9e, 0x58, 0x21, 0x1e, 0xab, 0x78, 0x7c, 0xf6, 0xdd,
+ 0x4b, 0x04, 0xbf, 0x8d, 0x42, 0xa0, 0xf7, 0x93, 0xc3, 0xfd, 0xb3, 0xc8,
+ 0xcd, 0x70, 0x65, 0x54, 0xfe, 0x45, 0x3e, 0x20, 0xb5, 0x8a, 0x4c, 0x70,
+ 0xaf, 0xe5, 0x17, 0x22, 0xf1, 0x98, 0x91, 0x51, 0x0d, 0xa4, 0xfa, 0x3c,
+ 0x23, 0x49, 0xb3, 0xc7, 0x18, 0xb3, 0x14, 0xfd, 0x8c, 0x0c, 0x90, 0x93,
+ 0xf9, 0x74, 0x8b, 0xff, 0x1c, 0x5c, 0xfe, 0x7d, 0x1a, 0xaa, 0x7a, 0x3e,
+ 0x4a, 0x73, 0x2b, 0x33, 0x4e, 0xa0, 0xaf, 0xf3, 0x66, 0x55, 0x41, 0xe0,
+ 0x7a, 0xcf, 0x3f, 0xe6, 0x89, 0xa4, 0x7a, 0x42, 0xf7, 0x5d, 0x35, 0x31,
+ 0x0c, 0x2f, 0xc0, 0xe2, 0x87, 0xef, 0x12, 0x10, 0xf8, 0xf4, 0xed, 0x96,
+ 0xd7, 0x90, 0x6d, 0xfd, 0xb1, 0xc6, 0x23, 0x09, 0x3c, 0xae, 0xaf, 0x2d,
+ 0x02, 0x7c, 0x93, 0x17, 0xb9, 0x23, 0x56, 0x6b, 0x82, 0x2f, 0x2f, 0x81,
+ 0xf7, 0x5a, 0x67, 0x75, 0x50, 0x13, 0x23, 0x93, 0x74, 0x26, 0x6f, 0x0c,
+ 0x76, 0xd7, 0xb9, 0x80, 0x8a, 0x80, 0x93, 0x15, 0x93, 0x7c, 0x91, 0xce,
+ 0x24, 0xcd, 0xf0, 0xd1, 0x4a, 0x3e, 0xdd, 0x42, 0x28, 0xed, 0x09, 0x19,
+ 0x65, 0xbb, 0x5b, 0x5c, 0x8c, 0xc8, 0xdf, 0xc3, 0xaf, 0xd5, 0x02, 0x67,
+ 0x9a, 0xcb, 0x8b, 0xdd, 0xc3, 0x01, 0x15, 0x3d, 0x1d, 0xb1, 0xfb, 0xc4,
+ 0xf2, 0xf0, 0x40, 0x98, 0x94, 0x44, 0x46, 0x12, 0xca, 0x1e, 0xda, 0x79,
+ 0xf5, 0x72, 0x27, 0xa9, 0xd3, 0x07, 0x60, 0x75, 0xd4, 0xf2, 0xf2, 0xf3,
+ 0xe1, 0xb3, 0xad, 0xe7, 0xc3, 0xe7, 0x89, 0xab, 0x73, 0x8a, 0x84, 0x1f,
+ 0x69, 0xde, 0xb0, 0xce, 0x00, 0xa3, 0xa1, 0x11, 0x2e, 0xfe, 0xfe, 0xe8,
+ 0x80, 0xa4, 0x11, 0xcd, 0x39, 0xed, 0x28, 0x78, 0x09, 0xaf, 0x1b, 0x2d,
+ 0x9c, 0xd6, 0xe9, 0x89, 0x29, 0xa5, 0x91, 0xe5, 0x50, 0xd2, 0x44, 0xf0,
+ 0x7e, 0x61, 0x07, 0x42, 0xbc, 0x92, 0xa9, 0x54, 0xd6, 0x25, 0x0a, 0x48,
+ 0xe1, 0x2f, 0x89, 0xb7, 0x60, 0xc3, 0xc7, 0x6b, 0xd3, 0xd4, 0x8d, 0xd1,
+ 0x52, 0xab, 0x78, 0x94, 0xd0, 0xb9, 0x18, 0x23, 0x39, 0xe0, 0x82, 0xaa,
+ 0x2f, 0xb3, 0xfb, 0x56, 0xde, 0x11, 0x6b, 0x66, 0x3b, 0xa7, 0x42, 0x23,
+ 0x60, 0x22, 0x75, 0x17, 0x5b, 0xd9, 0x0c, 0x52, 0x6e, 0x06, 0x75, 0x6a,
+ 0xd7, 0x07, 0xeb, 0x7a, 0x4d, 0x69, 0xfc, 0x0c, 0x75, 0xd6, 0xb0, 0xc5,
+ 0xb4, 0x5b, 0xa1, 0xe0, 0x37, 0x97, 0x5b, 0x1b, 0xba, 0x0d, 0x9a, 0x6c,
+ 0x56, 0x64, 0x8d, 0x14, 0x3f, 0x4c, 0x5e, 0x9f, 0x9e, 0x5d, 0xbc, 0xb9,
+ 0x4d, 0x67, 0x41, 0x8c, 0x07, 0x61, 0xfa, 0x69, 0xa9, 0x48, 0x6b, 0xcd,
+ 0xa5, 0x37, 0xbd, 0xdc, 0xa8, 0x91, 0x4d, 0x12, 0xf2, 0x8a, 0x4a, 0x06,
+ 0xb9, 0x40, 0x17, 0x17, 0x7f, 0x3d, 0x3b, 0x7a, 0xf3, 0x9a, 0x6c, 0xc1,
+ 0x5f, 0x90, 0x3d, 0xbe, 0x6e, 0x99, 0x86, 0xa9, 0x28, 0x71, 0x78, 0x33,
+ 0xfe, 0x70, 0x78, 0x3c, 0x3a, 0x3b, 0x39, 0x3d, 0x78, 0xf3, 0xfa, 0x07,
+ 0xf2, 0x60, 0x9a, 0xd5, 0x7b, 0xf0, 0xde, 0xb5, 0x9f, 0xd9, 0x7c, 0x87,
+ 0xb0, 0x14, 0xdb, 0xd1, 0xf7, 0x1f, 0x8f, 0xde, 0x7f, 0xf7, 0xe6, 0xf5,
+ 0x6d, 0x5a, 0xf5, 0x69, 0x7e, 0xfc, 0x36, 0x01, 0x41, 0x44, 0x6a, 0xf4,
+ 0x7a, 0x6b, 0x74, 0x41, 0x6b, 0xb4, 0x5c, 0x50, 0xe8, 0xe0, 0x23, 0x61,
+ 0x65, 0xe0, 0xb2, 0xae, 0xf6, 0x59, 0x9b, 0x3a, 0xbc, 0x10, 0x36, 0x4d,
+ 0xf0, 0xd2, 0xa2, 0x0c, 0x1f, 0xce, 0x4f, 0x20, 0xb5, 0x47, 0x8b, 0x95,
+ 0x71, 0x7d, 0x00, 0x57, 0x1e, 0x42, 0x6c, 0x43, 0xae, 0x61, 0x94, 0x62,
+ 0x38, 0xb0, 0xc9, 0x6d, 0x02, 0x60, 0xf9, 0x68, 0x0c, 0x1d, 0xf3, 0x2e,
+ 0x04, 0xd3, 0xda, 0x72, 0xa6, 0x88, 0x1e, 0xe2, 0x4a, 0x5c, 0x66, 0x0a,
+ 0x39, 0x32, 0xe8, 0xb7, 0x34, 0xe7, 0x77, 0x16, 0x9a, 0xbc, 0xbc, 0x98,
+ 0x79, 0xb8, 0xde, 0x05, 0x16, 0xaa, 0xe4, 0x6a, 0x74, 0x18, 0x8f, 0x22,
+ 0x10, 0xb7, 0x67, 0x21, 0xa0, 0x52, 0xf1, 0x0a, 0x0a, 0xb3, 0x19, 0xa0,
+ 0xb5, 0x6f, 0xec, 0xb8, 0x2a, 0xa6, 0xdf, 0x76, 0xf2, 0x83, 0xe6, 0xa6,
+ 0x79, 0x81, 0x85, 0x91, 0xf4, 0xb8, 0x36, 0xdc, 0x26, 0x87, 0x33, 0x92,
+ 0x48, 0x49, 0xa9, 0x7b, 0x66, 0xac, 0x2e, 0x6c, 0x98, 0x37, 0xd6, 0x81,
+ 0x35, 0x87, 0xbe, 0x4c, 0x54, 0x08, 0xb7, 0x67, 0x4e, 0x0f, 0x5b, 0x69,
+ 0x41, 0xaa, 0x37, 0x46, 0x9b, 0x36, 0xdb, 0x91, 0x5a, 0x3c, 0xfb, 0xe0,
+ 0xf0, 0x4b, 0x23, 0xb9, 0xf1, 0xc1, 0x21, 0xec, 0x0a, 0xca, 0x6e, 0xa1,
+ 0x7a, 0x83, 0x1e, 0x15, 0x3a, 0x11, 0x4f, 0x17, 0xca, 0x9c, 0xa8, 0xa5,
+ 0xdf, 0x70, 0x06, 0xaa, 0x72, 0xed, 0x52, 0xe9, 0xd3, 0x68, 0xa9, 0x0e,
+ 0x4e, 0xf5, 0x4a, 0xf6, 0x25, 0x0e, 0x29, 0x6b, 0xd5, 0xe2, 0xe0, 0x3e,
+ 0x86, 0xbd, 0xa4, 0x55, 0x4d, 0x85, 0x3d, 0x6f, 0x9b, 0x41, 0x52, 0xdf,
+ 0x03, 0x5f, 0x11, 0x9e, 0x14, 0x6f, 0x03, 0xfe, 0x4c, 0xf7, 0x34, 0xd4,
+ 0xce, 0xd0, 0xe0, 0x56, 0x18, 0x1b, 0xca, 0x8b, 0x54, 0xf4, 0x00, 0xa7,
+ 0x06, 0x0a, 0x37, 0xd7, 0x9c, 0xa6, 0xec, 0x74, 0x84, 0x2f, 0xd8, 0x14,
+ 0x02, 0x76, 0x35, 0x89, 0x47, 0x51, 0xda, 0x84, 0x30, 0x1f, 0x83, 0x10,
+ 0xe2, 0x4d, 0x8c, 0x2c, 0xea, 0x5f, 0x3b, 0x02, 0x32, 0xb1, 0xc2, 0xc1,
+ 0x85, 0x8b, 0xda, 0xa3, 0xa0, 0xbb, 0x48, 0x7e, 0xbd, 0x14, 0x7b, 0x1b,
+ 0x5c, 0x04, 0xe8, 0x64, 0xf4, 0x02, 0x85, 0xac, 0x79, 0xa1, 0xec, 0x88,
+ 0x10, 0xa5, 0xb9, 0x33, 0x25, 0x49, 0xce, 0x0d, 0x84, 0x8a, 0xa1, 0x84,
+ 0xcf, 0x92, 0x3b, 0x64, 0x45, 0x5e, 0x73, 0x9d, 0xf4, 0xae, 0x66, 0xe5,
+ 0x78, 0x6c, 0x26, 0xd5, 0xd3, 0x3b, 0xce, 0x8c, 0x30, 0xad, 0xae, 0x20,
+ 0xf4, 0xf6, 0x15, 0xbf, 0xce, 0x1d, 0x56, 0x94, 0x54, 0x42, 0x5f, 0xab,
+ 0x72, 0x73, 0x69, 0x77, 0xc5, 0xb5, 0x23, 0xbb, 0x8a, 0x62, 0x47, 0x0f,
+ 0x5e, 0x21, 0x46, 0x8e, 0xc4, 0xc2, 0xe7, 0x89, 0xf6, 0x1f, 0x84, 0xf1,
+ 0x52, 0x2e, 0xa9, 0x4b, 0xfb, 0x14, 0xe6, 0x03, 0x96, 0x23, 0x65, 0x6e,
+ 0xf2, 0x48, 0x9e, 0x27, 0x4d, 0xd8, 0x4c, 0xa0, 0xf7, 0x1f, 0x34, 0x8a,
+ 0x9d, 0x3e, 0xfd, 0xdc, 0xfd, 0xaf, 0x9e, 0x56, 0x33, 0xa2, 0xfa, 0x71,
+ 0x3c, 0xf8, 0x86, 0x0a, 0xc8, 0xd4, 0x5a, 0x42, 0x29, 0x52, 0x31, 0x89,
+ 0xdc, 0x86, 0x2b, 0x5b, 0xcf, 0xe7, 0x57, 0x3f, 0xee, 0x0c, 0x76, 0xb6,
+ 0xb7, 0xb7, 0x7f, 0x1e, 0x2e, 0x68, 0xe9, 0x2e, 0xd1, 0xbc, 0xf9, 0x39,
+ 0x5c, 0xe4, 0x13, 0x32, 0xe4, 0x9b, 0xcd, 0xcc, 0x53, 0x6a, 0x7a, 0x8b,
+ 0xfb, 0xdb, 0xf2, 0x6e, 0xfe, 0x66, 0xb2, 0x18, 0x14, 0x65, 0x2c, 0x44,
+ 0xe6, 0x62, 0x59, 0xa1, 0x2c, 0x83, 0xd6, 0x02, 0xfd, 0xf8, 0xfe, 0xf4,
+ 0xf0, 0xe8, 0x64, 0xff, 0xaf, 0x1a, 0x63, 0x6b, 0x81, 0x13, 0x68, 0x24,
+ 0x1f, 0xb3, 0xb4, 0x7e, 0xf8, 0x58, 0x67, 0x8d, 0xf9, 0x72, 0xe3, 0xd9,
+ 0x26, 0x05, 0xa1, 0x05, 0xd5, 0xa0, 0xaf, 0xb2, 0x56, 0x55, 0x7b, 0x89,
+ 0x57, 0x72, 0xb7, 0x77, 0x47, 0x46, 0xd9, 0x69, 0x07, 0xbe, 0x36, 0xe4,
+ 0x0f, 0x19, 0xcf, 0x6e, 0xea, 0xfc, 0x1f, 0xe6, 0xde, 0x21, 0xa4, 0xbf,
+ 0x30, 0x9e, 0xf9, 0x02, 0x08, 0x0a, 0xe4, 0xd6, 0xa6, 0xdf, 0x92, 0xaf,
+ 0x4e, 0xbe, 0xa5, 0x30, 0x72, 0xab, 0xd3, 0xcc, 0x39, 0x65, 0x3f, 0xf9,
+ 0xe2, 0xc5, 0xce, 0xee, 0xa6, 0x2d, 0x6f, 0xc1, 0xc9, 0x28, 0x74, 0x38,
+ 0x03, 0xb7, 0xfa, 0x3f, 0x32, 0xaf, 0xce, 0x00, 0x73, 0x65, 0xe7, 0x61,
+ 0x44, 0x68, 0x8b, 0x5e, 0x73, 0xc0, 0xa0, 0x83, 0x27, 0xb8, 0x01, 0xe8,
+ 0x1f, 0x25, 0x8a, 0x04, 0xd0, 0x39, 0x17, 0x2e, 0x1b, 0x7c, 0x48, 0x81,
+ 0x4a, 0xaa, 0xd9, 0x98, 0xe1, 0x48, 0x7e, 0x49, 0x5c, 0x36, 0xf9, 0xad,
+ 0x65, 0x9d, 0x27, 0x3d, 0x55, 0x66, 0xb5, 0x67, 0x35, 0x39, 0x89, 0x49,
+ 0xfe, 0x48, 0x5e, 0xeb, 0x6f, 0x5f, 0x84, 0x91, 0x75, 0x09, 0xdc, 0x6c,
+ 0x5d, 0x58, 0x24, 0x88, 0x2d, 0xf0, 0x9e, 0x53, 0x48, 0x23, 0x71, 0x5a,
+ 0x3e, 0x69, 0x52, 0xb1, 0x5b, 0xcf, 0xd1, 0x8a, 0x0a, 0xbf, 0xc4, 0xda,
+ 0x7a, 0xa3, 0xf3, 0xb3, 0x5e, 0x5f, 0x1c, 0x78, 0xa6, 0x8f, 0x81, 0xf9,
+ 0xdb, 0x8c, 0x18, 0xe8, 0x9d, 0x2f, 0xb6, 0x5f, 0x3c, 0x17, 0xfb, 0x1e,
+ 0x06, 0x8a, 0xd4, 0xd3, 0xb0, 0x02, 0x00, 0xbe, 0xb3, 0xd5, 0x7b, 0x81,
+ 0x7d, 0xe1, 0xf2, 0xec, 0x0c, 0xe5, 0xb5, 0x27, 0xc9, 0x16, 0x93, 0xbe,
+ 0x42, 0xdc, 0xaf, 0x8c, 0x8a, 0x90, 0x3d, 0x03, 0x4f, 0xc1, 0x20, 0xc3,
+ 0x62, 0xdf, 0xcf, 0x3b, 0x0b, 0x69, 0xc7, 0xf0, 0x5a, 0x7f, 0x8b, 0x2d,
+ 0xa4, 0x5f, 0x68, 0x58, 0x8a, 0xa4, 0x59, 0x9c, 0x1f, 0x5a, 0xe4, 0x38,
+ 0x1e, 0xd8, 0x4a, 0x6f, 0x8a, 0x62, 0x8e, 0x7b, 0x73, 0x1c, 0xaa, 0x83,
+ 0x54, 0x70, 0x6d, 0xdc, 0xe2, 0xb9, 0xec, 0x16, 0x4a, 0x3f, 0x1e, 0x3e,
+ 0x1e, 0x14, 0xda, 0x9d, 0x1e, 0x5a, 0x78, 0x4d, 0x3f, 0xa3, 0xd3, 0xa2,
+ 0x2f, 0x9c, 0xd2, 0xf9, 0xfb, 0x4e, 0x4b, 0xb2, 0x29, 0xda, 0xab, 0x6e,
+ 0x27, 0x17, 0xa8, 0xce, 0xcd, 0xd3, 0x7b, 0x77, 0xbb, 0x33, 0xdc, 0x8e,
+ 0x3a, 0x39, 0xdf, 0x52, 0x41, 0xb5, 0x36, 0x98, 0x19, 0x4d, 0x47, 0xd1,
+ 0x60, 0xc9, 0x4f, 0x09, 0x06, 0x61, 0x75, 0x30, 0x05, 0xaa, 0x5a, 0x01,
+ 0x3b, 0x46, 0x2f, 0x5b, 0xa4, 0x83, 0x56, 0xc5, 0x90, 0xe7, 0xc1, 0xc9,
+ 0x34, 0x83, 0xda, 0xf9, 0x75, 0x83, 0xda, 0xf9, 0x5d, 0x07, 0xb5, 0xfb,
+ 0xeb, 0x06, 0xb5, 0xfb, 0x7b, 0x0d, 0xaa, 0x1a, 0x68, 0x5e, 0x46, 0x1c,
+ 0xb1, 0xf8, 0x5c, 0xab, 0x87, 0x90, 0xc4, 0x43, 0xf8, 0x7e, 0xc4, 0x4e,
+ 0x2f, 0x84, 0xa3, 0x0f, 0x8e, 0xe4, 0x5d, 0x17, 0x41, 0xc3, 0x32, 0x43,
+ 0x18, 0x39, 0x6b, 0xeb, 0x58, 0xd9, 0x98, 0xc3, 0xba, 0x5d, 0x02, 0x93,
+ 0xdd, 0xb5, 0xcb, 0x42, 0xbb, 0x71, 0x71, 0x43, 0x10, 0xea, 0x82, 0x79,
+ 0x4e, 0xb2, 0x5c, 0xc0, 0x54, 0x9f, 0x8a, 0xd0, 0x7e, 0xd9, 0x9e, 0x30,
+ 0x41, 0xe7, 0x44, 0x75, 0x32, 0x2d, 0x38, 0x4b, 0xbe, 0x7d, 0x5c, 0x63,
+ 0xf4, 0xe4, 0x74, 0xc9, 0xc9, 0x49, 0x28, 0x56, 0x9d, 0x17, 0x12, 0xe3,
+ 0xcb, 0x96, 0x45, 0x73, 0x37, 0x5f, 0x95, 0xf8, 0x93, 0xc6, 0xd9, 0x0f,
+ 0x0c, 0x3b, 0x54, 0xa1, 0x07, 0x77, 0x5e, 0xc6, 0x60, 0x9b, 0x14, 0xd7,
+ 0x9f, 0x17, 0x5c, 0x66, 0x8b, 0x6b, 0xdd, 0x97, 0x1e, 0x44, 0x99, 0xc8,
+ 0xb0, 0x2c, 0x83, 0x7f, 0x08, 0x5c, 0xe9, 0x24, 0x32, 0x53, 0x5c, 0x0a,
+ 0x05, 0x73, 0x89, 0xc6, 0x22, 0xe9, 0x73, 0xb6, 0x5e, 0xa1, 0xd6, 0xf4,
+ 0x59, 0x61, 0x07, 0x88, 0xfb, 0x5e, 0x7c, 0xeb, 0x34, 0xe2, 0x67, 0x06,
+ 0xb7, 0x7d, 0xae, 0x5a, 0x3a, 0x2e, 0x6b, 0x44, 0x5b, 0xcb, 0xa2, 0x05,
+ 0x36, 0xa3, 0x7a, 0x92, 0xe7, 0xbf, 0xa7, 0x93, 0x8c, 0x7b, 0x45, 0x37,
+ 0x8f, 0x6f, 0x18, 0x85, 0xc4, 0x62, 0xcb, 0x64, 0xcf, 0x5a, 0x9b, 0x66,
+ 0xf7, 0x8c, 0xb6, 0xcc, 0xee, 0xd8, 0xff, 0x7b, 0x36, 0xcc, 0xfc, 0x3f,
+ 0xd5, 0xe6, 0xa5, 0xa4, 0xc3, 0x7c, 0x96, 0xc2, 0x96, 0x24, 0x4b, 0xc3,
+ 0xd8, 0xb6, 0xb3, 0x2c, 0xa5, 0xdc, 0x74, 0x35, 0x61, 0x5f, 0x67, 0xf7,
+ 0xac, 0xfc, 0x87, 0x97, 0x3d, 0xe7, 0x31, 0x5e, 0xab, 0xd9, 0x6c, 0x7f,
+ 0x74, 0x70, 0x7c, 0xdc, 0x32, 0x22, 0xd2, 0xb2, 0x21, 0x88, 0x4f, 0x52,
+ 0xb2, 0x6a, 0xca, 0x71, 0x71, 0xea, 0x55, 0x60, 0x73, 0xa0, 0xf4, 0x4e,
+ 0xc0, 0x64, 0x52, 0x85, 0xe1, 0xb4, 0xce, 0x35, 0x9f, 0x36, 0xe5, 0x60,
+ 0xad, 0x65, 0x41, 0xd6, 0x01, 0x4a, 0x6c, 0xb8, 0x5e, 0x1a, 0x59, 0xb7,
+ 0xfe, 0xad, 0x09, 0x72, 0xf8, 0x7b, 0x93, 0x5e, 0x24, 0xf7, 0xf1, 0xac,
+ 0xd2, 0xfc, 0xcc, 0x54, 0xa2, 0xf6, 0x25, 0x7f, 0x91, 0x40, 0x74, 0x48,
+ 0x09, 0x64, 0x0a, 0x34, 0x83, 0xd4, 0xf1, 0xa2, 0x44, 0x99, 0x95, 0x90,
+ 0x03, 0xcb, 0x08, 0xcc, 0x50, 0x75, 0xb7, 0x2e, 0x76, 0x9b, 0x4b, 0x2f,
+ 0xfb, 0x5a, 0xe0, 0x0f, 0x22, 0xc4, 0xde, 0x4a, 0x11, 0xc9, 0xcb, 0x52,
+ 0xf4, 0x4a, 0xfb, 0x51, 0xee, 0x94, 0x5e, 0xf4, 0x7e, 0x21, 0x4f, 0xd6,
+ 0x9d, 0x1f, 0xaf, 0xd6, 0x3c, 0x4c, 0x4e, 0xed, 0xc6, 0x0c, 0x8a, 0x3e,
+ 0xd0, 0x22, 0x9b, 0x6a, 0x22, 0xb1, 0x79, 0xf8, 0x7d, 0xa0, 0x99, 0xae,
+ 0x31, 0x5e, 0x20, 0x45, 0x4b, 0xc8, 0xec, 0xfb, 0xe0, 0x80, 0xfe, 0x3c,
+ 0x68, 0x15, 0xae, 0x35, 0xe9, 0x94, 0x87, 0x85, 0x51, 0x0a, 0x16, 0x92,
+ 0xed, 0x16, 0x68, 0x47, 0x3c, 0x89, 0x28, 0xba, 0x61, 0x7c, 0xbe, 0x82,
+ 0xe7, 0xb6, 0x98, 0xe5, 0x0d, 0x2a, 0x58, 0xda, 0xec, 0x29, 0x09, 0xb9,
+ 0x9e, 0x94, 0x33, 0x73, 0xac, 0x03, 0x03, 0x3f, 0xe5, 0x5a, 0xe8, 0x21,
+ 0x20, 0x6b, 0xeb, 0x7c, 0x51, 0x1a, 0xd5, 0x53, 0x00, 0x90, 0xd9, 0xf0,
+ 0x85, 0x37, 0x55, 0xc9, 0xf5, 0xaa, 0x39, 0x86, 0x70, 0xa0, 0x2d, 0xed,
+ 0x0d, 0x79, 0x5a, 0xba, 0x19, 0x46, 0x35, 0xef, 0x73, 0xf0, 0x59, 0x3c,
+ 0x6f, 0x85, 0xef, 0xd2, 0x6f, 0x0d, 0x21, 0x65, 0x55, 0x59, 0x27, 0xdf,
+ 0xbd, 0xd0, 0x2c, 0xf5, 0xef, 0xf3, 0x62, 0x4a, 0xc7, 0x98, 0x0b, 0x84,
+ 0x5b, 0x2b, 0xc8, 0x83, 0x4b, 0xc6, 0x8e, 0xb2, 0x36, 0x75, 0xad, 0xea,
+ 0xeb, 0x52, 0x63, 0x9e, 0xcd, 0x64, 0x9d, 0x99, 0x00, 0x0e, 0xd9, 0x0c,
+ 0x92, 0x90, 0x79, 0x02, 0x0b, 0x5c, 0x3b, 0x81, 0x9e, 0xf1, 0xe7, 0x88,
+ 0x01, 0x3f, 0x24, 0xe5, 0xb8, 0x61, 0x0c, 0x7e, 0x3b, 0xea, 0x8b, 0x7c,
+ 0x72, 0x93, 0xb9, 0x1a, 0xd1, 0xd3, 0x32, 0x8c, 0x1c, 0x87, 0x3e, 0x41,
+ 0x6d, 0x6a, 0x40, 0x6e, 0x47, 0xe0, 0xbd, 0x26, 0x64, 0x9b, 0x6b, 0x8a,
+ 0x01, 0x27, 0xbb, 0x12, 0x0c, 0x6c, 0x6b, 0x2b, 0x72, 0x92, 0x71, 0x1b,
+ 0x13, 0x9a, 0xa7, 0xa8, 0x53, 0x6e, 0x67, 0x02, 0xf0, 0x08, 0x21, 0xca,
+ 0xb4, 0x7e, 0xac, 0x3c, 0x67, 0xbf, 0xe5, 0x1f, 0xe4, 0x05, 0xeb, 0x4b,
+ 0xd0, 0x63, 0x25, 0xa6, 0x79, 0x5b, 0x58, 0x98, 0x97, 0x33, 0xc2, 0x79,
+ 0x29, 0xd6, 0xbf, 0x86, 0x3d, 0x16, 0x66, 0x4a, 0xae, 0xc4, 0x75, 0xe9,
+ 0xf0, 0xcd, 0x43, 0x8a, 0x2e, 0x3b, 0x87, 0xc5, 0xdf, 0x2a, 0x22, 0x40,
+ 0xce, 0xa0, 0x4a, 0x0e, 0xcb, 0xbb, 0x62, 0x70, 0x42, 0xa1, 0xaf, 0xc9,
+ 0x49, 0x79, 0x65, 0x96, 0xea, 0x7d, 0xd4, 0x62, 0xfa, 0xe1, 0xec, 0x7d,
+ 0xb2, 0xf1, 0x81, 0xe6, 0x74, 0x66, 0x9d, 0x52, 0xf4, 0xe4, 0xa6, 0xd4,
+ 0xfc, 0x34, 0xfc, 0xc7, 0x43, 0x5b, 0xef, 0x27, 0x47, 0x3f, 0xec, 0xbf,
+ 0x3b, 0x3b, 0x39, 0xfa, 0x69, 0x85, 0xd6, 0x48, 0x1f, 0x7f, 0xa9, 0x43,
+ 0xa7, 0xd2, 0xd2, 0x52, 0xc4, 0xc2, 0xdc, 0x8a, 0xb3, 0x87, 0xd5, 0x5c,
+ 0x80, 0x0f, 0x8e, 0x12, 0xdf, 0x68, 0x74, 0x76, 0x3c, 0x90, 0x3c, 0x7f,
+ 0x29, 0x77, 0xcf, 0xd0, 0x69, 0x38, 0xbf, 0x92, 0xf6, 0xf6, 0x6d, 0x18,
+ 0xec, 0xab, 0x67, 0xa1, 0xef, 0xa1, 0xd1, 0x9a, 0xb1, 0xc7, 0x40, 0x62,
+ 0x45, 0x51, 0x45, 0xe7, 0x08, 0xbe, 0xa5, 0x48, 0xcb, 0x68, 0x9d, 0x4a,
+ 0xd4, 0x66, 0x9f, 0xa1, 0xe8, 0xd9, 0x6a, 0xde, 0x09, 0x60, 0x0b, 0x6c,
+ 0xa0, 0xe7, 0x02, 0x58, 0x0b, 0xd0, 0x5e, 0x6a, 0x57, 0x88, 0xda, 0xd2,
+ 0x06, 0x73, 0x0b, 0x57, 0xd5, 0x91, 0xd9, 0xc1, 0x9e, 0x91, 0x11, 0x96,
+ 0xc9, 0x5e, 0xef, 0x77, 0x14, 0xa2, 0x3e, 0x58, 0xff, 0xfd, 0x6f, 0x7f,
+ 0x81, 0x48, 0x38, 0xc6, 0x13, 0x17, 0xc8, 0xa3, 0xe4, 0x40, 0xb7, 0xa8,
+ 0x12, 0xc4, 0xe3, 0x14, 0x31, 0x2d, 0x85, 0xe6, 0xbb, 0x7e, 0x9a, 0x5f,
+ 0x45, 0x04, 0x6e, 0xdf, 0x03, 0x85, 0xf7, 0x57, 0x51, 0x81, 0xee, 0x7b,
+ 0x18, 0x9e, 0xf7, 0xa9, 0x74, 0xf0, 0xe1, 0xf7, 0xa5, 0x03, 0x14, 0x0f,
+ 0x7e, 0xfd, 0xe1, 0xfc, 0x64, 0xd5, 0x96, 0xa7, 0x30, 0xee, 0x12, 0xa2,
+ 0x01, 0x95, 0xb7, 0x0f, 0xca, 0xa2, 0xc0, 0x1d, 0x42, 0x57, 0x38, 0xf1,
+ 0x62, 0x5b, 0x14, 0x25, 0xac, 0xc7, 0xa7, 0xf9, 0xbd, 0xca, 0xbc, 0x4c,
+ 0xa3, 0x94, 0x74, 0x8d, 0x2b, 0xc1, 0x43, 0x81, 0x7d, 0x22, 0x7e, 0x46,
+ 0xdd, 0x07, 0x98, 0x6d, 0x1b, 0xad, 0x53, 0x70, 0x24, 0x2f, 0x4a, 0x5b,
+ 0xb2, 0x0e, 0xa6, 0xf3, 0xd8, 0x9d, 0x4b, 0x13, 0x22, 0x70, 0x0a, 0x76,
+ 0x90, 0xf6, 0x6d, 0x36, 0xd9, 0xa0, 0xa4, 0x43, 0x21, 0x22, 0xb8, 0xa4,
+ 0x3e, 0x20, 0x6b, 0xdf, 0xa5, 0xd2, 0xc7, 0x5c, 0x44, 0xb6, 0xb8, 0xb2,
+ 0xae, 0xa9, 0x2f, 0x96, 0x46, 0x92, 0x01, 0x2d, 0xe8, 0x1e, 0x2d, 0x28,
+ 0xee, 0x25, 0x54, 0x39, 0x51, 0xc1, 0x70, 0xab, 0x49, 0x67, 0x37, 0xc8,
+ 0xf5, 0x1e, 0x26, 0xef, 0x78, 0x71, 0xcd, 0x00, 0x09, 0xc4, 0x35, 0x06,
+ 0xab, 0x3b, 0x5e, 0x5e, 0x5d, 0xa1, 0x8a, 0xc3, 0x3e, 0x0b, 0x94, 0xb5,
+ 0xd6, 0xa5, 0x03, 0x2d, 0xad, 0x7f, 0xb1, 0x2e, 0x99, 0xb5, 0x3d, 0x29,
+ 0x64, 0x4b, 0xfa, 0x4d, 0x8f, 0xf5, 0x8b, 0x10, 0xfd, 0x8b, 0x68, 0xbf,
+ 0x9f, 0xac, 0xbf, 0x8e, 0xbf, 0xc4, 0xaa, 0x35, 0x03, 0x6d, 0x4d, 0xac,
+ 0x6f, 0xce, 0x2c, 0xe4, 0x75, 0x6e, 0x24, 0xd4, 0x22, 0x8c, 0xae, 0xe7,
+ 0x64, 0x78, 0x8e, 0x95, 0x60, 0x2d, 0x3e, 0x8d, 0x0e, 0xf2, 0x5f, 0xb5,
+ 0x3f, 0x2d, 0xcd, 0x02, 0x68, 0xbc, 0xcb, 0x32, 0xc0, 0xaa, 0x15, 0x58,
+ 0x2c, 0xe9, 0x3f, 0x74, 0xcd, 0xc2, 0x13, 0x2a, 0xa0, 0x20, 0xca, 0x4d,
+ 0xa4, 0x56, 0x0f, 0x91, 0x1f, 0xe7, 0x06, 0x4b, 0xa1, 0x59, 0x15, 0x6c,
+ 0x78, 0xbb, 0xcd, 0x8e, 0xe5, 0x21, 0x98, 0xb5, 0x4a, 0x47, 0x56, 0x99,
+ 0x71, 0x35, 0x19, 0x00, 0x28, 0x53, 0x51, 0xf2, 0x59, 0x09, 0x10, 0xb7,
+ 0xcb, 0x48, 0x7d, 0x09, 0x91, 0x6c, 0xd4, 0x19, 0xe9, 0xce, 0x0d, 0xe7,
+ 0x15, 0x68, 0x4e, 0x04, 0x29, 0x8d, 0x78, 0x30, 0x2b, 0xb8, 0xa8, 0x8a,
+ 0x18, 0xf9, 0xfb, 0x21, 0x24, 0x33, 0xe3, 0x04, 0x68, 0xe9, 0x42, 0xab,
+ 0x52, 0xb4, 0x55, 0x62, 0x0d, 0x1f, 0xf8, 0xb5, 0x5a, 0x55, 0xab, 0x31,
+ 0x5f, 0xab, 0x8a, 0x78, 0x1a, 0xfd, 0xec, 0xb2, 0x36, 0xd6, 0x2a, 0x52,
+ 0xca, 0x3c, 0x46, 0x73, 0x47, 0x0f, 0x22, 0x00, 0x82, 0x4e, 0x98, 0xd1,
+ 0xdb, 0x21, 0x60, 0x74, 0xb9, 0xce, 0xa1, 0xe0, 0xd3, 0xaa, 0x33, 0x4c,
+ 0xdd, 0xf1, 0x58, 0x34, 0x64, 0x7a, 0x29, 0xb8, 0x31, 0x99, 0x83, 0x66,
+ 0x19, 0x8a, 0x92, 0x13, 0xdc, 0x21, 0x43, 0x1d, 0x07, 0x56, 0x4f, 0x73,
+ 0x6a, 0xac, 0x4b, 0x96, 0x85, 0x6c, 0xee, 0x57, 0x04, 0xb4, 0xa6, 0x92,
+ 0xe4, 0x76, 0x22, 0x19, 0x30, 0x17, 0x81, 0x6c, 0x49, 0x38, 0xae, 0x22,
+ 0x08, 0x10, 0xb9, 0x27, 0xcd, 0xf6, 0x3e, 0xb3, 0x60, 0xb3, 0x3e, 0x07,
+ 0x52, 0x9f, 0xbf, 0xd4, 0xe9, 0x95, 0xc6, 0x3d, 0xf1, 0x32, 0x1a, 0xa3,
+ 0x4d, 0x72, 0x66, 0x8f, 0x9f, 0xed, 0xc1, 0x8e, 0x40, 0xe0, 0x34, 0xac,
+ 0x2a, 0x33, 0x4a, 0x1a, 0xe0, 0xd4, 0x26, 0x4b, 0x52, 0xf1, 0xe1, 0x6e,
+ 0x0d, 0xab, 0x3d, 0xba, 0x3b, 0x05, 0x5a, 0x49, 0xd2, 0xfb, 0x52, 0x6d,
+ 0x0b, 0x3d, 0x31, 0x48, 0x01, 0xab, 0xd1, 0x96, 0x95, 0x54, 0x5d, 0xbc,
+ 0x71, 0xcb, 0x11, 0x71, 0xb9, 0xb0, 0xaf, 0x14, 0xd8, 0x0c, 0xb4, 0x6b,
+ 0xa6, 0xd5, 0x41, 0x2f, 0xaa, 0x61, 0xd9, 0x79, 0x27, 0x52, 0xe6, 0xa3,
+ 0x7d, 0xb4, 0xb4, 0x8b, 0x3b, 0xcd, 0x6f, 0x42, 0x41, 0xa0, 0x26, 0x6f,
+ 0x96, 0xa1, 0x17, 0xc3, 0xa2, 0xa7, 0xc2, 0x45, 0x05, 0x1e, 0x4c, 0x4b,
+ 0xee, 0xfc, 0x48, 0x38, 0x4b, 0x64, 0x3b, 0x69, 0x10, 0x21, 0xc9, 0xf6,
+ 0x98, 0xb1, 0x42, 0x12, 0x77, 0x15, 0xff, 0x7d, 0xd3, 0xa3, 0x1b, 0x5d,
+ 0xdb, 0x8b, 0x61, 0xde, 0xfe, 0xd3, 0x7f, 0xe8, 0x97, 0xc0, 0x80, 0xfc,
+ 0x2f, 0xf5, 0xb9, 0xaa, 0xd3, 0x38, 0x8d, 0xf3, 0xb3, 0xe4, 0x4f, 0x58,
+ 0x15, 0x60, 0x58, 0xf3, 0xd2, 0x00, 0xa2, 0x86, 0x1a, 0xfc, 0xd3, 0xd0,
+ 0xba, 0x8a, 0xa5, 0x91, 0x54, 0xcb, 0x84, 0x87, 0xdc, 0x96, 0x8f, 0xf1,
+ 0x4f, 0x05, 0xd5, 0x2f, 0xd3, 0xfa, 0xe1, 0x82, 0xf9, 0xc0, 0xe4, 0xf5,
+ 0x53, 0x25, 0x4c, 0xb3, 0x49, 0xc7, 0x8c, 0xc1, 0x2b, 0x9f, 0x87, 0x16,
+ 0x21, 0x8a, 0xc3, 0xd8, 0xc3, 0x6e, 0xfc, 0x69, 0xc0, 0x00, 0x9f, 0x42,
+ 0xe1, 0x82, 0xd7, 0xab, 0x9f, 0xf1, 0xc6, 0xdc, 0xe5, 0xc5, 0xb3, 0xdd,
+ 0x81, 0x27, 0xa6, 0xf4, 0xa3, 0xa1, 0x6c, 0x6c, 0xdb, 0x2c, 0x27, 0x13,
+ 0xb8, 0xa2, 0xc8, 0x0e, 0x0d, 0x6b, 0xed, 0x9f, 0x12, 0x81, 0x89, 0x41,
+ 0xa6, 0xf1, 0x12, 0x52, 0xd9, 0x9d, 0x53, 0x4b, 0x57, 0xba, 0x7f, 0x9e,
+ 0x20, 0x1e, 0x07, 0xe1, 0x14, 0x8b, 0xf5, 0x91, 0x02, 0xec, 0x1f, 0xe1,
+ 0x6f, 0xe2, 0x57, 0x0f, 0xf8, 0xa3, 0xc1, 0x05, 0x7d, 0xa4, 0x61, 0x5d,
+ 0x92, 0xc6, 0x4b, 0xda, 0xaf, 0x06, 0x7c, 0xf6, 0x93, 0x10, 0x4d, 0x27,
+ 0x89, 0x85, 0xc9, 0x50, 0xec, 0xa8, 0x39, 0xd2, 0xc1, 0x38, 0xf5, 0x34,
+ 0x7d, 0xe4, 0xb2, 0x3f, 0xf9, 0x6d, 0xf6, 0x78, 0x6b, 0x40, 0x2a, 0x25,
+ 0x27, 0xfa, 0x9c, 0xc4, 0x4f, 0x67, 0xe8, 0xf3, 0xfd, 0xa1, 0x1c, 0x09,
+ 0xc6, 0xa0, 0x13, 0xc3, 0xa7, 0x9a, 0xf3, 0x60, 0xcd, 0xbd, 0x32, 0x74,
+ 0xe6, 0x8a, 0x63, 0xcc, 0x68, 0xf2, 0xa7, 0xcd, 0x40, 0xb9, 0xdc, 0xee,
+ 0x13, 0x73, 0x2d, 0xd9, 0x2e, 0x8a, 0x80, 0x08, 0xaf, 0xda, 0x4d, 0x1b,
+ 0x9a, 0x08, 0x7c, 0x3f, 0x6a, 0xde, 0x4b, 0xa2, 0x7b, 0x9b, 0x1c, 0x53,
+ 0xea, 0x34, 0x62, 0x63, 0x44, 0x5a, 0xc9, 0x01, 0xcb, 0x3b, 0x56, 0xb0,
+ 0x50, 0xdb, 0xd3, 0xe3, 0xcd, 0xd9, 0x51, 0xf0, 0x35, 0x3d, 0xf0, 0x24,
+ 0xac, 0x61, 0x37, 0xef, 0x6a, 0x27, 0x08, 0xc3, 0xbd, 0x6c, 0x16, 0x1f,
+ 0x81, 0xbe, 0xf9, 0x11, 0x60, 0x5c, 0x17, 0x9e, 0xe9, 0x00, 0x1f, 0x60,
+ 0xbd, 0x18, 0x2f, 0xcd, 0x28, 0xda, 0xb9, 0x94, 0x0b, 0x99, 0x95, 0x90,
+ 0xa1, 0x42, 0x6c, 0xa9, 0x70, 0xe5, 0x3a, 0x15, 0x04, 0xd4, 0x95, 0xd2,
+ 0x49, 0xb0, 0x7a, 0x1e, 0x0c, 0x8c, 0xc2, 0x16, 0x3e, 0x02, 0xa5, 0xc4,
+ 0x52, 0x88, 0xb9, 0x38, 0xb2, 0x8a, 0x80, 0xdc, 0x3b, 0x30, 0x26, 0x0c,
+ 0x6b, 0x87, 0x4c, 0xd3, 0x65, 0xa1, 0xe1, 0x12, 0x8f, 0x0f, 0x0c, 0x42,
+ 0xbe, 0x96, 0xf6, 0xd3, 0x32, 0x22, 0x14, 0x4f, 0x84, 0x8c, 0x6d, 0x33,
+ 0x50, 0x12, 0xb5, 0xd5, 0xdb, 0x3e, 0x0c, 0x6b, 0x95, 0x27, 0x41, 0x56,
+ 0xe4, 0xe7, 0xc3, 0x5d, 0xc6, 0xb6, 0x9d, 0xe5, 0xa9, 0xc3, 0x08, 0xe4,
+ 0x19, 0xe0, 0x98, 0x60, 0xbe, 0x40, 0x22, 0xbb, 0x2e, 0xef, 0x9e, 0x3c,
+ 0x5c, 0x1c, 0x26, 0x42, 0x32, 0xdd, 0x70, 0xc5, 0xca, 0x70, 0x65, 0x71,
+ 0xad, 0x35, 0x69, 0x97, 0x86, 0x97, 0x44, 0x2e, 0xe8, 0xee, 0xa2, 0xc4,
+ 0x42, 0xca, 0x92, 0x15, 0x08, 0x31, 0xc9, 0x86, 0x56, 0x3f, 0x66, 0xf5,
+ 0x74, 0xd3, 0x1e, 0x04, 0x56, 0xf8, 0xb4, 0x30, 0xc9, 0x53, 0xcd, 0x81,
+ 0xbb, 0x04, 0xf9, 0xfb, 0xe1, 0x86, 0x23, 0x52, 0xee, 0x63, 0xbe, 0xf0,
+ 0x59, 0x42, 0xab, 0x64, 0xb9, 0xf5, 0x7b, 0x09, 0xbc, 0x29, 0x05, 0xdc,
+ 0x09, 0x13, 0xa3, 0x53, 0xf4, 0xd4, 0x38, 0x26, 0x88, 0x0d, 0x60, 0xa4,
+ 0x07, 0x2f, 0xeb, 0x76, 0xa0, 0xf2, 0x86, 0xd8, 0x81, 0x8e, 0xcf, 0x6e,
+ 0x9f, 0x27, 0xa1, 0xdd, 0xa7, 0xf3, 0x9f, 0x79, 0xea, 0x65, 0xfb, 0x70,
+ 0xbd, 0x8a, 0xa4, 0xe8, 0xf0, 0x94, 0xb8, 0x2a, 0x9b, 0x4e, 0x49, 0x06,
+ 0xef, 0xa7, 0x4f, 0x78, 0x93, 0x68, 0x8f, 0xf3, 0xf1, 0x31, 0x78, 0x93,
+ 0x78, 0x72, 0x24, 0xa6, 0x27, 0x25, 0x19, 0x2a, 0x8d, 0xf9, 0xde, 0x76,
+ 0x6c, 0xee, 0xda, 0xc4, 0x7e, 0x01, 0x38, 0x89, 0x5c, 0xf1, 0x6e, 0x26,
+ 0x50, 0x79, 0x70, 0x08, 0x06, 0x8f, 0x8f, 0xe4, 0x32, 0x38, 0xd1, 0x31,
+ 0x80, 0x06, 0x1a, 0x83, 0x42, 0x0d, 0xd4, 0x76, 0x0c, 0xd8, 0x56, 0xef,
+ 0x63, 0x21, 0xdc, 0x0c, 0x75, 0x21, 0x04, 0xbd, 0xe6, 0x53, 0x4e, 0xf4,
+ 0x2a, 0x42, 0x0b, 0xc7, 0xa1, 0x9d, 0x7d, 0x64, 0x32, 0x86, 0xbd, 0x53,
+ 0x61, 0x90, 0x2c, 0xc0, 0x46, 0x2a, 0xab, 0xa1, 0x36, 0xcb, 0x01, 0x34,
+ 0x7a, 0x1a, 0xd2, 0x13, 0x6b, 0x41, 0x51, 0x75, 0x76, 0x3a, 0x92, 0x49,
+ 0xa2, 0x57, 0xb6, 0x40, 0x3a, 0x10, 0x2a, 0x01, 0x58, 0xc5, 0x84, 0xd2,
+ 0x52, 0x1e, 0x6f, 0x0e, 0xe0, 0x74, 0xb6, 0x41, 0x1b, 0x67, 0x0f, 0x18,
+ 0x0f, 0x16, 0x6c, 0xcd, 0x6d, 0x98, 0x78, 0x79, 0xf4, 0x9f, 0xc2, 0xa8,
+ 0x22, 0x4b, 0x42, 0x0c, 0xda, 0x1e, 0xbe, 0x0b, 0x3f, 0x4e, 0xd6, 0x9c,
+ 0x41, 0x3d, 0x82, 0xff, 0xfb, 0x84, 0x1a, 0x3d, 0x6d, 0x65, 0xd5, 0x39,
+ 0x4f, 0x4f, 0xcd, 0x21, 0x4a, 0xe2, 0x32, 0x07, 0x3d, 0x6d, 0xfe, 0x1c,
+ 0xfe, 0xc9, 0x87, 0x8d, 0x22, 0xb9, 0x3e, 0x2a, 0xe8, 0x29, 0x8f, 0x84,
+ 0x31, 0x99, 0x1c, 0x7e, 0x11, 0xc7, 0x5f, 0xf1, 0xc5, 0x45, 0xa4, 0xae,
+ 0x4f, 0x47, 0xe2, 0xa6, 0xd0, 0x9a, 0x98, 0x15, 0x92, 0xc7, 0x5a, 0x53,
+ 0xd7, 0xa3, 0x6d, 0x0a, 0x8a, 0xfb, 0x13, 0xe4, 0x4a, 0xf5, 0x27, 0xa2,
+ 0x3d, 0xea, 0x49, 0x90, 0x95, 0xe4, 0x2e, 0x1f, 0x99, 0x81, 0xa7, 0xc6,
+ 0x3c, 0xde, 0xa3, 0x7f, 0xce, 0xe2, 0x5d, 0x4b, 0x3c, 0x67, 0xf2, 0x69,
+ 0x4b, 0xb7, 0x32, 0x04, 0xd5, 0x48, 0xf2, 0xd9, 0xd4, 0xed, 0x03, 0xb5,
+ 0x95, 0x92, 0xb5, 0xcf, 0x43, 0xa4, 0xe5, 0x67, 0x3c, 0x29, 0xd3, 0x08,
+ 0x8b, 0xf5, 0xb2, 0x62, 0x78, 0xc9, 0xa7, 0xef, 0x68, 0xd5, 0xa8, 0x6d,
+ 0x7b, 0x14, 0x67, 0x47, 0xa3, 0x5b, 0x10, 0x6e, 0x20, 0x80, 0x8c, 0x56,
+ 0x8c, 0xca, 0x4e, 0x11, 0x8b, 0xab, 0xc3, 0xd2, 0x48, 0xd6, 0xdf, 0x68,
+ 0x54, 0xdc, 0xda, 0xa7, 0x8c, 0xa9, 0x9e, 0x7d, 0x34, 0x43, 0x30, 0xea,
+ 0xb0, 0xd9, 0xf6, 0xda, 0xc8, 0xe1, 0x4f, 0x4b, 0xeb, 0xfc, 0x9c, 0xd2,
+ 0x1c, 0x81, 0x05, 0x98, 0x31, 0x57, 0xc9, 0x24, 0x33, 0xaa, 0x37, 0x4a,
+ 0xd9, 0xb2, 0x79, 0x0e, 0xbf, 0x3f, 0x41, 0x82, 0x1c, 0xfc, 0xad, 0x32,
+ 0x9c, 0x55, 0x47, 0x86, 0x04, 0x99, 0x07, 0x23, 0x17, 0xf5, 0xa0, 0x6d,
+ 0x45, 0x72, 0x5a, 0x92, 0xae, 0xdd, 0xb4, 0xf6, 0xea, 0x38, 0x0d, 0x1f,
+ 0x01, 0xda, 0xb4, 0xfd, 0x1b, 0x45, 0x25, 0x5d, 0x2c, 0xe4, 0x88, 0x3f,
+ 0x3d, 0x77, 0x06, 0x39, 0xe2, 0xa4, 0x9e, 0x12, 0x85, 0x8a, 0x60, 0x44,
+ 0x68, 0xca, 0xf2, 0x26, 0x61, 0x1b, 0x84, 0x44, 0xfa, 0x36, 0x69, 0xf5,
+ 0x44, 0x73, 0x0c, 0x54, 0xc7, 0x8f, 0x13, 0xc2, 0xc7, 0x68, 0xf4, 0x0d,
+ 0xc1, 0x58, 0x5a, 0x7e, 0xb3, 0xe5, 0x1c, 0x76, 0x2c, 0x4b, 0x3f, 0x75,
+ 0x09, 0xda, 0xda, 0x81, 0x58, 0x07, 0x6b, 0xf2, 0xf9, 0xd4, 0x65, 0x68,
+ 0x8b, 0x95, 0xbf, 0xd3, 0x44, 0x2f, 0x0e, 0xce, 0xec, 0x04, 0x13, 0x5b,
+ 0x15, 0xc3, 0x1f, 0xfb, 0xc6, 0x53, 0x74, 0x2e, 0x12, 0x69, 0x7b, 0x8e,
+ 0xd1, 0x19, 0x91, 0x3a, 0x44, 0x26, 0xc7, 0xe5, 0xe2, 0xff, 0x81, 0x8d,
+ 0x45, 0x26, 0x24, 0x09, 0xf2, 0x9c, 0x61, 0x0b, 0x03, 0xee, 0xd3, 0x43,
+ 0xa6, 0x6a, 0x46, 0xf1, 0xf2, 0x5e, 0x31, 0xb5, 0x59, 0x20, 0xb7, 0xc8,
+ 0x02, 0x17, 0x19, 0xb6, 0xad, 0x8e, 0xfd, 0x8b, 0xc6, 0xcc, 0x09, 0x33,
+ 0x0a, 0xa2, 0x46, 0x43, 0x86, 0xed, 0xc6, 0x62, 0x3e, 0x9a, 0x1b, 0xdc,
+ 0xe8, 0x7f, 0x9f, 0xa4, 0x85, 0xb3, 0x41, 0x98, 0x51, 0x8f, 0x09, 0x1d,
+ 0xc0, 0xb6, 0xea, 0xea, 0xc4, 0x19, 0x39, 0x9e, 0xa2, 0xf1, 0x9e, 0x64,
+ 0x13, 0xa9, 0xa4, 0x40, 0xa1, 0x4a, 0x62, 0xe5, 0x21, 0xad, 0x8a, 0x9a,
+ 0xe9, 0xd9, 0xfd, 0x22, 0xb9, 0x6a, 0x81, 0x6a, 0x3a, 0x29, 0x67, 0xec,
+ 0x50, 0xb9, 0x05, 0xee, 0x6c, 0x7c, 0x2f, 0x9c, 0xe4, 0x15, 0x27, 0x10,
+ 0xc2, 0x5c, 0xc4, 0x3a, 0x0b, 0x7c, 0xa5, 0x3e, 0xff, 0x24, 0x9b, 0x32,
+ 0x2c, 0x6e, 0x61, 0x97, 0x87, 0x89, 0x84, 0xc9, 0xb4, 0x6f, 0xcf, 0x06,
+ 0x97, 0x70, 0xfb, 0x34, 0x52, 0x60, 0xa3, 0xa5, 0x85, 0xbd, 0xeb, 0x80,
+ 0xe2, 0x21, 0xb9, 0x8b, 0xbe, 0x14, 0x40, 0xe6, 0xbb, 0xb4, 0x7e, 0x6a,
+ 0x74, 0x29, 0x17, 0x53, 0x6b, 0x2f, 0x82, 0x0b, 0x79, 0xb2, 0x97, 0x4c,
+ 0x92, 0xdd, 0x67, 0x61, 0xd5, 0x8a, 0x18, 0x8b, 0x97, 0x20, 0x1f, 0xc4,
+ 0x58, 0xdb, 0x8c, 0x09, 0x6f, 0xbd, 0x7c, 0x90, 0xb7, 0x27, 0xa5, 0xd8,
+ 0x98, 0x60, 0x8f, 0xb1, 0x62, 0xe4, 0x9f, 0x7e, 0x7c, 0x7e, 0x1f, 0x16,
+ 0xc7, 0x31, 0x31, 0xa8, 0xac, 0x10, 0x1e, 0x9e, 0x71, 0xf6, 0xa9, 0x4a,
+ 0x15, 0xf0, 0xb6, 0xda, 0xc7, 0xa8, 0xcb, 0x20, 0x64, 0xe7, 0x23, 0x20,
+ 0xa1, 0x11, 0xc9, 0x40, 0x76, 0xc0, 0xab, 0x73, 0xc6, 0x10, 0xc3, 0x8a,
+ 0x91, 0x6e, 0x34, 0x53, 0x3a, 0x3e, 0x4d, 0xf6, 0x29, 0x37, 0x0d, 0xdd,
+ 0xff, 0xf1, 0x33, 0x23, 0xb2, 0x62, 0x4b, 0x7e, 0x0b, 0xd7, 0x59, 0xf3,
+ 0xd4, 0x24, 0xde, 0x10, 0x4e, 0x87, 0x4f, 0x21, 0x23, 0x32, 0x61, 0x64,
+ 0x52, 0x28, 0x0a, 0xf3, 0xb1, 0x18, 0x8e, 0xec, 0xf9, 0x50, 0x57, 0xc3,
+ 0x3c, 0x7f, 0x52, 0x55, 0xcb, 0x05, 0x84, 0x16, 0xdc, 0x79, 0x19, 0xb5,
+ 0xb8, 0x22, 0xd9, 0x44, 0x8d, 0x98, 0x3c, 0x21, 0x78, 0x77, 0xad, 0xc9,
+ 0x89, 0x5c, 0x92, 0x19, 0x97, 0x02, 0x71, 0x39, 0x1e, 0xd0, 0x2e, 0x48,
+ 0x78, 0x79, 0x62, 0x04, 0x62, 0x97, 0x54, 0xdf, 0xdb, 0x3a, 0x70, 0x46,
+ 0xc8, 0x32, 0xa9, 0x5e, 0x07, 0x56, 0x81, 0x6d, 0x6e, 0xe5, 0xde, 0xe3,
+ 0xcd, 0x89, 0xa3, 0xee, 0xf7, 0x28, 0x64, 0xe0, 0xa1, 0x17, 0xbc, 0xfe,
+ 0x51, 0xd3, 0x4e, 0xf7, 0xb6, 0xb6, 0x7e, 0xfe, 0xb1, 0x15, 0x06, 0xf1,
+ 0xe5, 0xcf, 0x9f, 0x52, 0xc4, 0xb7, 0x9d, 0x4a, 0xc9, 0x68, 0x3d, 0x31,
+ 0x53, 0x37, 0xf7, 0x17, 0xba, 0x85, 0x72, 0x17, 0x9b, 0x9f, 0x26, 0xde,
+ 0x60, 0xbc, 0x92, 0x97, 0xe5, 0x8a, 0xc2, 0xb8, 0x2d, 0x64, 0x70, 0x6e,
+ 0xdf, 0x02, 0x7c, 0x71, 0x51, 0x63, 0x0b, 0x77, 0xd4, 0xf7, 0x10, 0x6e,
+ 0xfa, 0x51, 0x7c, 0x07, 0xea, 0x92, 0xc2, 0xff, 0x1c, 0x2a, 0x09, 0x1c,
+ 0x45, 0xac, 0x38, 0xb5, 0xb0, 0xc0, 0x81, 0xbb, 0x61, 0x83, 0xd0, 0x63,
+ 0xc8, 0xe6, 0x02, 0xf2, 0x9a, 0xbc, 0x2f, 0x1d, 0x18, 0x84, 0x07, 0xa8,
+ 0x21, 0x59, 0x5c, 0xec, 0xde, 0x20, 0x44, 0x48, 0x52, 0x9f, 0x6d, 0x06,
+ 0x4f, 0x80, 0x78, 0x4b, 0x35, 0xbe, 0xe0, 0xb1, 0xb1, 0x55, 0x88, 0x19,
+ 0x44, 0x53, 0x56, 0x55, 0x9a, 0x17, 0x68, 0x39, 0x67, 0x9e, 0xcc, 0x8b,
+ 0x58, 0x68, 0x25, 0xa3, 0x62, 0xc4, 0x00, 0x37, 0x25, 0x31, 0xfc, 0x11,
+ 0x28, 0x10, 0x35, 0x27, 0xf9, 0x5b, 0x29, 0x79, 0xd7, 0x41, 0x10, 0x34,
+ 0x63, 0x85, 0x30, 0x87, 0x5c, 0x0d, 0x0d, 0x12, 0xf8, 0x63, 0xb3, 0xfb,
+ 0x9c, 0x91, 0x73, 0xfd, 0x28, 0x12, 0xcf, 0x4d, 0x22, 0x26, 0xa5, 0x3a,
+ 0x8b, 0x04, 0xcb, 0x59, 0x24, 0x14, 0xcd, 0x5a, 0x3d, 0x96, 0x78, 0xb4,
+ 0xf5, 0x95, 0x09, 0xca, 0xd4, 0x10, 0xba, 0x4b, 0xd7, 0x22, 0x32, 0xa9,
+ 0xc3, 0xcd, 0xaf, 0x39, 0x3f, 0xfb, 0x1e, 0x19, 0x5c, 0x3d, 0x24, 0x69,
+ 0xea, 0x98, 0x63, 0x91, 0xf6, 0xe4, 0x79, 0xb3, 0x8e, 0x57, 0x4f, 0xc8,
+ 0x91, 0xf8, 0x2d, 0x4a, 0x7c, 0x45, 0x8c, 0x69, 0xe1, 0x17, 0x96, 0x96,
+ 0x24, 0xb1, 0xc8, 0x65, 0x62, 0x64, 0x21, 0x36, 0x6d, 0x80, 0xb6, 0x0c,
+ 0x97, 0x23, 0xd4, 0x49, 0xe1, 0xf3, 0xd4, 0x00, 0x07, 0x27, 0x8b, 0x7a,
+ 0x45, 0x7a, 0xa6, 0xf9, 0x9a, 0xbc, 0xb8, 0x4a, 0x1c, 0xf1, 0x5a, 0xd9,
+ 0x13, 0x7f, 0x88, 0xec, 0xe3, 0x97, 0x2a, 0xc7, 0xd6, 0x17, 0xe5, 0x98,
+ 0x20, 0x60, 0x5c, 0x49, 0x54, 0x48, 0x43, 0x30, 0xbb, 0x4b, 0xbb, 0x4c,
+ 0xcd, 0xd2, 0xc8, 0x3a, 0xb3, 0xb0, 0xba, 0x35, 0xbc, 0x95, 0xcc, 0x90,
+ 0x24, 0x7f, 0x67, 0xb0, 0x50, 0x1e, 0xd4, 0x9d, 0xec, 0x83, 0x34, 0xb2,
+ 0xc2, 0x6b, 0xf6, 0x41, 0x62, 0xef, 0xbc, 0xd0, 0xab, 0x56, 0xc0, 0xb5,
+ 0xab, 0x1e, 0x16, 0xd2, 0x2a, 0xed, 0xc1, 0x5a, 0x68, 0x92, 0xe3, 0x92,
+ 0x1d, 0x5e, 0x64, 0x05, 0xcf, 0xba, 0x8d, 0xf2, 0x41, 0xdd, 0xe1, 0xca,
+ 0xf3, 0x4a, 0x80, 0xa6, 0x93, 0x10, 0x43, 0xa1, 0x82, 0xc2, 0x8a, 0xa2,
+ 0x17, 0x5f, 0xba, 0x64, 0xd1, 0x3f, 0x3d, 0xdf, 0x26, 0xe6, 0xa2, 0x8d,
+ 0xa4, 0x7e, 0xc4, 0xd3, 0x9f, 0x9e, 0xa5, 0x8f, 0x30, 0x4c, 0xa8, 0x50,
+ 0x01, 0xbb, 0xe4, 0xda, 0x37, 0xe9, 0x44, 0x6a, 0xb8, 0xdc, 0xa5, 0x1a,
+ 0xb0, 0x29, 0x94, 0x1b, 0x20, 0x81, 0xc6, 0x0e, 0x53, 0xdf, 0x8f, 0xed,
+ 0x6f, 0x7c, 0x66, 0x22, 0x9c, 0x77, 0x43, 0x18, 0x55, 0x37, 0x8d, 0x59,
+ 0xab, 0xa2, 0xa3, 0x3c, 0x2a, 0xbc, 0x49, 0xb4, 0x29, 0x7f, 0x5e, 0x1d,
+ 0x89, 0xfc, 0xdb, 0x5d, 0x5d, 0x3f, 0x70, 0x11, 0x11, 0xe6, 0xca, 0x2b,
+ 0x4b, 0x62, 0x73, 0x8e, 0xce, 0xc8, 0x26, 0x17, 0xa7, 0x5a, 0x4f, 0x43,
+ 0xdf, 0x94, 0x5c, 0x31, 0x3f, 0x1d, 0x93, 0xda, 0x5a, 0x16, 0x64, 0x95,
+ 0x88, 0x40, 0x2e, 0xb7, 0x5c, 0x85, 0x38, 0xb3, 0x36, 0x8d, 0xe8, 0xa2,
+ 0x75, 0xff, 0x75, 0x41, 0x9d, 0x23, 0xb5, 0x25, 0x3a, 0x95, 0xdb, 0x65,
+ 0x28, 0xae, 0x88, 0x06, 0x96, 0x46, 0xca, 0x08, 0xb8, 0x9c, 0x41, 0xc8,
+ 0x74, 0x5f, 0x1f, 0x5d, 0x6c, 0x86, 0x18, 0xb4, 0xe9, 0xd4, 0x1f, 0x18,
+ 0x52, 0xb5, 0xf4, 0x88, 0xa7, 0xb6, 0x64, 0x8b, 0x4d, 0x9d, 0x2d, 0x08,
+ 0x0d, 0xc4, 0xc8, 0x56, 0x45, 0x1c, 0x4b, 0xf2, 0xc0, 0x2c, 0x03, 0x65,
+ 0xe5, 0xbb, 0x58, 0x24, 0xdf, 0xc6, 0x57, 0x7b, 0x31, 0xd3, 0x94, 0xa1,
+ 0xcf, 0x02, 0xeb, 0xe1, 0xd1, 0xc9, 0xd1, 0xc5, 0x51, 0x1f, 0x00, 0x27,
+ 0x81, 0x21, 0x77, 0x86, 0xdb, 0xab, 0xc9, 0x26, 0xd7, 0x85, 0xa1, 0xf9,
+ 0x2b, 0xda, 0x0e, 0xe4, 0x3d, 0x7f, 0x9f, 0x8d, 0x0f, 0xf7, 0xbf, 0xa3,
+ 0x8a, 0x68, 0x74, 0x66, 0xce, 0xce, 0x4f, 0xcf, 0xde, 0x1e, 0xbf, 0x3f,
+ 0xec, 0x27, 0x07, 0xa7, 0x67, 0x7f, 0xed, 0x27, 0xef, 0x4e, 0xbf, 0x3b,
+ 0x8a, 0x84, 0xd8, 0x52, 0xa8, 0x58, 0x24, 0xf0, 0x49, 0xaa, 0x8e, 0xd8,
+ 0x40, 0x6a, 0xae, 0xb5, 0xd1, 0x8a, 0x30, 0x27, 0x96, 0x8c, 0xea, 0x22,
+ 0xe2, 0x7c, 0x32, 0x4b, 0x69, 0x06, 0xfc, 0xcd, 0xd1, 0xfe, 0x61, 0x57,
+ 0x1c, 0x38, 0x3b, 0x1d, 0x5d, 0x60, 0x5e, 0x34, 0x41, 0x3b, 0x6f, 0x62,
+ 0xdf, 0x86, 0x59, 0x92, 0x9d, 0x9b, 0x94, 0xcc, 0x9b, 0xcc, 0xc3, 0xd0,
+ 0x34, 0x47, 0x00, 0x56, 0xb2, 0xe9, 0xca, 0x6a, 0xca, 0x08, 0x81, 0xb0,
+ 0x91, 0x72, 0x8f, 0xdd, 0x84, 0xe4, 0xe5, 0xf6, 0x01, 0xeb, 0x13, 0xf1,
+ 0x2c, 0x00, 0x60, 0xd4, 0xc2, 0x36, 0xe5, 0x85, 0xb7, 0xe5, 0x6b, 0x51,
+ 0xe7, 0x09, 0x2b, 0x3f, 0x16, 0x80, 0x07, 0xa2, 0x12, 0x87, 0x3f, 0xa4,
+ 0x12, 0xc0, 0x36, 0xce, 0x28, 0xf1, 0xa6, 0x46, 0xc1, 0x1d, 0x2f, 0xea,
+ 0x3a, 0xce, 0xde, 0x35, 0x82, 0x11, 0x21, 0x4e, 0x10, 0xd4, 0xc8, 0x06,
+ 0x49, 0xeb, 0xe7, 0x3a, 0xd4, 0xe2, 0x09, 0x3f, 0xf0, 0xc2, 0x26, 0x31,
+ 0xe0, 0x06, 0x08, 0x14, 0xcb, 0x4b, 0x43, 0x9b, 0x19, 0x47, 0x8b, 0xf0,
+ 0x56, 0x95, 0x2e, 0x0c, 0xf1, 0x98, 0x8e, 0xf8, 0x35, 0x4e, 0x48, 0xfc,
+ 0x0a, 0xd8, 0x78, 0xbb, 0xe2, 0x74, 0xfb, 0x45, 0xc0, 0xa4, 0x45, 0xef,
+ 0xb0, 0x9d, 0x1c, 0x9b, 0x7d, 0xa5, 0xa3, 0xde, 0x8d, 0x22, 0x44, 0xe6,
+ 0x13, 0x97, 0x79, 0xcd, 0x69, 0xab, 0x71, 0xd4, 0x4d, 0x5b, 0x61, 0xc7,
+ 0x04, 0x1c, 0x1c, 0xed, 0x99, 0xbe, 0x78, 0xaa, 0xeb, 0xc0, 0x0c, 0x76,
+ 0x7e, 0x74, 0x71, 0xde, 0xf1, 0xea, 0xbf, 0x8c, 0xd8, 0xf2, 0x36, 0x08,
+ 0xa8, 0x78, 0x33, 0xf1, 0xba, 0x75, 0xfd, 0xd2, 0x57, 0x4f, 0xf4, 0xfb,
+ 0x58, 0x4a, 0xee, 0xb3, 0x18, 0xc8, 0xf0, 0x06, 0x43, 0x22, 0x47, 0x66,
+ 0x49, 0x5f, 0x3c, 0xd2, 0xdb, 0x37, 0x47, 0x27, 0x67, 0xe1, 0x2c, 0xbf,
+ 0x3b, 0x7f, 0xfb, 0xd7, 0xe1, 0x23, 0xc9, 0x96, 0xbf, 0x7d, 0x4c, 0xef,
+ 0x7d, 0xda, 0x34, 0x51, 0x74, 0x71, 0x73, 0x59, 0x72, 0xa5, 0x17, 0x0d,
+ 0x71, 0x02, 0xb8, 0x03, 0x17, 0x55, 0x6b, 0x56, 0x22, 0x0f, 0x9b, 0xa9,
+ 0x07, 0x62, 0x83, 0x4a, 0x58, 0x5c, 0x39, 0xda, 0xb0, 0x56, 0x2e, 0x52,
+ 0x56, 0xb8, 0x82, 0x74, 0x12, 0x61, 0x42, 0x43, 0xc9, 0xc7, 0x54, 0xab,
+ 0xa4, 0x95, 0xd4, 0x1e, 0x11, 0x5e, 0x25, 0x2c, 0x17, 0xbd, 0x59, 0xe9,
+ 0xe5, 0x7e, 0x7a, 0x35, 0x2c, 0xab, 0x9c, 0xec, 0x73, 0x52, 0x41, 0x8e,
+ 0x5b, 0x4b, 0x50, 0x29, 0x95, 0x0e, 0x2d, 0x31, 0x80, 0x58, 0x73, 0x12,
+ 0x31, 0x94, 0x68, 0x86, 0x7a, 0xbb, 0xdd, 0x39, 0x54, 0x7b, 0x04, 0x13,
+ 0xd9, 0x36, 0x87, 0x56, 0x0b, 0x88, 0x04, 0x00, 0x51, 0xc5, 0x55, 0xb3,
+ 0xd1, 0xf3, 0xc4, 0x71, 0x14, 0xd5, 0x38, 0xec, 0x94, 0xdd, 0x5c, 0x29,
+ 0xa6, 0xeb, 0x2e, 0xad, 0x0a, 0x2e, 0x82, 0x1e, 0x60, 0x29, 0xd7, 0xcb,
+ 0xd6, 0x86, 0x3d, 0x20, 0x88, 0x92, 0xdc, 0x24, 0x52, 0x36, 0x82, 0x7e,
+ 0x46, 0x0a, 0x05, 0xa5, 0xce, 0xd5, 0x43, 0x13, 0x22, 0x77, 0xb2, 0xd4,
+ 0x3d, 0xe0, 0x97, 0xb9, 0xc4, 0xc1, 0xb8, 0xe3, 0x20, 0x49, 0xa6, 0xcb,
+ 0x2a, 0x4c, 0xe3, 0x4d, 0x13, 0xaf, 0x43, 0x06, 0x6b, 0xe9, 0xb7, 0x3c,
+ 0x6e, 0x14, 0x88, 0x08, 0xa0, 0x09, 0x36, 0x9d, 0x99, 0xee, 0xbd, 0x17,
+ 0x82, 0x39, 0x39, 0x64, 0x68, 0x0b, 0x39, 0xe7, 0x0d, 0x49, 0x09, 0x75,
+ 0x47, 0x81, 0xfa, 0x49, 0x9d, 0xe0, 0x6c, 0xf4, 0xbf, 0x3e, 0x5e, 0xae,
+ 0x89, 0x63, 0xb9, 0x7d, 0x48, 0x24, 0x96, 0xbd, 0x96, 0xb5, 0xd6, 0x05,
+ 0xa1, 0x9d, 0x48, 0x52, 0x18, 0x35, 0x12, 0xac, 0xc9, 0x5a, 0xd4, 0xd7,
+ 0x49, 0x25, 0x6a, 0x9a, 0x89, 0x07, 0x73, 0x8d, 0xf8, 0x38, 0xf3, 0xa5,
+ 0xa1, 0x64, 0x16, 0x10, 0x0c, 0x93, 0xef, 0x33, 0x46, 0x05, 0xca, 0xe2,
+ 0xc9, 0x7b, 0x83, 0x88, 0x4d, 0x88, 0x4c, 0x5f, 0x2b, 0x58, 0xf3, 0x6f,
+ 0x77, 0x8a, 0xff, 0xea, 0x88, 0x82, 0x17, 0xf1, 0x35, 0xfe, 0xf8, 0x45,
+ 0x64, 0xe1, 0x95, 0xc3, 0x60, 0x2f, 0xdc, 0x86, 0x21, 0xff, 0x16, 0x7d,
+ 0x0c, 0x82, 0x5c, 0xd0, 0xe9, 0xa6, 0x58, 0x35, 0xbd, 0xed, 0x16, 0x33,
+ 0x17, 0xdd, 0xa7, 0x6d, 0xaa, 0x68, 0x91, 0x44, 0x44, 0x29, 0xe5, 0x3d,
+ 0xe6, 0x4c, 0x8d, 0x9c, 0x8a, 0xc1, 0xd2, 0x6d, 0x8a, 0xb3, 0x93, 0xfd,
+ 0x9e, 0x78, 0x64, 0xff, 0x00, 0x1e, 0x19, 0xd5, 0x94, 0xc4, 0x01, 0x78,
+ 0x3d, 0x25, 0x2b, 0xa0, 0x11, 0xfa, 0xc8, 0xef, 0x6f, 0x9a, 0xfe, 0xe2,
+ 0x3f, 0xe3, 0x25, 0x1d, 0xb5, 0xd6, 0xb1, 0x9f, 0xdd, 0xce, 0xce, 0x03,
+ 0xd2, 0xb0, 0x6c, 0xb9, 0xbc, 0x79, 0x39, 0x15, 0x3c, 0xae, 0xb4, 0xd1,
+ 0x95, 0x8e, 0x70, 0x0d, 0x5e, 0x77, 0x2d, 0x5d, 0x44, 0xe7, 0xd0, 0x3c,
+ 0xde, 0x27, 0x2d, 0xa8, 0x2c, 0x56, 0x36, 0x29, 0xa6, 0x6e, 0xfa, 0x36,
+ 0x42, 0x78, 0x6c, 0x27, 0x0c, 0xa6, 0xa3, 0xea, 0x11, 0x99, 0x52, 0x58,
+ 0xc2, 0x33, 0x97, 0x11, 0x1e, 0x62, 0xb5, 0xaf, 0x8e, 0x84, 0x00, 0x99,
+ 0x7d, 0x10, 0xe9, 0x88, 0xc4, 0x45, 0x46, 0x27, 0xa4, 0x78, 0x66, 0x5b,
+ 0xcb, 0xd1, 0x0c, 0xb2, 0x56, 0x4c, 0x39, 0x0a, 0xd0, 0x00, 0x56, 0x7c,
+ 0x6a, 0xa3, 0x19, 0x63, 0x1a, 0x91, 0x16, 0x27, 0x43, 0xf1, 0x55, 0x48,
+ 0x67, 0x3c, 0x2f, 0xcd, 0xb8, 0xc1, 0x90, 0x92, 0x8d, 0x39, 0x4d, 0x65,
+ 0x53, 0x0d, 0xd2, 0xd1, 0xad, 0xb0, 0x10, 0x78, 0x5c, 0x35, 0xca, 0x22,
+ 0xe5, 0x98, 0x96, 0xa9, 0x11, 0x41, 0xc9, 0x01, 0x2e, 0x0e, 0xd7, 0x88,
+ 0xeb, 0x2c, 0x49, 0x90, 0x27, 0xd1, 0xb4, 0xab, 0x61, 0x68, 0x92, 0x0b,
+ 0xd9, 0xc1, 0x15, 0x50, 0xc0, 0x7f, 0x5f, 0xcd, 0x71, 0x04, 0x96, 0x95,
+ 0x6c, 0x0c, 0x36, 0xad, 0xe0, 0x87, 0x2a, 0x5c, 0x4c, 0x1b, 0xa1, 0xfb,
+ 0x3a, 0x75, 0x41, 0xa7, 0x36, 0x39, 0x82, 0x31, 0xec, 0xe5, 0x34, 0x6a,
+ 0x86, 0x38, 0xf5, 0xb6, 0xc5, 0x46, 0x64, 0x65, 0x97, 0xc4, 0x8e, 0x02,
+ 0xb9, 0xac, 0xd3, 0x56, 0x91, 0xdd, 0xf9, 0x6d, 0x39, 0xa5, 0xcb, 0xb6,
+ 0xf7, 0x3b, 0x9e, 0xa9, 0x6b, 0x96, 0x4a, 0x67, 0x8b, 0xc0, 0x1e, 0x41,
+ 0xce, 0x7e, 0xfa, 0xc2, 0x7b, 0xf8, 0x1d, 0x57, 0xcb, 0x29, 0xc2, 0x88,
+ 0xa0, 0x77, 0xf8, 0x70, 0x98, 0x1c, 0x4a, 0x64, 0x3f, 0x72, 0xd3, 0x97,
+ 0xd2, 0x02, 0xc2, 0xbd, 0xbd, 0x66, 0xbe, 0x93, 0x4c, 0x9a, 0xc8, 0x96,
+ 0xca, 0xfb, 0xb5, 0x9f, 0x87, 0x2f, 0x5e, 0x09, 0x06, 0xcb, 0x12, 0x15,
+ 0x7d, 0x96, 0x8f, 0xf1, 0xb7, 0x5a, 0x2b, 0x73, 0x04, 0xa8, 0xd6, 0xc3,
+ 0x88, 0xbd, 0x81, 0xfd, 0x1c, 0xd0, 0x54, 0x9c, 0x87, 0x42, 0x4d, 0xfa,
+ 0xfa, 0x3e, 0xa9, 0x4e, 0x9c, 0x27, 0x63, 0x9b, 0x8e, 0xa5, 0xd4, 0x43,
+ 0x4f, 0x7a, 0x56, 0x4d, 0xe1, 0xc6, 0x7b, 0xa0, 0x47, 0xab, 0xb4, 0x62,
+ 0xd5, 0xaf, 0xb8, 0x51, 0x73, 0x2f, 0x1b, 0x31, 0xb2, 0xc9, 0xb2, 0x69,
+ 0x63, 0x05, 0xfa, 0x0e, 0x51, 0xb9, 0xc3, 0x79, 0x58, 0x1b, 0x70, 0xdc,
+ 0x88, 0x80, 0xde, 0x3b, 0x53, 0x53, 0xef, 0x5e, 0x6f, 0x53, 0x9c, 0x59,
+ 0xec, 0x97, 0x94, 0x8f, 0x63, 0x79, 0xf9, 0x3a, 0xe6, 0x2a, 0x63, 0xd4,
+ 0x30, 0xa4, 0xe9, 0x42, 0x8c, 0x89, 0x76, 0x6f, 0x68, 0xa7, 0x9a, 0xc6,
+ 0xfa, 0x7e, 0xcb, 0x05, 0x99, 0xbd, 0xae, 0xad, 0x51, 0x4d, 0x6a, 0x35,
+ 0x77, 0xbb, 0x8f, 0xf4, 0x0c, 0xd5, 0xd7, 0x68, 0xa6, 0x36, 0xf2, 0x5b,
+ 0x5f, 0xd5, 0xf5, 0x0f, 0xc2, 0xc0, 0x11, 0x59, 0xe5, 0xf0, 0xd8, 0x48,
+ 0xfe, 0xc6, 0x47, 0x36, 0x73, 0x2e, 0x98, 0xc5, 0x4d, 0x35, 0x7e, 0x6e,
+ 0xfe, 0xf9, 0x96, 0xfe, 0x21, 0x46, 0x41, 0x2a, 0x12, 0x83, 0x20, 0x33,
+ 0x8e, 0x52, 0xc8, 0x13, 0xa8, 0xc8, 0x0f, 0xeb, 0x95, 0x23, 0x50, 0xd1,
+ 0x5b, 0xfc, 0x52, 0x65, 0x8f, 0xbc, 0x63, 0xe6, 0xf6, 0x0f, 0xb2, 0x7a,
+ 0x2e, 0x8d, 0x92, 0x60, 0x28, 0x71, 0xc2, 0x16, 0xb5, 0xb9, 0xe5, 0x26,
+ 0xa8, 0x84, 0x6b, 0x51, 0x52, 0x18, 0x57, 0x0d, 0x06, 0x50, 0x98, 0x16,
+ 0xf2, 0x15, 0xee, 0xcb, 0xd5, 0xfd, 0x21, 0x9f, 0x31, 0x89, 0xa6, 0x35,
+ 0x3e, 0x3a, 0xb7, 0x43, 0xca, 0x17, 0x13, 0x09, 0x0b, 0x9b, 0x81, 0xa4,
+ 0x9f, 0xd4, 0xee, 0xcd, 0x78, 0x99, 0x6b, 0xcd, 0x5a, 0x3c, 0x3a, 0xd4,
+ 0x04, 0x3c, 0xce, 0xbe, 0x5c, 0x31, 0x4e, 0x4e, 0x5f, 0x43, 0x51, 0x22,
+ 0xa4, 0x0a, 0xdd, 0x58, 0x24, 0x94, 0x79, 0x36, 0x27, 0xbc, 0x45, 0x9b,
+ 0xa6, 0xc6, 0x22, 0x18, 0xa5, 0x14, 0x53, 0x77, 0x2b, 0xdc, 0x49, 0x53,
+ 0x4a, 0x5b, 0x26, 0xe5, 0x9a, 0x43, 0xde, 0xff, 0x10, 0xd8, 0x96, 0xeb,
+ 0x87, 0x62, 0x72, 0x7d, 0xf8, 0x7e, 0xb4, 0xb6, 0xda, 0x51, 0xef, 0x4d,
+ 0x0e, 0x4f, 0x57, 0x65, 0x41, 0x39, 0x4e, 0x5e, 0xf4, 0x42, 0xc8, 0x02,
+ 0x46, 0x67, 0xef, 0x8f, 0xbe, 0x3e, 0xd5, 0x7f, 0x7e, 0xc9, 0xb2, 0x9e,
+ 0xa4, 0xd5, 0x55, 0x16, 0x41, 0x90, 0x0c, 0x46, 0xa4, 0x98, 0x36, 0x9e,
+ 0x38, 0x6b, 0x48, 0x63, 0x46, 0xaf, 0x33, 0x55, 0xf4, 0x85, 0x38, 0xf0,
+ 0xd1, 0x0a, 0x87, 0x2f, 0xf8, 0xff, 0xee, 0xd7, 0x5f, 0x85, 0xbc, 0xfe,
+ 0xf0, 0xfd, 0x8a, 0xee, 0xe8, 0x9b, 0x81, 0x5e, 0xed, 0x62, 0xd5, 0xf2,
+ 0x32, 0xc7, 0xc3, 0x53, 0x23, 0xb0, 0xc1, 0xf1, 0x01, 0x28, 0xa6, 0xf0,
+ 0x13, 0xc7, 0xc8, 0x3c, 0x21, 0xff, 0x3c, 0xfa, 0xa0, 0x00, 0x94, 0xc5,
+ 0xbb, 0x62, 0xe4, 0xb2, 0x11, 0x17, 0x95, 0x3a, 0xe7, 0x98, 0x9a, 0x33,
+ 0x31, 0xb2, 0x6e, 0x3e, 0xb6, 0x47, 0xf1, 0xe6, 0x88, 0x01, 0x44, 0xca,
+ 0x0e, 0xbd, 0x33, 0xe2, 0x01, 0xf1, 0xe5, 0x4f, 0xde, 0x3e, 0x7d, 0x21,
+ 0xd9, 0x18, 0x1b, 0x4e, 0x6f, 0xef, 0x86, 0x67, 0x62, 0x0e, 0x7c, 0xce,
+ 0x68, 0x6b, 0xf1, 0xe6, 0x5e, 0x7c, 0xfe, 0xe2, 0xf9, 0xe6, 0x66, 0xdf,
+ 0xc2, 0x49, 0x68, 0x0e, 0x13, 0xe5, 0xd2, 0xe6, 0x74, 0x86, 0x58, 0xc5,
+ 0x31, 0xa2, 0xe1, 0x35, 0x74, 0x66, 0x0b, 0x81, 0x11, 0x6f, 0x8e, 0x58,
+ 0xa0, 0xbe, 0x47, 0xd3, 0x23, 0x14, 0x04, 0xb0, 0x16, 0x8b, 0x45, 0x40,
+ 0xac, 0x2b, 0xe3, 0x07, 0x36, 0xd4, 0x32, 0xbf, 0xd2, 0x23, 0xce, 0x85,
+ 0xc0, 0x2d, 0x08, 0x08, 0xfb, 0x43, 0xe0, 0x39, 0x50, 0x26, 0x4d, 0xd8,
+ 0xc7, 0x6f, 0x8f, 0x4f, 0x8e, 0xec, 0xf1, 0xfb, 0x5f, 0x5b, 0x43, 0x1a,
+ 0x63, 0x35, 0x09, 0x73, 0xf9, 0x20, 0xd9, 0x78, 0xe9, 0xbd, 0xfd, 0x04,
+ 0xb5, 0x08, 0xbf, 0xed, 0xb3, 0x7e, 0x85, 0x8f, 0x9d, 0x69, 0xd6, 0x34,
+ 0x7c, 0xf4, 0xfe, 0xbb, 0xe3, 0xf3, 0xd3, 0xf7, 0xef, 0x8e, 0xde, 0xdb,
+ 0x48, 0x7c, 0xba, 0x86, 0x62, 0x9e, 0xab, 0x3a, 0x74, 0x0a, 0xe4, 0x94,
+ 0xcb, 0x41, 0x22, 0x12, 0x39, 0x69, 0x68, 0x16, 0x66, 0xbf, 0xe4, 0xaf,
+ 0xa1, 0xdf, 0x9c, 0xf7, 0x90, 0x6e, 0x1d, 0x49, 0xe2, 0x0b, 0x8a, 0xa0,
+ 0x9d, 0x52, 0xa6, 0xd3, 0x90, 0xd3, 0x12, 0xd8, 0x01, 0x91, 0xb3, 0xf3,
+ 0xec, 0x7e, 0x92, 0x09, 0xf8, 0x79, 0xed, 0x15, 0x5b, 0xd3, 0xbc, 0x1c,
+ 0x97, 0xbd, 0xd4, 0x1a, 0x84, 0xa3, 0x76, 0x2e, 0x46, 0xcd, 0xe5, 0xdb,
+ 0x62, 0x7e, 0x38, 0x20, 0x0d, 0x34, 0x9e, 0xc7, 0xe6, 0x5a, 0xfc, 0x19,
+ 0xf0, 0x6f, 0xb0, 0xd3, 0xde, 0x03, 0xab, 0x77, 0x10, 0x9c, 0xea, 0xc8,
+ 0xee, 0x2a, 0xa4, 0xde, 0x0c, 0x5a, 0x2e, 0x6e, 0x54, 0x59, 0xf8, 0x42,
+ 0xfc, 0xd9, 0x21, 0xe8, 0x5c, 0xed, 0x3b, 0x8d, 0x2c, 0x94, 0x87, 0xa6,
+ 0xf6, 0xc3, 0xd9, 0xb6, 0xe6, 0xc5, 0xbe, 0x8e, 0x3e, 0x9e, 0x9d, 0x9f,
+ 0xfe, 0xf0, 0xd7, 0xdf, 0xb8, 0x8b, 0x91, 0x9b, 0xc6, 0x8f, 0x74, 0x51,
+ 0x68, 0xe3, 0x3f, 0xff, 0xe6, 0xbd, 0xb5, 0x9b, 0xef, 0x7b, 0x20, 0xee,
+ 0x51, 0x84, 0x70, 0x38, 0x87, 0xb8, 0x18, 0x44, 0xe2, 0xbc, 0x45, 0x5e,
+ 0x70, 0xab, 0x65, 0x11, 0x70, 0x6d, 0xd7, 0x6d, 0xe2, 0x4c, 0x43, 0xdf,
+ 0xdb, 0x30, 0x41, 0x41, 0x36, 0x92, 0x31, 0xc2, 0xb2, 0x6c, 0x7d, 0x54,
+ 0x01, 0xc0, 0xa5, 0x69, 0xd7, 0x63, 0xff, 0xe4, 0xe4, 0x37, 0x5d, 0x04,
+ 0xe8, 0xe3, 0x6e, 0x2e, 0x03, 0x2b, 0xc6, 0xa9, 0x2f, 0x39, 0x90, 0x4e,
+ 0x5a, 0xaa, 0xfb, 0xfb, 0x53, 0x19, 0x0d, 0xbb, 0xa2, 0x06, 0x75, 0x66,
+ 0x04, 0x5e, 0x78, 0x02, 0xc8, 0x94, 0x4c, 0xb7, 0x1b, 0x6a, 0x98, 0x7f,
+ 0x11, 0x08, 0x4c, 0x14, 0x8c, 0x4d, 0xb2, 0xb4, 0xad, 0xd0, 0x21, 0xae,
+ 0x5b, 0x86, 0xa9, 0x41, 0x5e, 0x74, 0x69, 0xfd, 0xa8, 0x5c, 0x2d, 0x43,
+ 0xcb, 0x20, 0x45, 0x7c, 0xdf, 0x64, 0xc6, 0xa4, 0x48, 0x9a, 0x2a, 0xaf,
+ 0x6f, 0x90, 0x50, 0x4e, 0x87, 0x52, 0xca, 0x84, 0x36, 0xa8, 0x99, 0x8c,
+ 0x82, 0xf7, 0x34, 0x14, 0x33, 0x76, 0x1e, 0xb1, 0xf9, 0x79, 0x71, 0x7a,
+ 0x70, 0x7a, 0x62, 0x7e, 0x39, 0x7a, 0x7b, 0xfc, 0x83, 0x63, 0x68, 0x5c,
+ 0x3d, 0xa3, 0xa5, 0x35, 0xb8, 0x52, 0x1a, 0x1d, 0x87, 0x6a, 0x0c, 0xd0,
+ 0x58, 0xca, 0xf1, 0xae, 0x39, 0x4f, 0xba, 0x0d, 0xe9, 0x10, 0xbf, 0xa2,
+ 0x07, 0x84, 0xf0, 0x58, 0x04, 0x87, 0x1f, 0xf9, 0xd2, 0xda, 0x25, 0x26,
+ 0xc1, 0x16, 0x86, 0x72, 0x2b, 0x00, 0x40, 0x06, 0x57, 0x56, 0xb6, 0x0c,
+ 0x5f, 0xe3, 0x9b, 0x00, 0x3b, 0x5a, 0xbf, 0x07, 0xce, 0x6b, 0xf4, 0x3f,
+ 0x7f, 0x92, 0xaa, 0x0a, 0xda, 0x18, 0x0c, 0xd4, 0xdb, 0x21, 0x1e, 0xe6,
+ 0xbb, 0x5d, 0x3a, 0x21, 0x2f, 0xf0, 0x07, 0xda, 0x16, 0xdb, 0x73, 0x92,
+ 0x05, 0x90, 0x6c, 0x5c, 0xe4, 0x73, 0xc1, 0xc9, 0xec, 0x04, 0x7d, 0x1b,
+ 0xb0, 0x12, 0x45, 0x4e, 0x90, 0xa2, 0xd0, 0x84, 0x59, 0x79, 0x9b, 0x72,
+ 0xf5, 0xd2, 0x4b, 0x5b, 0x63, 0xa3, 0xd3, 0x46, 0xfa, 0xab, 0x1a, 0x49,
+ 0xdb, 0xad, 0xbc, 0xf8, 0x35, 0x8d, 0xbc, 0xe8, 0xb4, 0x71, 0xfd, 0xab,
+ 0x1a, 0xb1, 0x55, 0xa0, 0xcc, 0xb5, 0xf8, 0xc3, 0xf1, 0x45, 0x72, 0x70,
+ 0x7a, 0xe8, 0x68, 0xf4, 0x42, 0x32, 0x74, 0x2b, 0xc6, 0x4a, 0x19, 0x2f,
+ 0x0b, 0x92, 0x25, 0xe8, 0x40, 0x71, 0x29, 0x4c, 0x57, 0x59, 0x9d, 0x3c,
+ 0xfb, 0x6a, 0x35, 0xcd, 0x72, 0xfa, 0xbb, 0xe2, 0xac, 0x38, 0x1f, 0xdb,
+ 0x51, 0x8b, 0xb0, 0xa3, 0xa0, 0xa8, 0x9c, 0x44, 0x22, 0x6d, 0x42, 0x82,
+ 0x4f, 0x2b, 0xb1, 0x20, 0x27, 0xe3, 0x94, 0x1c, 0x7c, 0x05, 0x3b, 0x46,
+ 0x8d, 0x6c, 0xb2, 0xdf, 0xb4, 0x22, 0xf1, 0x4a, 0x9b, 0x65, 0x0b, 0x93,
+ 0x03, 0xe5, 0xa2, 0x22, 0x3e, 0x86, 0xd5, 0xdc, 0xbc, 0xd1, 0xa1, 0xf8,
+ 0xe9, 0xbd, 0x3b, 0xc2, 0x09, 0x8b, 0x16, 0xc5, 0x48, 0x19, 0x00, 0x48,
+ 0x5e, 0xa4, 0x93, 0xc0, 0xbb, 0x82, 0x03, 0x49, 0xb7, 0x62, 0x61, 0x75,
+ 0x56, 0xa9, 0x50, 0x1a, 0xb0, 0x28, 0xdb, 0x84, 0xed, 0x67, 0x97, 0xff,
+ 0x79, 0xcb, 0x05, 0xb3, 0xcd, 0xf9, 0x93, 0xbc, 0xd0, 0xfc, 0x1f, 0xde,
+ 0x1d, 0xfd, 0xcc, 0x85, 0x44, 0xcc, 0xd3, 0x19, 0x07, 0xaa, 0x48, 0x32,
+ 0xff, 0x43, 0xd1, 0xa4, 0xf7, 0x88, 0x2d, 0x22, 0x91, 0x08, 0x6b, 0x38,
+ 0xf1, 0xd8, 0xe0, 0x73, 0x61, 0xce, 0xaa, 0xc1, 0xc2, 0xca, 0xb7, 0x70,
+ 0xb9, 0x00, 0x5c, 0x97, 0xc6, 0x8f, 0x4e, 0x54, 0x24, 0x23, 0x5e, 0x40,
+ 0xb3, 0x2e, 0x54, 0x8f, 0x34, 0xee, 0xc8, 0xd4, 0xb7, 0xc9, 0xd0, 0xad,
+ 0x30, 0x38, 0xd4, 0x01, 0x7d, 0x4a, 0x9e, 0xec, 0x7c, 0x92, 0x23, 0xed,
+ 0x87, 0x0b, 0xb2, 0xa3, 0xcc, 0x1b, 0x16, 0x6d, 0x10, 0xb7, 0x20, 0xfa,
+ 0x28, 0x0d, 0x2a, 0x7a, 0x4c, 0x4b, 0x2c, 0x23, 0xc7, 0xfb, 0xa0, 0x16,
+ 0xa3, 0xf9, 0xe6, 0x81, 0x47, 0x4c, 0x07, 0xbe, 0x8c, 0x20, 0xec, 0xd8,
+ 0x8d, 0x11, 0xed, 0xd1, 0x29, 0x6a, 0x2f, 0xd4, 0x93, 0x2e, 0x9c, 0xdc,
+ 0x95, 0x1d, 0x13, 0x26, 0xce, 0xa6, 0x0d, 0x31, 0x90, 0xca, 0x3d, 0xc3,
+ 0xf5, 0xc7, 0x26, 0xc8, 0x08, 0x63, 0xb1, 0x33, 0x58, 0x8d, 0xba, 0x13,
+ 0xda, 0xfc, 0xb2, 0xd3, 0x8f, 0x76, 0x43, 0x4d, 0xf1, 0xbe, 0x71, 0x17,
+ 0xdd, 0x44, 0x02, 0x6a, 0x3e, 0x6c, 0xed, 0xb3, 0x2e, 0x89, 0x68, 0x50,
+ 0x3f, 0x01, 0x34, 0x96, 0x7e, 0x7a, 0xcf, 0xe7, 0xf2, 0xa4, 0xd1, 0xdd,
+ 0xef, 0x32, 0x32, 0x90, 0xc8, 0x95, 0x5a, 0x65, 0x8b, 0x99, 0x9d, 0x9d,
+ 0x86, 0xa4, 0x32, 0xd6, 0x0a, 0xdc, 0x63, 0x92, 0x6b, 0x3a, 0x91, 0xf1,
+ 0x86, 0x41, 0x4e, 0xbe, 0xc0, 0xf8, 0xca, 0x75, 0x92, 0xa4, 0x48, 0x00,
+ 0x21, 0x32, 0x29, 0x72, 0x4b, 0x92, 0x52, 0x59, 0x15, 0x1f, 0x51, 0x0e,
+ 0x33, 0x70, 0xd9, 0xf4, 0x6f, 0x79, 0x23, 0x88, 0xcd, 0xeb, 0x44, 0x96,
+ 0xd3, 0x2a, 0x2c, 0x2b, 0x46, 0x11, 0x71, 0xf5, 0x11, 0xd4, 0xdd, 0x2d,
+ 0x29, 0xbe, 0x28, 0xe0, 0x6d, 0xa6, 0xf5, 0x2e, 0xcc, 0x4b, 0x2d, 0x2f,
+ 0x1b, 0x0b, 0xa2, 0x44, 0xe6, 0xdf, 0xa9, 0x57, 0x0f, 0x08, 0x97, 0xb2,
+ 0x6b, 0x14, 0xe7, 0x40, 0x6f, 0x1e, 0x44, 0xb9, 0x85, 0x09, 0xd7, 0x0e,
+ 0x3f, 0xce, 0xad, 0xc3, 0xce, 0x4e, 0x67, 0xb1, 0xcf, 0xf6, 0x47, 0x23,
+ 0x5d, 0x6a, 0xd4, 0x88, 0xd0, 0xf5, 0xe4, 0x15, 0x94, 0xf4, 0x0b, 0x82,
+ 0x70, 0x53, 0x18, 0xcd, 0x88, 0xba, 0x23, 0x8d, 0x74, 0xf2, 0xb6, 0x76,
+ 0x9e, 0xb9, 0x35, 0xb7, 0x9d, 0x7d, 0xc7, 0xad, 0xf5, 0x3f, 0xb1, 0xb3,
+ 0x68, 0x5f, 0xdf, 0x45, 0xfa, 0x7a, 0xde, 0x99, 0xd7, 0xee, 0xee, 0x67,
+ 0x82, 0x95, 0x31, 0x94, 0xe2, 0xd9, 0xae, 0x33, 0xe9, 0x8d, 0x99, 0x85,
+ 0x79, 0x70, 0x00, 0x93, 0x5c, 0xa4, 0x2f, 0xa1, 0x0a, 0x1a, 0x8c, 0xd7,
+ 0xd5, 0x0b, 0x37, 0x2d, 0xa3, 0x34, 0x51, 0x7b, 0x64, 0xa2, 0xe7, 0x63,
+ 0x12, 0x9c, 0x1e, 0x5b, 0x37, 0xed, 0x98, 0x46, 0x66, 0xc4, 0xb0, 0x15,
+ 0x99, 0x70, 0x3a, 0x0c, 0xaf, 0x9f, 0xcf, 0x6c, 0x3f, 0x76, 0xe4, 0xa4,
+ 0xd4, 0x30, 0x5c, 0xd7, 0xd0, 0xe7, 0x08, 0x42, 0x23, 0x5e, 0x90, 0xbf,
+ 0x84, 0x01, 0x45, 0xc2, 0x49, 0xf9, 0x6d, 0xd7, 0x0b, 0x1f, 0xbf, 0x33,
+ 0xa2, 0x62, 0xa9, 0x46, 0x32, 0x4c, 0x4e, 0xa1, 0x84, 0xb5, 0x50, 0x4b,
+ 0xa1, 0xca, 0xd2, 0x71, 0xb7, 0x38, 0xf3, 0xfe, 0x69, 0xdf, 0x79, 0xe5,
+ 0xad, 0x89, 0x0e, 0x4b, 0xfd, 0x68, 0x5b, 0x7a, 0x7c, 0x2c, 0x0b, 0x51,
+ 0x1f, 0x79, 0x86, 0xa0, 0x05, 0x4a, 0xe9, 0x01, 0xf0, 0x6a, 0x97, 0xc5,
+ 0x9a, 0x33, 0xb5, 0x69, 0x03, 0x04, 0x2e, 0xc1, 0x49, 0xbc, 0x3b, 0xc8,
+ 0x51, 0xf2, 0xdf, 0x97, 0xc4, 0x90, 0x70, 0xeb, 0x12, 0x74, 0x13, 0xff,
+ 0xa9, 0xef, 0x31, 0x06, 0x08, 0x15, 0x2d, 0xc2, 0xad, 0xec, 0x92, 0x5e,
+ 0xe4, 0x64, 0xd8, 0xf5, 0x77, 0x19, 0x88, 0x28, 0x10, 0xc0, 0x6c, 0x4d,
+ 0x40, 0x00, 0x86, 0x92, 0xd8, 0x66, 0xe1, 0x30, 0x40, 0x50, 0xee, 0x22,
+ 0xe1, 0x44, 0xfa, 0xd0, 0x2f, 0x64, 0x3b, 0x57, 0xae, 0x6f, 0xcb, 0x8d,
+ 0xbb, 0x00, 0x30, 0x74, 0xe9, 0xa4, 0x0b, 0xb1, 0x10, 0x3c, 0xdf, 0xde,
+ 0x0e, 0x9b, 0x4b, 0xc7, 0xe5, 0xad, 0x46, 0x51, 0x0a, 0xb6, 0x09, 0x5e,
+ 0x61, 0xa5, 0x19, 0xd2, 0x45, 0x4d, 0x42, 0xea, 0xe0, 0x92, 0x6c, 0x02,
+ 0xb4, 0x62, 0xea, 0xa3, 0xf0, 0xd6, 0x8d, 0x4f, 0xe5, 0xf7, 0xc0, 0x5a,
+ 0x91, 0x35, 0x6b, 0x9f, 0x45, 0x86, 0x61, 0xd1, 0x12, 0x02, 0xa9, 0xa6,
+ 0xa5, 0xc3, 0x96, 0x26, 0x5e, 0xfb, 0x60, 0x64, 0x82, 0x9b, 0xeb, 0x75,
+ 0xf3, 0x22, 0x42, 0x11, 0xc9, 0xe8, 0xe2, 0xf4, 0x3c, 0x11, 0x22, 0x0b,
+ 0xd9, 0x2e, 0xd2, 0x05, 0xe9, 0x09, 0x1b, 0x49, 0xda, 0x8f, 0x38, 0xc6,
+ 0xad, 0xe1, 0x99, 0x73, 0x18, 0x09, 0xaf, 0xcb, 0xf5, 0xfa, 0xd2, 0x05,
+ 0xb1, 0xc9, 0xdc, 0xbe, 0x4b, 0x2b, 0x20, 0x32, 0x69, 0x35, 0x13, 0x2d,
+ 0x8d, 0xec, 0xbd, 0xc4, 0x07, 0xed, 0x74, 0x09, 0x62, 0x67, 0x2b, 0x2b,
+ 0xd1, 0x91, 0xd8, 0x5b, 0x29, 0x70, 0x53, 0x6c, 0x62, 0xd6, 0x59, 0xd5,
+ 0xa5, 0x45, 0x3e, 0x44, 0xa7, 0xae, 0x5e, 0x0d, 0xfb, 0xb5, 0x87, 0x9d,
+ 0x70, 0x3e, 0x7c, 0x0e, 0xc4, 0x26, 0x09, 0x12, 0x10, 0x1a, 0xc2, 0x9d,
+ 0x10, 0x16, 0xfd, 0x9c, 0x18, 0xc9, 0x88, 0xa3, 0x29, 0x4b, 0x0d, 0xc2,
+ 0x50, 0x69, 0xd1, 0x49, 0x59, 0xdb, 0x6e, 0x9d, 0xcf, 0x4e, 0xcf, 0x2f,
+ 0x12, 0x1d, 0x1c, 0x5f, 0x9c, 0xf8, 0xa8, 0x73, 0x84, 0x08, 0xda, 0x0b,
+ 0x1a, 0x9c, 0x03, 0xdd, 0x08, 0xb4, 0x52, 0x91, 0x08, 0x1b, 0x6d, 0x42,
+ 0xdb, 0x20, 0xc0, 0xcf, 0xea, 0x41, 0xa3, 0x9c, 0x00, 0xcf, 0x6b, 0x79,
+ 0x8e, 0xc4, 0x6b, 0x11, 0x83, 0x8e, 0x3b, 0x20, 0x9d, 0x4c, 0xf3, 0x6c,
+ 0x27, 0x42, 0x1d, 0xa4, 0x40, 0x9f, 0x1f, 0x51, 0xf5, 0xec, 0x8b, 0x6b,
+ 0xfe, 0x2d, 0x18, 0x39, 0x5b, 0x0f, 0xe5, 0xc3, 0x68, 0xd8, 0x04, 0xa8,
+ 0x83, 0x32, 0x50, 0x28, 0x2c, 0x9a, 0xda, 0xb7, 0xc6, 0x61, 0x6f, 0xcd,
+ 0x9e, 0x79, 0xd9, 0xc6, 0xe0, 0x9c, 0x42, 0x2b, 0x38, 0xe4, 0xf8, 0xa0,
+ 0x27, 0x9d, 0xf4, 0xcc, 0x9d, 0xcb, 0x87, 0xa2, 0xac, 0x6e, 0xbc, 0x16,
+ 0x9e, 0x7b, 0xdc, 0x82, 0xb8, 0xbb, 0x34, 0x70, 0xac, 0xfe, 0x5e, 0xfa,
+ 0xd0, 0x06, 0x96, 0x5e, 0x65, 0x85, 0x12, 0x06, 0x3f, 0xe7, 0xda, 0x79,
+ 0x61, 0xbd, 0x24, 0x2a, 0x1f, 0x79, 0x43, 0xa1, 0x8f, 0x35, 0xc9, 0x13,
+ 0x41, 0x65, 0x1d, 0xb2, 0x7b, 0xf6, 0xd2, 0xae, 0x22, 0x29, 0x13, 0x36,
+ 0x6e, 0x81, 0xa7, 0xef, 0x5d, 0x46, 0x14, 0xf8, 0x91, 0x17, 0xcb, 0x4c,
+ 0x2c, 0x66, 0x69, 0x35, 0xcb, 0x91, 0x1e, 0x34, 0x8e, 0x59, 0x77, 0x6d,
+ 0xc2, 0xb2, 0xeb, 0x47, 0x6e, 0xa2, 0xe3, 0x93, 0x23, 0xb7, 0x5b, 0x8c,
+ 0xaa, 0x85, 0x93, 0xec, 0x84, 0x3c, 0x73, 0x70, 0x0b, 0x7b, 0x5d, 0x0c,
+ 0x93, 0x33, 0xaa, 0x1e, 0x06, 0xa7, 0x4d, 0xfd, 0x6f, 0xae, 0x35, 0x3e,
+ 0x2c, 0x30, 0xc6, 0x98, 0xfb, 0x13, 0xd2, 0x69, 0x5e, 0x98, 0xcd, 0xc5,
+ 0x27, 0xf4, 0xab, 0x57, 0xf8, 0x29, 0x98, 0xf2, 0x2b, 0xf7, 0x72, 0x6d,
+ 0x26, 0x62, 0xf4, 0xb4, 0xee, 0x23, 0xcf, 0x85, 0xb6, 0x8c, 0x12, 0xc7,
+ 0x05, 0xe8, 0xcb, 0x86, 0xf9, 0x33, 0x9d, 0xe9, 0x8a, 0x0b, 0x34, 0x4c,
+ 0xb9, 0x85, 0x4b, 0x7d, 0x46, 0xe5, 0x58, 0x7e, 0xce, 0x35, 0xc5, 0x97,
+ 0xc2, 0x3e, 0xaf, 0x13, 0x02, 0xba, 0xcd, 0xb9, 0x19, 0xa7, 0x93, 0x1b,
+ 0xd3, 0x56, 0x41, 0x1c, 0x77, 0xa6, 0xe6, 0xf2, 0x56, 0x6a, 0x0e, 0x16,
+ 0x56, 0xf0, 0xed, 0x42, 0x6c, 0xd5, 0x4e, 0x29, 0xb4, 0xe7, 0x4c, 0x8d,
+ 0x96, 0x74, 0xec, 0x3d, 0xd6, 0x1a, 0x1d, 0x75, 0xec, 0x12, 0x5b, 0x68,
+ 0xbb, 0xc9, 0x34, 0x64, 0xae, 0x79, 0x5f, 0xba, 0x7b, 0xfe, 0xc2, 0x35,
+ 0x75, 0x49, 0x08, 0x57, 0xb6, 0x2d, 0xc7, 0x83, 0x1c, 0x9c, 0x7e, 0x6e,
+ 0x1f, 0x13, 0x45, 0x81, 0xef, 0xb2, 0x71, 0x04, 0xa6, 0xd7, 0x5f, 0x13,
+ 0x26, 0x86, 0x8b, 0x92, 0x34, 0x9f, 0xe2, 0xc1, 0x01, 0x5a, 0x0c, 0x39,
+ 0x2a, 0x8e, 0x6d, 0x10, 0x5c, 0xad, 0xc0, 0x42, 0x5d, 0xb0, 0xb6, 0x29,
+ 0x0a, 0xfa, 0x3c, 0xbd, 0x0f, 0xae, 0xfa, 0xf9, 0x72, 0x2e, 0x79, 0xfc,
+ 0x5e, 0x4f, 0x9f, 0x8b, 0x36, 0x7b, 0x53, 0x18, 0x92, 0xb4, 0x70, 0x7f,
+ 0x2e, 0x6a, 0xbd, 0x54, 0x65, 0xc9, 0x7a, 0xd6, 0x0c, 0xf1, 0x20, 0x74,
+ 0xd6, 0x66, 0x76, 0x84, 0xd8, 0x99, 0x14, 0x55, 0x8e, 0x0b, 0x59, 0x04,
+ 0x45, 0x55, 0x2c, 0x4b, 0x0f, 0x86, 0x91, 0x16, 0x5c, 0x9e, 0xe3, 0xaf,
+ 0xd4, 0xa5, 0x17, 0xfa, 0xa6, 0xab, 0xec, 0x6f, 0xa8, 0x89, 0x38, 0xe4,
+ 0x4b, 0x87, 0x81, 0x90, 0x78, 0x96, 0xe4, 0x9a, 0x77, 0x2c, 0xef, 0xf9,
+ 0x2b, 0x31, 0x55, 0x88, 0x2a, 0xac, 0x75, 0xfa, 0xba, 0x96, 0xe6, 0x17,
+ 0x3b, 0x2e, 0x64, 0x3f, 0xcb, 0xaa, 0xf5, 0x9a, 0xb9, 0x83, 0x97, 0x3c,
+ 0x6f, 0x18, 0xdc, 0x68, 0xf4, 0x4d, 0xf2, 0xee, 0xf0, 0x05, 0xa5, 0x6f,
+ 0x5e, 0x65, 0x15, 0xd5, 0xc0, 0x74, 0xba, 0xd8, 0xe9, 0xb7, 0x5e, 0x63,
+ 0xbb, 0xce, 0x88, 0x24, 0x57, 0x6d, 0x2e, 0xa7, 0x17, 0xa8, 0xcc, 0xc5,
+ 0x03, 0x61, 0xc0, 0x5d, 0xf5, 0xc5, 0x7d, 0xc2, 0x66, 0x10, 0x5a, 0x48,
+ 0x85, 0x47, 0x64, 0xd1, 0xa5, 0x1b, 0xff, 0xdf, 0x66, 0x62, 0x2f, 0x9e,
+ 0x39, 0x26, 0x56, 0x3d, 0x2c, 0x08, 0xa3, 0xbd, 0xb8, 0x22, 0x89, 0x3a,
+ 0x72, 0xa2, 0x5e, 0x30, 0xe3, 0x3c, 0xe0, 0x73, 0x4f, 0xe2, 0x6c, 0xf8,
+ 0x1a, 0xa0, 0xe8, 0xe0, 0xed, 0xf0, 0xde, 0x7b, 0xe1, 0xab, 0x93, 0x46,
+ 0x20, 0xc7, 0xbd, 0x68, 0xd6, 0x0f, 0xf5, 0x5f, 0x49, 0x56, 0xf1, 0x9e,
+ 0x7d, 0x69, 0x9f, 0x25, 0xe3, 0x41, 0x5e, 0x78, 0x75, 0x2c, 0x56, 0xbc,
+ 0x21, 0x42, 0x30, 0x8b, 0x06, 0x2e, 0x9c, 0x80, 0x25, 0x1f, 0x6f, 0xed,
+ 0xbd, 0x57, 0x5e, 0xb5, 0xb5, 0x65, 0x14, 0x59, 0x73, 0xb5, 0xc3, 0x69,
+ 0x52, 0xf9, 0xe2, 0xda, 0x3f, 0x9c, 0x2f, 0xf9, 0xa6, 0x3e, 0x23, 0x2c,
+ 0x84, 0xd6, 0x7e, 0x2a, 0x13, 0xcc, 0x7c, 0x17, 0x9c, 0x9e, 0x75, 0xa6,
+ 0xfd, 0x83, 0x7d, 0x7d, 0x23, 0x28, 0x6b, 0x4d, 0xd4, 0xee, 0x75, 0xb2,
+ 0x23, 0x67, 0xc6, 0x4c, 0xb9, 0xbc, 0x2a, 0xf2, 0x7f, 0x10, 0xa1, 0xe9,
+ 0x0d, 0xad, 0x35, 0x48, 0xbc, 0xc7, 0x77, 0x85, 0x61, 0xdc, 0xa6, 0xb3,
+ 0x5c, 0x98, 0x22, 0xd9, 0xd1, 0xdd, 0x03, 0xcf, 0x84, 0x6a, 0xef, 0x73,
+ 0x3a, 0xa2, 0xd0, 0x02, 0x50, 0x8d, 0x8a, 0x3c, 0x38, 0x59, 0x0b, 0x5a,
+ 0xe3, 0xe5, 0x73, 0x91, 0xbd, 0x54, 0x48, 0xa6, 0x7b, 0x89, 0x16, 0x62,
+ 0x06, 0xe4, 0xec, 0x2e, 0x9b, 0x7e, 0x29, 0x57, 0x9f, 0x6c, 0xa5, 0xad,
+ 0x43, 0x52, 0x69, 0x09, 0x1d, 0xfa, 0xf5, 0x2e, 0x2f, 0x24, 0x23, 0x27,
+ 0x78, 0xfd, 0xe5, 0x0a, 0x13, 0x54, 0xcd, 0xf7, 0xe6, 0x11, 0x68, 0xc9,
+ 0x7b, 0xfe, 0x33, 0x7b, 0x12, 0x3c, 0xd8, 0x71, 0x4d, 0x31, 0x41, 0x20,
+ 0x99, 0xd6, 0x7e, 0xd0, 0x83, 0x04, 0xb5, 0x7f, 0xe1, 0x4a, 0x1c, 0x47,
+ 0xd2, 0xdf, 0x2e, 0x6d, 0xf7, 0xb3, 0xf2, 0x2a, 0xc9, 0xbd, 0x63, 0xfc,
+ 0x92, 0x49, 0xea, 0x2d, 0x6a, 0xfa, 0xe9, 0x39, 0x20, 0x6e, 0xe2, 0x97,
+ 0xde, 0x72, 0x4f, 0xbf, 0x12, 0xda, 0xd0, 0xfb, 0x52, 0xc5, 0xd4, 0x95,
+ 0x6f, 0x7c, 0xb6, 0xed, 0x0b, 0xad, 0x53, 0xb2, 0xd4, 0x33, 0xa8, 0xe1,
+ 0xca, 0x17, 0x98, 0x32, 0x8e, 0xcd, 0x35, 0x72, 0x65, 0x88, 0x1a, 0xcf,
+ 0x38, 0x34, 0x4f, 0xf7, 0xd8, 0x6e, 0x8b, 0xe9, 0x5e, 0xf8, 0x22, 0x54,
+ 0x72, 0x7c, 0xe8, 0x3d, 0xf8, 0xcc, 0x4d, 0x30, 0x9d, 0x91, 0x34, 0xf0,
+ 0xc0, 0x86, 0x88, 0x5a, 0xaa, 0x9f, 0x79, 0x8f, 0x3e, 0x97, 0xc4, 0x0a,
+ 0xce, 0x65, 0xc2, 0xfa, 0x07, 0xcf, 0x30, 0x39, 0x1c, 0x20, 0x0f, 0xaa,
+ 0x01, 0x06, 0x40, 0xa1, 0xfe, 0x82, 0xee, 0xde, 0x7f, 0xf6, 0xf2, 0x91,
+ 0x67, 0xe5, 0xd2, 0xac, 0xed, 0x55, 0xef, 0xbd, 0xf7, 0x59, 0x78, 0xcc,
+ 0x55, 0x2d, 0x50, 0xa8, 0x12, 0x39, 0x69, 0xc9, 0x06, 0x41, 0xdc, 0xfd,
+ 0x9b, 0x5a, 0x7e, 0x2a, 0xca, 0x07, 0xab, 0xff, 0xcd, 0x1f, 0xef, 0xe7,
+ 0x3e, 0xde, 0x09, 0x9b, 0x7d, 0x6c, 0x05, 0x5e, 0xbf, 0x2e, 0x9f, 0x8b,
+ 0x70, 0xc6, 0xea, 0x78, 0x2d, 0xf0, 0x9e, 0x1b, 0x39, 0x62, 0x59, 0x38,
+ 0xce, 0xc1, 0x8a, 0xa0, 0xc0, 0x44, 0x6a, 0xb4, 0xb1, 0x8c, 0xee, 0x1b,
+ 0xb3, 0xa9, 0xa0, 0x0e, 0xcf, 0x78, 0xb6, 0xdd, 0x39, 0x06, 0xf5, 0xf5,
+ 0x92, 0x35, 0x6f, 0x3b, 0x23, 0x07, 0x4f, 0xe4, 0xbd, 0xb6, 0xeb, 0xb8,
+ 0x97, 0x5c, 0xfb, 0x0c, 0x3a, 0x73, 0x40, 0x09, 0x6c, 0xac, 0x9e, 0x27,
+ 0x20, 0x45, 0xc4, 0xb7, 0x57, 0x5c, 0xf8, 0x5b, 0xc1, 0x47, 0x37, 0xd2,
+ 0x78, 0x2a, 0xbe, 0xa0, 0x87, 0x78, 0xdd, 0x88, 0x68, 0x43, 0x21, 0xda,
+ 0x66, 0x97, 0xae, 0xb3, 0xc9, 0x8d, 0x1e, 0x19, 0xdb, 0x46, 0xe4, 0xad,
+ 0xe7, 0x76, 0x69, 0x89, 0xfa, 0xce, 0xce, 0x8f, 0xba, 0x8a, 0x80, 0x7b,
+ 0x94, 0xa9, 0xe6, 0xfc, 0x62, 0x74, 0xb6, 0x47, 0xe3, 0x65, 0x1f, 0x8c,
+ 0x39, 0x10, 0x07, 0xa3, 0xec, 0xef, 0x92, 0x77, 0x5a, 0xbb, 0xa7, 0x5f,
+ 0xae, 0x78, 0x7a, 0x24, 0x91, 0x45, 0xc7, 0x53, 0xe2, 0xbe, 0x66, 0x1f,
+ 0xfc, 0x97, 0x3e, 0x93, 0x0c, 0x7e, 0xb5, 0xee, 0xb2, 0xf1, 0x88, 0x46,
+ 0x66, 0x93, 0x3c, 0xdc, 0xc3, 0x9f, 0x3b, 0x9b, 0xcd, 0xf5, 0xb2, 0xb8,
+ 0xb1, 0xf2, 0xa2, 0x04, 0x6a, 0xe9, 0x06, 0xbb, 0x17, 0x5e, 0xe9, 0xd1,
+ 0xf0, 0x50, 0xa4, 0xac, 0xfb, 0xbb, 0x2f, 0x96, 0x0a, 0x8d, 0xa2, 0x64,
+ 0xff, 0x91, 0xe1, 0xaf, 0x4b, 0x6f, 0x0d, 0x7e, 0xf8, 0x81, 0x59, 0x74,
+ 0xa9, 0x91, 0x09, 0xe2, 0x19, 0xb0, 0xc5, 0x67, 0x0d, 0x4b, 0xe3, 0x32,
+ 0x0a, 0x74, 0x3a, 0x60, 0x4f, 0xaf, 0xb2, 0x59, 0x46, 0x38, 0xd2, 0xac,
+ 0x66, 0x80, 0x2e, 0x63, 0x59, 0x6a, 0x14, 0xb4, 0x0a, 0xa7, 0x08, 0x25,
+ 0x83, 0xc2, 0x1c, 0x57, 0x50, 0xa4, 0xa3, 0x98, 0x9b, 0xcc, 0x86, 0xed,
+ 0x7f, 0xb8, 0xf8, 0xe6, 0xf4, 0x7c, 0x94, 0x6c, 0x11, 0xe0, 0xdf, 0xc5,
+ 0xf9, 0xf1, 0x57, 0x1f, 0x8c, 0xf6, 0x6e, 0xbd, 0x2a, 0x87, 0xa9, 0xd1,
+ 0xea, 0x67, 0x14, 0x17, 0x9a, 0x15, 0x66, 0x1f, 0xae, 0xb4, 0xc2, 0x21,
+ 0x22, 0x65, 0xe8, 0xaa, 0x2b, 0x2b, 0x2e, 0xae, 0x83, 0x34, 0xa2, 0xeb,
+ 0x52, 0x16, 0x93, 0xe3, 0xbb, 0x0a, 0x0e, 0xfe, 0x2f, 0x9d, 0x6a, 0x9a,
+ 0x77, 0xf0, 0x0a, 0xd5, 0x39, 0x9a, 0x5c, 0x7c, 0xb3, 0xff, 0xfe, 0xdb,
+ 0x91, 0x22, 0x9e, 0x7f, 0xff, 0xfd, 0xf7, 0xbe, 0xd3, 0x7e, 0x6f, 0x6b,
+ 0x0b, 0x12, 0xe2, 0x75, 0x7a, 0x7f, 0x3f, 0xac, 0xb3, 0xb5, 0xb5, 0xb7,
+ 0xce, 0xd5, 0xe6, 0xca, 0x53, 0xd6, 0x4b, 0x23, 0x18, 0x98, 0xaf, 0xb7,
+ 0x16, 0xcb, 0x31, 0x95, 0xc3, 0xdc, 0x5a, 0x36, 0xf9, 0xcc, 0xdc, 0x27,
+ 0x59, 0x8d, 0xb7, 0xb7, 0xd6, 0xd6, 0x46, 0x47, 0x47, 0xc9, 0xfe, 0xc9,
+ 0xe8, 0xd4, 0x7b, 0x77, 0x63, 0x67, 0xd3, 0x08, 0x4e, 0x57, 0x59, 0xb3,
+ 0x41, 0xd8, 0x99, 0x27, 0xfb, 0x17, 0xa4, 0xb1, 0x7e, 0x77, 0x74, 0x3e,
+ 0x3a, 0x3e, 0x7d, 0x4f, 0xbb, 0x43, 0x71, 0x75, 0xe9, 0xec, 0x8e, 0xc2,
+ 0x2a, 0x2f, 0x73, 0x00, 0x99, 0xdc, 0x69, 0xad, 0x49, 0x42, 0x64, 0x36,
+ 0x92, 0x1d, 0x0b, 0xe2, 0x1c, 0x05, 0xa1, 0x35, 0xee, 0x39, 0x7a, 0xb4,
+ 0x21, 0xbd, 0x51, 0x78, 0x1a, 0xad, 0x80, 0x35, 0x5b, 0x71, 0x00, 0x4b,
+ 0x36, 0xe6, 0x68, 0xdd, 0x3e, 0xa7, 0xff, 0xc3, 0x4d, 0xe1, 0x85, 0xf7,
+ 0x45, 0x27, 0x3e, 0x3a, 0xa6, 0x6a, 0x13, 0xc9, 0x87, 0xd1, 0xfe, 0xd7,
+ 0x47, 0xf4, 0xe8, 0xd7, 0x59, 0xe3, 0xb6, 0x83, 0x6b, 0x62, 0x52, 0x27,
+ 0xef, 0xb3, 0xa6, 0x9e, 0xa4, 0x0b, 0xca, 0x72, 0x36, 0xdd, 0x0c, 0xf8,
+ 0x1a, 0xf1, 0xda, 0x66, 0x51, 0xde, 0x15, 0x0e, 0x2d, 0xe4, 0x79, 0x54,
+ 0xf5, 0xf4, 0xdb, 0x3d, 0x3f, 0xda, 0x3f, 0x7c, 0x77, 0xa4, 0x21, 0xdf,
+ 0x7c, 0xed, 0x9a, 0x46, 0xaf, 0x4b, 0x2a, 0xe4, 0x6e, 0x0d, 0xd9, 0x74,
+ 0xb5, 0xd3, 0xe2, 0x9b, 0x6f, 0xa8, 0xac, 0x66, 0xbc, 0x3b, 0xb7, 0x51,
+ 0x78, 0x76, 0x78, 0x99, 0x6f, 0x71, 0xeb, 0xda, 0x5f, 0x6a, 0x97, 0x44,
+ 0x81, 0x9e, 0x45, 0xdc, 0x65, 0x9b, 0x04, 0x6c, 0x19, 0x9f, 0x6f, 0x6f,
+ 0x6f, 0x3f, 0x32, 0x0f, 0x68, 0x03, 0x72, 0x69, 0x9a, 0xa9, 0xec, 0xd1,
+ 0xe3, 0x5b, 0xae, 0x7d, 0x37, 0xe2, 0x99, 0xa4, 0x94, 0x53, 0xe5, 0xab,
+ 0x82, 0x6d, 0x28, 0x79, 0x93, 0xc5, 0x87, 0x3c, 0x29, 0x4b, 0xbb, 0x03,
+ 0xad, 0xc5, 0x99, 0x12, 0x34, 0x77, 0xde, 0x68, 0x38, 0x23, 0xde, 0xe0,
+ 0x81, 0x1b, 0x05, 0x06, 0x31, 0x65, 0xd5, 0x43, 0xb7, 0x49, 0xfa, 0xc6,
+ 0xb4, 0x49, 0xff, 0x0c, 0xcb, 0xea, 0x6a, 0x6b, 0xbe, 0x07, 0x89, 0xc4,
+ 0x3c, 0xf4, 0x96, 0x90, 0x26, 0x12, 0x23, 0xd9, 0xda, 0x28, 0xe7, 0x9a,
+ 0x16, 0x96, 0xd2, 0x31, 0x3e, 0x61, 0x5c, 0xbf, 0x60, 0x15, 0x38, 0xa0,
+ 0xe9, 0x52, 0x67, 0xae, 0xe5, 0xef, 0x22, 0x9d, 0xd4, 0xb4, 0x61, 0x64,
+ 0x31, 0x1c, 0x1a, 0x06, 0x62, 0x7a, 0xa1, 0x98, 0x33, 0x90, 0x88, 0xf9,
+ 0xb5, 0x32, 0x24, 0x33, 0x6c, 0xee, 0xc1, 0x36, 0xa5, 0x12, 0x23, 0xe3,
+ 0xee, 0x91, 0x17, 0x7b, 0x41, 0xb9, 0x80, 0x15, 0x6a, 0x4d, 0xa0, 0x07,
+ 0xca, 0x2f, 0x94, 0x28, 0x78, 0x1b, 0xc0, 0x43, 0x0d, 0x77, 0xfb, 0x1c,
+ 0x0c, 0x40, 0x3f, 0xb5, 0xa5, 0x96, 0x4f, 0xe8, 0xdc, 0x9b, 0x14, 0xaf,
+ 0x7e, 0x21, 0xb7, 0xac, 0x47, 0x3b, 0x23, 0x33, 0x8a, 0xa0, 0xaf, 0xa5,
+ 0x2b, 0x26, 0x59, 0x73, 0x77, 0xf5, 0xb5, 0x39, 0xbf, 0x43, 0xaf, 0x5c,
+ 0x0b, 0x61, 0x75, 0x6d, 0x21, 0x39, 0xe9, 0x93, 0x7b, 0x3a, 0x38, 0x93,
+ 0xdf, 0x28, 0x21, 0x32, 0xbf, 0xa5, 0x25, 0xb8, 0xc9, 0x30, 0x7b, 0x5f,
+ 0x31, 0x78, 0x64, 0x30, 0x7b, 0x66, 0x15, 0xe8, 0x8d, 0xff, 0xb5, 0x35,
+ 0xac, 0xeb, 0xeb, 0xad, 0x7c, 0xfa, 0x71, 0x5a, 0xa7, 0x14, 0xd3, 0xb4,
+ 0x1c, 0x07, 0x1f, 0x0f, 0xcd, 0x87, 0xc9, 0x4f, 0x2d, 0xae, 0x5f, 0x4f,
+ 0xe2, 0x33, 0xf9, 0x5f, 0x5b, 0x14, 0x3f, 0x8a, 0xe2, 0x53, 0xde, 0xc2,
+ 0x45, 0x78, 0x87, 0x99, 0x15, 0x07, 0x10, 0x9b, 0xc3, 0x18, 0xa7, 0x8c,
+ 0x9e, 0xd0, 0xda, 0x8f, 0xbb, 0xdb, 0xdb, 0x3b, 0x7b, 0x3b, 0x9f, 0xbf,
+ 0xda, 0xde, 0xdb, 0xd9, 0xd9, 0xd9, 0xdd, 0xdb, 0xd9, 0xdb, 0xdb, 0xdd,
+ 0xfe, 0x79, 0xab, 0xb7, 0xb6, 0x76, 0x78, 0xfa, 0xfd, 0xfb, 0x93, 0xd3,
+ 0xfd, 0xc3, 0xe4, 0xe2, 0x34, 0xd9, 0x87, 0xcd, 0x29, 0x72, 0xc8, 0x81,
+ 0x52, 0x4f, 0x29, 0x68, 0x9c, 0xfe, 0xee, 0x55, 0x52, 0x17, 0x03, 0x89,
+ 0x0d, 0xbc, 0xc1, 0xb2, 0x74, 0x57, 0xac, 0x84, 0x4e, 0x41, 0x2d, 0x0d,
+ 0xaf, 0x9b, 0xf9, 0xd3, 0xec, 0xec, 0x53, 0x7a, 0xee, 0xb3, 0x23, 0xd8,
+ 0xa9, 0x8d, 0x18, 0x8e, 0x92, 0xad, 0x24, 0x79, 0x88, 0x33, 0x45, 0x5c,
+ 0xa8, 0x36, 0x25, 0x61, 0x83, 0xe3, 0x86, 0x5c, 0x01, 0x70, 0x2e, 0x2c,
+ 0x5f, 0x87, 0x58, 0x19, 0x28, 0xf4, 0x2c, 0x3e, 0x7a, 0x5c, 0xf0, 0x24,
+ 0x10, 0x6d, 0x06, 0x13, 0x3c, 0x5d, 0x39, 0x25, 0x73, 0x11, 0x65, 0xf7,
+ 0x98, 0x75, 0x9b, 0x71, 0x70, 0xa4, 0xac, 0x9b, 0x1d, 0x50, 0xd8, 0x55,
+ 0x11, 0xce, 0x2b, 0x1d, 0x32, 0x62, 0x8b, 0x22, 0xdd, 0x51, 0x3f, 0xca,
+ 0x4f, 0x5c, 0x17, 0xf4, 0x8d, 0x7f, 0x09, 0x6d, 0x59, 0xdb, 0x22, 0x0f,
+ 0xe0, 0xc3, 0xe8, 0xf8, 0xfd, 0xd7, 0xf0, 0x1e, 0x7e, 0x7f, 0x7a, 0x7e,
+ 0x38, 0x32, 0xcd, 0xd2, 0xed, 0xbc, 0x06, 0xf3, 0x12, 0x1d, 0x63, 0x19,
+ 0x15, 0x1f, 0x0a, 0xea, 0xfa, 0xcf, 0x50, 0xd8, 0xa6, 0x7d, 0x9b, 0x36,
+ 0x8e, 0x61, 0x7a, 0xc2, 0x36, 0xe5, 0x82, 0xc7, 0x59, 0x1e, 0x08, 0x81,
+ 0x5f, 0xff, 0x72, 0x9e, 0x52, 0xad, 0x90, 0x6c, 0xc8, 0x51, 0xbb, 0x08,
+ 0xf3, 0xda, 0xa2, 0xbc, 0x84, 0x2d, 0x12, 0xfa, 0xb7, 0x9a, 0x12, 0xcc,
+ 0x03, 0xad, 0x94, 0x95, 0x8d, 0x2d, 0x6a, 0xad, 0x08, 0x9d, 0xba, 0xcb,
+ 0x59, 0x7a, 0x85, 0x0e, 0xc3, 0x03, 0xe9, 0x75, 0x26, 0xdd, 0x7f, 0x6a,
+ 0x97, 0xc4, 0xf3, 0xd0, 0xde, 0x31, 0x08, 0x00, 0xf0, 0x50, 0x48, 0x70,
+ 0x17, 0xaf, 0x07, 0x4b, 0x4c, 0xe4, 0x22, 0x46, 0x44, 0x09, 0x15, 0x94,
+ 0xed, 0x56, 0x83, 0x41, 0x85, 0x4f, 0xc6, 0xd5, 0x30, 0xf2, 0xff, 0xc0,
+ 0xc3, 0xe7, 0x60, 0xc5, 0x88, 0x5a, 0xf2, 0xec, 0x0f, 0xb5, 0x0b, 0x89,
+ 0x43, 0xcd, 0x0f, 0xa8, 0xdb, 0xbc, 0xe4, 0x34, 0x18, 0x20, 0xcb, 0xd4,
+ 0x1a, 0x6b, 0x25, 0x22, 0x5c, 0x8f, 0xaa, 0x7a, 0x51, 0xa4, 0x44, 0x4f,
+ 0xc1, 0x22, 0x5c, 0xf1, 0x00, 0xe7, 0xde, 0xac, 0x1b, 0x33, 0x94, 0x94,
+ 0xea, 0xc3, 0x71, 0xc5, 0x78, 0xc1, 0x0e, 0x36, 0xa2, 0x3c, 0x67, 0x78,
+ 0xf6, 0x34, 0xde, 0x82, 0x5b, 0xc9, 0x6b, 0x46, 0x60, 0xb6, 0x89, 0xf0,
+ 0xc4, 0x79, 0x19, 0xd7, 0x66, 0x4d, 0xdc, 0xd9, 0x8e, 0xc9, 0x3b, 0xb3,
+ 0x19, 0x31, 0x68, 0x23, 0x81, 0x1a, 0xee, 0xc9, 0x94, 0x23, 0xe9, 0x88,
+ 0x5e, 0x25, 0xc7, 0xd6, 0xb2, 0xf9, 0x95, 0xe7, 0x03, 0x3e, 0xdb, 0x4e,
+ 0x41, 0x5e, 0x43, 0x16, 0x92, 0x85, 0xa1, 0xf0, 0x96, 0x87, 0x83, 0xba,
+ 0xdc, 0xab, 0xb4, 0x17, 0x79, 0x53, 0x67, 0xb3, 0x4b, 0x01, 0x0d, 0x69,
+ 0x60, 0x14, 0xa4, 0xa9, 0xb8, 0x06, 0xd6, 0x34, 0x6d, 0x84, 0x7c, 0x72,
+ 0x85, 0x85, 0x32, 0x28, 0x85, 0x67, 0x5c, 0x81, 0x95, 0x0a, 0x0a, 0x49,
+ 0x9b, 0x51, 0xb0, 0xdb, 0x6d, 0xa8, 0x45, 0x50, 0xd6, 0x12, 0x5b, 0xbf,
+ 0xa5, 0x33, 0x05, 0x5b, 0xd3, 0x02, 0x35, 0x05, 0x40, 0x1d, 0xde, 0x83,
+ 0xcb, 0xb1, 0x59, 0x6d, 0xfb, 0x1c, 0xad, 0x1d, 0x02, 0xcf, 0xa8, 0x39,
+ 0x78, 0x00, 0xf1, 0xbc, 0x8d, 0xb9, 0x5c, 0x06, 0xd0, 0x28, 0xb9, 0x00,
+ 0xcc, 0x98, 0x83, 0x86, 0x34, 0xa7, 0x65, 0x6d, 0x57, 0x74, 0x91, 0x1b,
+ 0x1d, 0x87, 0x2f, 0xb8, 0x35, 0x44, 0x24, 0x86, 0xc7, 0x50, 0x38, 0xd2,
+ 0xea, 0x73, 0xf8, 0xf4, 0x11, 0x0c, 0x87, 0xa4, 0x4a, 0xc0, 0xec, 0x81,
+ 0x4f, 0x49, 0x5e, 0x3c, 0x7e, 0x18, 0x65, 0x10, 0x9f, 0xd4, 0x31, 0xe6,
+ 0x2a, 0x80, 0x12, 0x30, 0x75, 0xbb, 0x60, 0x30, 0x76, 0xaf, 0x23, 0xdf,
+ 0xa0, 0x13, 0x36, 0x4f, 0xa3, 0x6b, 0xc5, 0xae, 0xe2, 0x20, 0x70, 0x82,
+ 0xd8, 0x5e, 0xf2, 0x55, 0x5a, 0xe7, 0x93, 0x7e, 0x72, 0x98, 0x5f, 0x01,
+ 0xe1, 0x80, 0x53, 0x4e, 0xcc, 0x1b, 0xae, 0xbe, 0xd6, 0x06, 0x67, 0x4c,
+ 0x6c, 0x0e, 0x93, 0xef, 0xb5, 0x24, 0x9e, 0xb9, 0x8e, 0x81, 0x0e, 0x49,
+ 0x26, 0x5a, 0x6a, 0xad, 0x85, 0x36, 0x22, 0xb6, 0x75, 0xbf, 0x18, 0x38,
+ 0x3a, 0x71, 0xb5, 0x33, 0xb0, 0xab, 0x69, 0x7d, 0x63, 0xbd, 0x13, 0xd8,
+ 0x2b, 0x39, 0xa2, 0x40, 0x23, 0x63, 0x01, 0x89, 0xd5, 0xbd, 0x72, 0x69,
+ 0x5d, 0xfe, 0xf8, 0xdb, 0x92, 0xbb, 0x16, 0xb2, 0x84, 0x4d, 0xac, 0x96,
+ 0x58, 0x31, 0x75, 0xe8, 0xd3, 0xb5, 0x44, 0xcd, 0xd9, 0xa3, 0x3b, 0x18,
+ 0x98, 0x05, 0xa3, 0xa5, 0x11, 0xc6, 0x72, 0x7a, 0x71, 0xf4, 0x87, 0x64,
+ 0xbf, 0xeb, 0xd0, 0x24, 0x8e, 0xdd, 0xc2, 0x16, 0xe9, 0x3b, 0x02, 0xc3,
+ 0xd8, 0x39, 0x3c, 0xac, 0x90, 0x6a, 0x87, 0xb4, 0xfd, 0x6b, 0x92, 0x1e,
+ 0xe9, 0x2c, 0x77, 0x75, 0x29, 0xb1, 0xae, 0xcd, 0x83, 0xc2, 0x68, 0xd3,
+ 0x6b, 0x30, 0xf3, 0x7a, 0x95, 0x34, 0x38, 0x02, 0x35, 0x4f, 0x19, 0x6d,
+ 0x82, 0x40, 0x84, 0xcc, 0xa6, 0x14, 0x7c, 0x26, 0x11, 0x16, 0xcb, 0x06,
+ 0x7e, 0x46, 0xe9, 0xc9, 0x1b, 0xc8, 0xcf, 0xf0, 0xd8, 0x4b, 0x2d, 0x2c,
+ 0xaf, 0x56, 0x64, 0xea, 0xe3, 0x39, 0x7d, 0xa4, 0xa3, 0xf6, 0x51, 0x19,
+ 0xae, 0x5c, 0x0d, 0x3c, 0x16, 0x29, 0x33, 0xde, 0x26, 0x59, 0x3d, 0x76,
+ 0xcc, 0xe5, 0xcf, 0x34, 0x38, 0x0c, 0x1b, 0x31, 0x01, 0x5a, 0x0a, 0xd7,
+ 0xa8, 0x12, 0xfb, 0xaf, 0x9e, 0x6e, 0x9f, 0x61, 0x03, 0xff, 0x08, 0xa8,
+ 0x2b, 0xa8, 0xfb, 0x2a, 0xd5, 0x5a, 0x38, 0x10, 0xd7, 0xb4, 0xda, 0x0e,
+ 0x9d, 0x46, 0x4e, 0x05, 0x56, 0x95, 0x46, 0xc1, 0x60, 0x63, 0x7e, 0xe8,
+ 0x72, 0xcd, 0xc5, 0x17, 0x13, 0xad, 0x2f, 0xda, 0x21, 0xe8, 0xe1, 0x1a,
+ 0xdd, 0x44, 0xd6, 0x86, 0x85, 0xda, 0xba, 0xb6, 0x0e, 0x8a, 0x17, 0x37,
+ 0xf8, 0xd6, 0x02, 0x4f, 0x49, 0xb3, 0x54, 0x8c, 0x6d, 0x92, 0x79, 0x59,
+ 0x13, 0x45, 0xb9, 0xe6, 0xdd, 0x08, 0x4c, 0x3f, 0x65, 0x2d, 0xf5, 0x75,
+ 0x73, 0x46, 0x25, 0xe2, 0x5a, 0x4e, 0xe3, 0x8c, 0x01, 0xd6, 0x0d, 0x95,
+ 0xf0, 0x2e, 0x02, 0xb3, 0x8f, 0x4e, 0x20, 0x53, 0xe6, 0x1c, 0xc4, 0xbd,
+ 0xe6, 0xa8, 0x9b, 0xd8, 0xf6, 0xaa, 0x79, 0x4a, 0x16, 0xad, 0xb5, 0x61,
+ 0xb2, 0x48, 0x41, 0x32, 0x75, 0x21, 0x55, 0x81, 0x60, 0x11, 0x90, 0x51,
+ 0xd3, 0xee, 0x40, 0xe2, 0x2b, 0xac, 0xfc, 0xa1, 0x9b, 0xde, 0x42, 0xd7,
+ 0x22, 0x9e, 0x32, 0x4d, 0xe6, 0x0f, 0x92, 0x2e, 0x20, 0x77, 0x26, 0x65,
+ 0x82, 0x43, 0xd5, 0xfc, 0xfc, 0xf3, 0x40, 0x46, 0xba, 0xb7, 0x4f, 0xef,
+ 0x99, 0xaf, 0x3d, 0x95, 0x76, 0x46, 0xce, 0x7f, 0x52, 0x21, 0x21, 0x9f,
+ 0x59, 0xbd, 0x36, 0xa2, 0x31, 0x78, 0x48, 0x41, 0xdc, 0xa3, 0xb5, 0x95,
+ 0x07, 0x54, 0xd6, 0x77, 0x39, 0x0d, 0x6b, 0xac, 0x33, 0xf1, 0x40, 0xd3,
+ 0x9a, 0x83, 0x48, 0x56, 0x28, 0x11, 0xca, 0x26, 0xbb, 0xa3, 0xf5, 0xa4,
+ 0x49, 0x23, 0xd1, 0x0e, 0x49, 0x00, 0x25, 0xe1, 0x78, 0x54, 0x4a, 0xc3,
+ 0xb4, 0xc8, 0x32, 0x18, 0x4b, 0x1d, 0x1d, 0x3a, 0xb2, 0x35, 0xf0, 0x1c,
+ 0x8f, 0xf8, 0xb0, 0x7a, 0x38, 0x1f, 0x7e, 0xcd, 0x70, 0xf6, 0x93, 0x47,
+ 0xc3, 0xe6, 0xa5, 0xc2, 0x21, 0x71, 0xfc, 0x5a, 0x1c, 0x5e, 0xd3, 0x12,
+ 0x54, 0xad, 0x1a, 0x28, 0xaf, 0xd1, 0x84, 0x1c, 0x5e, 0xe3, 0x76, 0x79,
+ 0xa3, 0x50, 0xdb, 0x2c, 0x4a, 0x7e, 0x1a, 0xc2, 0x3e, 0xb5, 0xdf, 0xd7,
+ 0xa1, 0x7c, 0xea, 0x70, 0x19, 0x4f, 0x2e, 0xb1, 0x79, 0x31, 0x1d, 0xf8,
+ 0x42, 0x49, 0x45, 0xd9, 0x19, 0x6e, 0xfb, 0xa8, 0x28, 0x36, 0x41, 0xa5,
+ 0x02, 0xf0, 0x62, 0x03, 0x00, 0x1a, 0x57, 0xd8, 0x97, 0x66, 0x82, 0xc4,
+ 0xfb, 0xce, 0x6b, 0xf2, 0xd9, 0x0e, 0x83, 0xd1, 0x9a, 0x93, 0x24, 0x15,
+ 0x3a, 0x08, 0x65, 0x23, 0x9b, 0x2f, 0x10, 0xc8, 0xaf, 0x1c, 0xd0, 0x17,
+ 0x02, 0x70, 0x8e, 0x9e, 0xbb, 0x23, 0xf5, 0xc2, 0x6e, 0xb7, 0x8c, 0x91,
+ 0xe3, 0xbc, 0xa5, 0x52, 0x31, 0x87, 0x5a, 0x43, 0x28, 0xcb, 0x32, 0x6e,
+ 0xa9, 0x59, 0x99, 0x70, 0x74, 0xd0, 0xce, 0xe1, 0x23, 0x7a, 0xc6, 0x65,
+ 0x9b, 0x5c, 0x2e, 0x2b, 0x30, 0x5e, 0x81, 0x1e, 0x13, 0xd4, 0x0a, 0x6a,
+ 0x95, 0x62, 0x26, 0x23, 0x9c, 0x06, 0xe9, 0xa4, 0x19, 0x6a, 0x0f, 0xd3,
+ 0xb9, 0x66, 0x93, 0x27, 0xf2, 0xeb, 0xa5, 0xc8, 0x94, 0xf3, 0x87, 0x58,
+ 0x43, 0x9a, 0x69, 0x77, 0x96, 0x9b, 0x01, 0xad, 0x03, 0xbc, 0x41, 0x0b,
+ 0xab, 0x0a, 0x2f, 0xb4, 0xa8, 0x6c, 0x8a, 0x43, 0xdc, 0xae, 0x5c, 0x1a,
+ 0xd6, 0xac, 0xe9, 0x32, 0x5d, 0xbe, 0x06, 0xfa, 0xc9, 0xe0, 0x7f, 0xc8,
+ 0xca, 0x90, 0xd8, 0x4a, 0xf1, 0x3c, 0x00, 0xaa, 0x5f, 0x78, 0x38, 0x7e,
+ 0x92, 0x76, 0x05, 0x86, 0x4f, 0xc1, 0x7a, 0x3a, 0x0f, 0x9b, 0xd2, 0xa8,
+ 0x59, 0x1b, 0xe0, 0x7f, 0x6f, 0x7d, 0xc4, 0xc6, 0x56, 0x31, 0x59, 0x61,
+ 0x15, 0xdc, 0xdc, 0x9a, 0x45, 0xbe, 0xe7, 0x08, 0xae, 0x60, 0xc0, 0xf6,
+ 0x22, 0xfb, 0x8a, 0x2a, 0x83, 0x1d, 0x94, 0xa9, 0xbf, 0xac, 0xaa, 0xe3,
+ 0xac, 0xe9, 0x48, 0x99, 0xf8, 0x95, 0x4f, 0xf4, 0x38, 0x73, 0x70, 0x60,
+ 0x5e, 0x18, 0x7c, 0x10, 0xc3, 0xc3, 0x97, 0xdc, 0xc3, 0x10, 0xb6, 0x54,
+ 0xee, 0xe1, 0x0c, 0xe5, 0x50, 0xf5, 0x81, 0x3d, 0x79, 0x89, 0xd2, 0x0d,
+ 0x7b, 0x62, 0x76, 0x68, 0xaf, 0x0a, 0x3f, 0xaf, 0xe9, 0x88, 0x54, 0x4b,
+ 0x13, 0x53, 0x18, 0xb0, 0x91, 0x9d, 0x0e, 0x19, 0xff, 0xca, 0xef, 0x8a,
+ 0x52, 0xf5, 0x40, 0x4d, 0x0c, 0x39, 0x0e, 0x5a, 0x0c, 0x0e, 0xbb, 0x3b,
+ 0x5b, 0x3c, 0x98, 0x2d, 0x6e, 0x80, 0xe5, 0x3a, 0x21, 0x49, 0xe7, 0x98,
+ 0x57, 0x90, 0x12, 0xff, 0xe6, 0xa2, 0xd0, 0x6d, 0x0a, 0xa8, 0x98, 0x73,
+ 0x31, 0x71, 0xae, 0xe7, 0x46, 0x57, 0x93, 0xb9, 0x6b, 0x01, 0x7a, 0x22,
+ 0x69, 0x65, 0x84, 0x17, 0x6e, 0x37, 0xa8, 0x6f, 0x45, 0x3e, 0x43, 0x4a,
+ 0x83, 0x5b, 0x2f, 0x9e, 0x80, 0xb2, 0xf3, 0x80, 0xaa, 0x67, 0x2e, 0xf4,
+ 0x3b, 0x9b, 0xd3, 0x04, 0x64, 0x8f, 0x42, 0xdc, 0xb0, 0xe7, 0xfb, 0xef,
+ 0xbf, 0x3e, 0x82, 0x24, 0x00, 0xde, 0x4e, 0x07, 0x34, 0x27, 0x6a, 0x9f,
+ 0x2e, 0x27, 0xd0, 0x1e, 0xcc, 0x8a, 0x21, 0x1e, 0x09, 0xf8, 0xa3, 0x5a,
+ 0x0f, 0x0c, 0x25, 0xce, 0x40, 0xbc, 0xd8, 0x6e, 0x89, 0x32, 0x5a, 0x4b,
+ 0xd4, 0x4c, 0x06, 0x09, 0x82, 0x14, 0x29, 0x4a, 0x42, 0x28, 0x91, 0x6a,
+ 0x3d, 0x5e, 0xa4, 0x02, 0x64, 0x91, 0xfa, 0x40, 0x07, 0x62, 0x7f, 0x18,
+ 0xb6, 0xcf, 0xe2, 0x9a, 0xa6, 0x1c, 0x58, 0x5d, 0xb7, 0x82, 0xae, 0x3b,
+ 0xf4, 0x2d, 0x3f, 0x9c, 0xde, 0xbf, 0xb3, 0xbd, 0xed, 0x2a, 0x4c, 0xa4,
+ 0xb6, 0xc1, 0x80, 0x5b, 0x56, 0xc9, 0xf6, 0xe0, 0xd5, 0xab, 0x55, 0x8c,
+ 0xd0, 0x36, 0x0a, 0xd4, 0x84, 0x17, 0x9f, 0xdc, 0xe6, 0x80, 0x1e, 0x5d,
+ 0xd5, 0x66, 0x44, 0xa3, 0x41, 0x2d, 0x6a, 0x89, 0xf0, 0xaa, 0xad, 0xd4,
+ 0x22, 0x96, 0x0f, 0xb6, 0xc0, 0xc3, 0x23, 0x52, 0x58, 0xb5, 0x86, 0x96,
+ 0x72, 0xcd, 0x21, 0xc4, 0x22, 0x69, 0x5f, 0x8d, 0x24, 0x0b, 0x0a, 0xf2,
+ 0xca, 0xad, 0x5f, 0xed, 0x93, 0x16, 0xc6, 0x53, 0x6c, 0x57, 0x2c, 0xd1,
+ 0x65, 0x38, 0x1b, 0x15, 0x09, 0x3e, 0x9c, 0x91, 0x5d, 0xec, 0xf8, 0xfd,
+ 0xd7, 0x6c, 0x26, 0x30, 0x3a, 0x2f, 0x0c, 0xa4, 0x5b, 0x1d, 0x0d, 0xf8,
+ 0x03, 0x17, 0x8a, 0xa0, 0x00, 0x3f, 0x38, 0xd4, 0xb9, 0xda, 0x63, 0x5e,
+ 0x30, 0x2b, 0xf0, 0x2a, 0x73, 0x47, 0x0d, 0x74, 0x83, 0x8b, 0x64, 0xe0,
+ 0x09, 0x27, 0x52, 0x27, 0x82, 0x24, 0x93, 0xf9, 0x83, 0x6a, 0x46, 0xd2,
+ 0x03, 0x5a, 0x57, 0x73, 0xbb, 0x6d, 0x96, 0x6d, 0x61, 0xac, 0xce, 0x82,
+ 0x82, 0x02, 0xd9, 0x24, 0xd2, 0x25, 0x77, 0x83, 0xf3, 0xdd, 0x91, 0x44,
+ 0x3e, 0x6d, 0x28, 0x2d, 0x13, 0x60, 0xbb, 0xb2, 0x18, 0x49, 0x56, 0x7d,
+ 0xb5, 0x89, 0x74, 0xcd, 0x73, 0x5c, 0x78, 0xd8, 0xe7, 0xea, 0xb4, 0xdb,
+ 0xa8, 0x42, 0x58, 0x96, 0xff, 0xfb, 0xe3, 0x7c, 0x64, 0x84, 0x74, 0x50,
+ 0xe9, 0xa6, 0x2a, 0xa6, 0xce, 0x06, 0x20, 0x23, 0x8e, 0x5a, 0xb7, 0x2f,
+ 0xf8, 0x7d, 0xee, 0x3a, 0x8d, 0x77, 0xc7, 0xef, 0xeb, 0xd2, 0x44, 0x0e,
+ 0x00, 0x89, 0xb4, 0x52, 0x47, 0xc4, 0x26, 0x03, 0xaa, 0x2e, 0x43, 0x52,
+ 0x38, 0x38, 0x47, 0xde, 0x16, 0x4b, 0xd6, 0x12, 0xc9, 0x39, 0x46, 0x95,
+ 0x11, 0xa2, 0x21, 0xc0, 0x4e, 0xe3, 0xf2, 0xba, 0xc9, 0xa5, 0xce, 0x16,
+ 0x30, 0x56, 0x51, 0x39, 0xf7, 0xd8, 0x22, 0xe1, 0x38, 0xb8, 0xdb, 0x6a,
+ 0x59, 0x08, 0xef, 0x23, 0x7d, 0xcb, 0x0c, 0x3e, 0xad, 0xaf, 0x11, 0xca,
+ 0x65, 0x4d, 0x34, 0xa1, 0x78, 0x85, 0xee, 0x05, 0xbb, 0xd5, 0xc8, 0x53,
+ 0x2c, 0x4c, 0x41, 0xb8, 0x6e, 0x2d, 0x45, 0x7b, 0x05, 0x3c, 0x8b, 0xc6,
+ 0xa7, 0x9e, 0x02, 0x96, 0xa9, 0x23, 0x0e, 0x1c, 0x1c, 0x04, 0x8f, 0xb9,
+ 0x44, 0xc9, 0xaf, 0x6d, 0x11, 0xf2, 0xe5, 0x73, 0x18, 0x60, 0xa0, 0x2d,
+ 0x01, 0x92, 0xa8, 0xb3, 0x84, 0x50, 0xa2, 0x81, 0x08, 0xc9, 0x10, 0x45,
+ 0xca, 0x72, 0x45, 0x1a, 0x80, 0x19, 0xcc, 0x15, 0x2a, 0x91, 0x72, 0xef,
+ 0x74, 0xdf, 0xb3, 0x4a, 0x0a, 0x9f, 0x22, 0x27, 0x1a, 0xa1, 0x4f, 0xcc,
+ 0x90, 0x07, 0xc8, 0x49, 0xe1, 0x1c, 0xb7, 0x3b, 0xba, 0x20, 0xd5, 0x1e,
+ 0xd7, 0x91, 0xea, 0x88, 0xdf, 0x1d, 0x9d, 0x7f, 0x75, 0x3a, 0x3a, 0x32,
+ 0xdc, 0xe2, 0xf0, 0xe8, 0xab, 0x0f, 0xc4, 0x49, 0x68, 0xc7, 0xd8, 0x4c,
+ 0x0a, 0x40, 0x4f, 0x4e, 0xd9, 0x05, 0x50, 0x11, 0x12, 0x0e, 0x88, 0x74,
+ 0x58, 0x36, 0xe9, 0xdb, 0xf4, 0x47, 0x11, 0xbb, 0x18, 0x1b, 0x73, 0x96,
+ 0xb1, 0x5d, 0x2d, 0x47, 0xb0, 0xb6, 0x43, 0xef, 0xa5, 0x98, 0xa8, 0x82,
+ 0x20, 0xc7, 0x1b, 0x05, 0x8f, 0xd1, 0xf2, 0x71, 0xf5, 0x9e, 0x43, 0x67,
+ 0xbc, 0x65, 0x2b, 0xaa, 0x1c, 0x08, 0x57, 0xe6, 0x59, 0xcb, 0x39, 0xcb,
+ 0xd5, 0x04, 0xd9, 0x56, 0x60, 0xf6, 0x66, 0x25, 0xdf, 0x64, 0x04, 0x55,
+ 0x83, 0x73, 0x8d, 0xbb, 0x35, 0x6f, 0x70, 0xad, 0xb2, 0x90, 0x2f, 0xc5,
+ 0x95, 0x6b, 0x26, 0x38, 0xc3, 0x72, 0x38, 0x43, 0x77, 0x96, 0x79, 0x35,
+ 0xc7, 0xeb, 0x8c, 0x21, 0x9e, 0xf8, 0x26, 0x15, 0xc7, 0x23, 0xc7, 0x44,
+ 0x4a, 0x25, 0x84, 0x0d, 0x51, 0x4c, 0xef, 0x30, 0x4f, 0x29, 0xcd, 0xc7,
+ 0x35, 0x88, 0xb5, 0x40, 0x17, 0x56, 0xde, 0x0b, 0x5d, 0x10, 0xd2, 0xb9,
+ 0x5d, 0xcd, 0x0e, 0x2e, 0x78, 0xa6, 0x64, 0x7b, 0xe0, 0xcb, 0xd9, 0x47,
+ 0x52, 0xf5, 0xd1, 0x77, 0xc8, 0xe1, 0x6f, 0x85, 0x06, 0x3e, 0x4f, 0x14,
+ 0x79, 0xed, 0xa9, 0x75, 0xab, 0x8b, 0x16, 0xab, 0x84, 0x29, 0xce, 0x10,
+ 0x97, 0x74, 0xc1, 0x0c, 0x4f, 0xc2, 0x95, 0x68, 0x4b, 0x61, 0xbe, 0x66,
+ 0xe2, 0x0b, 0xcf, 0x20, 0xb7, 0xce, 0xf5, 0x8a, 0x9b, 0xfb, 0xc6, 0x37,
+ 0xf2, 0xaf, 0xad, 0xad, 0x1d, 0x1e, 0x5d, 0xec, 0x1f, 0x9f, 0x1c, 0x1d,
+ 0x26, 0xc7, 0xef, 0xdf, 0x9e, 0x9e, 0xbf, 0xdb, 0xbf, 0x10, 0xb7, 0xf7,
+ 0xa1, 0xb5, 0x92, 0xd9, 0xdc, 0x5b, 0x6b, 0x84, 0x74, 0x16, 0x34, 0x90,
+ 0xb0, 0xd9, 0xc5, 0x2b, 0x41, 0xcc, 0xe6, 0x65, 0xc8, 0x5a, 0x6b, 0xb0,
+ 0x96, 0x88, 0xbb, 0xdc, 0xa1, 0xe1, 0xd0, 0x5d, 0xbd, 0x65, 0x9d, 0x9c,
+ 0x43, 0x5d, 0x4e, 0x0b, 0xae, 0x48, 0xf5, 0xd3, 0x1e, 0x6d, 0xca, 0x16,
+ 0x89, 0xe7, 0x7b, 0x8a, 0xb6, 0x93, 0x93, 0xa4, 0x41, 0x93, 0x83, 0xe3,
+ 0xad, 0x36, 0x58, 0x28, 0x8c, 0x1f, 0x0a, 0x8e, 0x94, 0x02, 0x36, 0xc2,
+ 0x07, 0x27, 0x30, 0x14, 0x48, 0x36, 0x3f, 0xbf, 0x4d, 0x9b, 0x76, 0xaf,
+ 0x70, 0x37, 0x1c, 0x64, 0xc1, 0xd8, 0x34, 0xde, 0xfe, 0x0a, 0x44, 0x95,
+ 0xa1, 0x66, 0xa6, 0x03, 0xe0, 0x1e, 0xd6, 0x54, 0xa8, 0x5c, 0xcf, 0x3a,
+ 0xb0, 0x18, 0x2d, 0x13, 0x55, 0x4f, 0x92, 0x94, 0xfb, 0xf2, 0x9b, 0xda,
+ 0xb0, 0x8e, 0x51, 0x23, 0xc5, 0x0c, 0x8e, 0xa5, 0x10, 0x1c, 0xad, 0x05,
+ 0x41, 0x2d, 0xd3, 0xbf, 0x85, 0x83, 0x42, 0x93, 0x30, 0x3b, 0xa7, 0x85,
+ 0xe7, 0x5b, 0xb6, 0x36, 0xb7, 0x9c, 0x36, 0x77, 0x6e, 0x15, 0xdb, 0x62,
+ 0x70, 0x68, 0x1e, 0x9a, 0x2e, 0xe7, 0x0b, 0xa9, 0x24, 0xaa, 0x52, 0x2e,
+ 0xec, 0x6b, 0xba, 0x85, 0x2c, 0x48, 0x41, 0x20, 0x80, 0x31, 0xe6, 0xad,
+ 0xac, 0x01, 0xcf, 0x03, 0xf4, 0xdd, 0xa8, 0xdb, 0x8a, 0xf4, 0x56, 0xe7,
+ 0x69, 0xea, 0x96, 0x11, 0x6f, 0x4b, 0x13, 0x58, 0x90, 0x91, 0x7d, 0xb6,
+ 0x5b, 0x77, 0x3c, 0x75, 0x91, 0x20, 0x58, 0xff, 0x0d, 0x2d, 0x75, 0x40,
+ 0x24, 0x2b, 0x0d, 0x8a, 0x9a, 0x14, 0x3a, 0xca, 0x5a, 0x93, 0xf2, 0x5f,
+ 0x6c, 0xc7, 0x4e, 0xf8, 0x9c, 0x5e, 0xbb, 0x76, 0x10, 0x98, 0xdd, 0x11,
+ 0x08, 0x17, 0x37, 0xfc, 0xc4, 0x56, 0x9b, 0x27, 0xc4, 0x76, 0x46, 0xb8,
+ 0x5b, 0x93, 0x04, 0x5f, 0x1f, 0x08, 0x57, 0xc9, 0x77, 0x89, 0xb2, 0xa5,
+ 0xe5, 0x0d, 0xe9, 0xd7, 0xc8, 0x80, 0x1b, 0x3f, 0xf8, 0xb9, 0x4a, 0x1c,
+ 0xe3, 0x23, 0xc5, 0x42, 0xc0, 0xf4, 0x8a, 0x35, 0x85, 0xe7, 0xd4, 0x97,
+ 0x34, 0xd0, 0x0b, 0xdc, 0x9f, 0x91, 0xab, 0xc1, 0xe4, 0x49, 0xd1, 0xcd,
+ 0xd2, 0x1a, 0x4a, 0x0e, 0x32, 0x16, 0xf8, 0xce, 0xb0, 0xa6, 0x51, 0x87,
+ 0xcd, 0x8e, 0xcb, 0xc7, 0x43, 0xc4, 0x60, 0xc4, 0xbf, 0x94, 0x40, 0x07,
+ 0xf4, 0x50, 0x70, 0x74, 0xb2, 0x6d, 0x05, 0x77, 0x1d, 0x29, 0xb1, 0xd5,
+ 0x0c, 0x21, 0xa6, 0x12, 0x73, 0x77, 0x56, 0xd6, 0x7c, 0xde, 0x20, 0x75,
+ 0xf7, 0xb8, 0x84, 0x36, 0x91, 0x41, 0x6f, 0x71, 0x6d, 0xfa, 0xe8, 0x25,
+ 0x57, 0xa4, 0xb7, 0x8c, 0xcd, 0xd0, 0x03, 0x06, 0x3a, 0xe5, 0xc7, 0xdf,
+ 0x9c, 0xa7, 0x97, 0x69, 0x36, 0xfb, 0xd3, 0xee, 0xf6, 0x28, 0xbd, 0x5a,
+ 0xce, 0xd2, 0x7f, 0xc1, 0x8b, 0x6f, 0x9e, 0x3d, 0xdb, 0xdd, 0xfe, 0xec,
+ 0xf3, 0xed, 0x5e, 0xc7, 0x7d, 0xed, 0x45, 0xbe, 0x20, 0x94, 0x81, 0x6e,
+ 0x32, 0xf0, 0x5d, 0xf4, 0x33, 0x9c, 0x5c, 0xe5, 0x50, 0xb4, 0x48, 0x78,
+ 0x91, 0x35, 0x48, 0x59, 0xc3, 0x03, 0x9b, 0x64, 0x18, 0x32, 0xc2, 0xd3,
+ 0x34, 0x74, 0xfd, 0xc7, 0x9d, 0x3d, 0x66, 0x65, 0x57, 0x30, 0x88, 0xa7,
+ 0x4c, 0xb1, 0xc9, 0xeb, 0xbc, 0x30, 0x37, 0xd0, 0x17, 0x49, 0x93, 0x5e,
+ 0x59, 0x5a, 0x45, 0x0b, 0xd8, 0x0d, 0x1f, 0xd7, 0xf8, 0x92, 0x88, 0x3c,
+ 0x2f, 0xb8, 0xac, 0x02, 0x95, 0x0c, 0x80, 0xe0, 0xb3, 0xc8, 0x2a, 0x20,
+ 0x8a, 0x5d, 0x55, 0xe9, 0x5c, 0x23, 0xfa, 0xe9, 0x7d, 0x0a, 0x0f, 0x1a,
+ 0x2e, 0x66, 0x08, 0x36, 0xd7, 0x18, 0x1f, 0x96, 0x42, 0x99, 0xe0, 0x66,
+ 0x8b, 0xda, 0x81, 0x72, 0xf1, 0x75, 0xe3, 0x17, 0x23, 0x30, 0x8b, 0x05,
+ 0x3b, 0x47, 0x0f, 0xb3, 0x62, 0x96, 0x01, 0x6e, 0x36, 0xd5, 0x99, 0x0e,
+ 0xf1, 0x3b, 0xb2, 0xe4, 0x53, 0x46, 0x60, 0xeb, 0x2d, 0x38, 0xff, 0xd4,
+ 0x16, 0x4b, 0x67, 0x83, 0x58, 0xde, 0x9a, 0x57, 0xea, 0x22, 0xdb, 0x92,
+ 0xd7, 0x6a, 0xb9, 0xd9, 0xf9, 0xe2, 0x0d, 0x08, 0x62, 0xe7, 0x8b, 0x7f,
+ 0xb1, 0x9f, 0xed, 0xca, 0x67, 0xbb, 0x5f, 0xfc, 0xcb, 0x70, 0x88, 0xf1,
+ 0x11, 0x85, 0xac, 0xeb, 0xd7, 0xeb, 0x82, 0x49, 0x91, 0xca, 0x11, 0xe6,
+ 0xbf, 0x2c, 0x6c, 0x29, 0xef, 0x75, 0x4f, 0x7b, 0xf6, 0x57, 0xb9, 0x2f,
+ 0xde, 0x3f, 0xcb, 0xb7, 0xf2, 0xda, 0xc7, 0xa3, 0xad, 0x63, 0x8b, 0x6e,
+ 0x7d, 0x13, 0x68, 0x47, 0x82, 0xdc, 0xf0, 0xf2, 0xbf, 0x12, 0xa5, 0xfe,
+ 0xeb, 0x5a, 0x22, 0x4e, 0x3a, 0xda, 0x8e, 0x07, 0x38, 0x21, 0x94, 0x6c,
+ 0xcd, 0xa3, 0xa9, 0xd6, 0x3e, 0xa0, 0x96, 0x29, 0x4c, 0x9e, 0xee, 0x40,
+ 0xaf, 0x5e, 0xf8, 0x9f, 0x25, 0xfb, 0x9f, 0x37, 0x7c, 0x2d, 0xb1, 0xcf,
+ 0x70, 0x3a, 0x81, 0x91, 0x31, 0x1a, 0xae, 0xbe, 0x41, 0x58, 0xfc, 0x3f,
+ 0xfc, 0x20, 0x02, 0x95, 0xf9, 0x45, 0x46, 0x7e, 0x6d, 0x78, 0xd1, 0xd4,
+ 0xb0, 0xb7, 0x39, 0x6a, 0x15, 0x4b, 0x91, 0x77, 0xb9, 0xf2, 0x2f, 0x65,
+ 0xa6, 0xdc, 0x88, 0xd9, 0xda, 0xfd, 0xd1, 0xc1, 0xf1, 0x31, 0xe2, 0xf9,
+ 0xb0, 0xa8, 0x47, 0xcc, 0xc6, 0x40, 0x9b, 0x1b, 0x08, 0x47, 0x70, 0xe1,
+ 0x5f, 0x3e, 0xe9, 0xd3, 0xde, 0x61, 0xdb, 0x41, 0xfd, 0xa6, 0x31, 0x55,
+ 0x8a, 0x65, 0x2b, 0x41, 0xb3, 0x2c, 0xe5, 0xbc, 0xe9, 0xf1, 0x83, 0x57,
+ 0x79, 0x4f, 0x1c, 0x4b, 0xfc, 0x49, 0xcf, 0x81, 0x8c, 0xf0, 0x7e, 0x60,
+ 0xd3, 0xde, 0xb0, 0xe8, 0x94, 0xff, 0x23, 0x7b, 0xb3, 0xb3, 0x1d, 0x7f,
+ 0x02, 0x45, 0x09, 0x08, 0x0b, 0xf8, 0x8d, 0x73, 0xd2, 0x3d, 0xf6, 0x7c,
+ 0x3e, 0xe5, 0xa7, 0xaf, 0xf3, 0xe9, 0xd4, 0xdc, 0x09, 0xa8, 0x55, 0xff,
+ 0xa6, 0x37, 0xa6, 0x1b, 0x96, 0xfe, 0x7f, 0xc5, 0x38, 0xe0, 0x45, 0x92,
+ 0x67, 0xeb, 0xe5, 0x78, 0x9e, 0xb7, 0x06, 0xbc, 0x45, 0x13, 0xfc, 0x82,
+ 0x26, 0xfc, 0x7d, 0x66, 0xa9, 0x23, 0x23, 0xd1, 0x8e, 0x65, 0xbf, 0xf5,
+ 0xcb, 0xb2, 0x1c, 0xa7, 0xd5, 0xba, 0xb8, 0x58, 0x74, 0x9c, 0xeb, 0x3b,
+ 0xbb, 0xcf, 0x9e, 0xbf, 0x58, 0x1f, 0x8a, 0x9c, 0x06, 0x16, 0xd1, 0xf8,
+ 0xb9, 0xfc, 0xdc, 0x44, 0xca, 0x07, 0x54, 0x43, 0x52, 0x91, 0x3c, 0x1c,
+ 0x73, 0x78, 0x12, 0x17, 0xa3, 0xee, 0xde, 0x70, 0x6f, 0xff, 0x42, 0xfd,
+ 0xbc, 0x41, 0x17, 0xff, 0x92, 0x4f, 0xdf, 0xd8, 0x19, 0xfe, 0x0b, 0xcd,
+ 0xe5, 0x8d, 0x4c, 0xc2, 0xec, 0xab, 0x26, 0x6b, 0xd5, 0x7e, 0x9d, 0x84,
+ 0xa7, 0x36, 0x57, 0x37, 0x71, 0x0d, 0x93, 0x86, 0xb7, 0x7d, 0x30, 0x65,
+ 0x8f, 0x04, 0xa4, 0x55, 0x97, 0xa9, 0xb4, 0x75, 0x3f, 0x30, 0xad, 0x0c,
+ 0xa8, 0x95, 0x81, 0x63, 0xd8, 0x80, 0x70, 0x1e, 0xd0, 0x46, 0xf4, 0x25,
+ 0x5d, 0x6d, 0x06, 0xcb, 0x87, 0x88, 0x02, 0x65, 0x09, 0x5f, 0xf6, 0xc1,
+ 0xd7, 0xc7, 0xeb, 0x12, 0x24, 0xc2, 0xaa, 0x5b, 0x3f, 0x66, 0x33, 0xb6,
+ 0xb1, 0x5c, 0x93, 0x74, 0x41, 0xa7, 0x7f, 0x4d, 0x6b, 0x7a, 0xa5, 0x14,
+ 0xf3, 0x40, 0xfd, 0x72, 0x6e, 0xa9, 0xe9, 0x4c, 0x6e, 0x9d, 0x19, 0x59,
+ 0xa1, 0x2b, 0x06, 0x97, 0xf6, 0x9a, 0x01, 0xd8, 0x2a, 0x07, 0x3f, 0xc0,
+ 0x0f, 0xb3, 0xb0, 0x69, 0x69, 0x83, 0xb7, 0xd6, 0x11, 0x69, 0xd3, 0xa0,
+ 0xe4, 0x51, 0xf3, 0x15, 0xf3, 0x13, 0x65, 0x11, 0xbd, 0xa1, 0xb8, 0xcd,
+ 0x85, 0x12, 0x7c, 0xee, 0x81, 0xf4, 0xe8, 0x71, 0x26, 0xc9, 0x6c, 0x6c,
+ 0xca, 0x60, 0xc1, 0x90, 0xf8, 0xe7, 0xeb, 0x2f, 0x15, 0x9f, 0xf5, 0x8b,
+ 0x04, 0xa5, 0xf9, 0xf8, 0x2d, 0xf1, 0x05, 0x8a, 0x51, 0x88, 0xed, 0xa8,
+ 0x78, 0x49, 0xd4, 0x03, 0xeb, 0x96, 0xf2, 0x22, 0x47, 0x44, 0x30, 0xf0,
+ 0x51, 0xb4, 0xc7, 0x0f, 0x62, 0x00, 0xa0, 0x16, 0xd6, 0xff, 0x82, 0x43,
+ 0xf0, 0x9a, 0xb6, 0x01, 0x5f, 0x7f, 0xb1, 0xbe, 0x66, 0x6b, 0xa4, 0x5b,
+ 0xc9, 0xbd, 0xe3, 0xd4, 0x65, 0x02, 0xf5, 0xe7, 0x53, 0x5e, 0x5a, 0x30,
+ 0x52, 0x96, 0xc6, 0x08, 0xc6, 0x00, 0xf5, 0x6b, 0x8d, 0x34, 0x35, 0xa3,
+ 0xa4, 0xd0, 0x96, 0xd1, 0x98, 0x1b, 0xcf, 0x08, 0x23, 0x82, 0xa4, 0xc7,
+ 0x75, 0x0a, 0x0b, 0xc4, 0x7b, 0xeb, 0x16, 0xdb, 0x14, 0x76, 0x4c, 0x30,
+ 0xbc, 0x2a, 0x53, 0x58, 0xbd, 0x35, 0x49, 0x5f, 0x76, 0xd2, 0xbc, 0x3f,
+ 0xb1, 0xda, 0x13, 0x1e, 0x5c, 0x32, 0x18, 0x63, 0x7e, 0x04, 0x47, 0xe4,
+ 0x2d, 0x65, 0x5a, 0x4a, 0xa7, 0x6f, 0x68, 0xb9, 0x77, 0x86, 0x57, 0xf9,
+ 0x25, 0x2f, 0x86, 0x61, 0x91, 0x57, 0xd9, 0x96, 0xf9, 0xb3, 0x6f, 0x3e,
+ 0xdf, 0x25, 0xa9, 0x8c, 0x7e, 0x79, 0x86, 0xd8, 0x21, 0xff, 0xee, 0xf7,
+ 0xce, 0x86, 0x3d, 0x17, 0xf4, 0x4b, 0x6e, 0xef, 0x7c, 0xf1, 0xb4, 0xc8,
+ 0x28, 0x07, 0x0a, 0x62, 0xde, 0xaa, 0x46, 0xd4, 0xf7, 0xbc, 0x28, 0xc0,
+ 0xad, 0x2e, 0x21, 0x9f, 0xd4, 0x2e, 0xf4, 0x56, 0x82, 0x1b, 0x44, 0x50,
+ 0x27, 0xb9, 0x3b, 0x17, 0x93, 0x09, 0xe5, 0x4a, 0xe0, 0x66, 0xcd, 0xee,
+ 0x36, 0xfb, 0x7e, 0x48, 0xa3, 0x61, 0xef, 0xb7, 0x94, 0x7d, 0x4c, 0x88,
+ 0x06, 0x2e, 0x6f, 0x8d, 0xba, 0x47, 0x05, 0xf5, 0x35, 0x24, 0x64, 0x6a,
+ 0x3e, 0x26, 0xb6, 0x39, 0xef, 0xee, 0xa0, 0x57, 0xcd, 0x50, 0xa5, 0x4d,
+ 0xf2, 0x6a, 0x6d, 0x52, 0x37, 0xd9, 0xac, 0x86, 0xae, 0x2e, 0x80, 0x76,
+ 0xda, 0xab, 0xa2, 0xe0, 0xa2, 0xa3, 0x75, 0xff, 0xec, 0x97, 0x93, 0x26,
+ 0x33, 0xba, 0x2e, 0x01, 0x10, 0xcd, 0x99, 0xcf, 0x1d, 0xcd, 0xb9, 0xaa,
+ 0x1b, 0x48, 0x78, 0x36, 0xe0, 0xdb, 0x53, 0x44, 0xa2, 0xc1, 0xdb, 0x61,
+ 0x72, 0x82, 0xd0, 0xdc, 0x3a, 0x65, 0x1c, 0x0b, 0xbd, 0x61, 0x95, 0x1a,
+ 0x0c, 0xe9, 0xd4, 0x8a, 0xc5, 0x45, 0xef, 0x11, 0x74, 0x80, 0x92, 0x54,
+ 0xae, 0x00, 0xc7, 0x4c, 0x5c, 0x2c, 0x5f, 0x88, 0x3c, 0xd2, 0x87, 0x7d,
+ 0xda, 0x3e, 0x07, 0x3b, 0x3c, 0xdb, 0xe2, 0x90, 0x24, 0x63, 0x09, 0xd6,
+ 0x6b, 0x84, 0x03, 0x8c, 0x44, 0x00, 0xf5, 0xd8, 0xba, 0x3d, 0x04, 0x1c,
+ 0xfe, 0x97, 0xb1, 0xd1, 0x85, 0x72, 0xd8, 0x09, 0x4c, 0x03, 0x7e, 0x5a,
+ 0xd3, 0x1a, 0xa8, 0x0c, 0x78, 0xb8, 0x86, 0x8c, 0x7a, 0xd0, 0x1b, 0x67,
+ 0x99, 0x55, 0xae, 0x79, 0xaf, 0x4a, 0x1b, 0xd7, 0x0b, 0x5b, 0x8c, 0x60,
+ 0xf0, 0x5b, 0x17, 0x1a, 0x0d, 0x92, 0xc6, 0x95, 0xde, 0x9a, 0x5f, 0x48,
+ 0x38, 0x1b, 0x57, 0x66, 0xd7, 0xb3, 0x8a, 0xaf, 0x06, 0xf4, 0x8a, 0x12,
+ 0x5f, 0xe9, 0x54, 0xd4, 0x94, 0x77, 0x27, 0x89, 0xe2, 0x81, 0x5c, 0x3a,
+ 0x51, 0x51, 0xa3, 0x08, 0x31, 0x45, 0xb1, 0x8c, 0xb0, 0x3c, 0x24, 0x4f,
+ 0xf1, 0x2d, 0xc7, 0x6b, 0x4b, 0x19, 0xc5, 0x09, 0x2d, 0x4e, 0xeb, 0xc8,
+ 0x7a, 0x4f, 0xf0, 0xab, 0x6b, 0x8c, 0x5d, 0xb4, 0x4e, 0x4b, 0xb0, 0xde,
+ 0x4f, 0xd6, 0x69, 0xa8, 0xf4, 0xc5, 0x3a, 0xd6, 0x13, 0x1f, 0x7b, 0xcb,
+ 0xb7, 0x3e, 0x8c, 0x9c, 0x42, 0x7a, 0xe6, 0xcd, 0x97, 0xad, 0x55, 0xc2,
+ 0xe7, 0xda, 0xd4, 0x1b, 0x8e, 0xe6, 0x0f, 0x64, 0x6e, 0x7d, 0xd7, 0x6b,
+ 0xff, 0xcd, 0x81, 0x69, 0x05, 0xe0, 0xc3, 0x5e, 0x48, 0xe6, 0xc4, 0x7e,
+ 0x96, 0x23, 0xb3, 0x30, 0x68, 0xe8, 0xe9, 0x53, 0x7c, 0xa1, 0xac, 0xc8,
+ 0x86, 0x2b, 0x32, 0x77, 0x63, 0x12, 0x50, 0xce, 0x6b, 0x76, 0x33, 0x67,
+ 0xbd, 0xef, 0xae, 0x84, 0x95, 0x01, 0x3c, 0x67, 0x67, 0x88, 0x4c, 0x33,
+ 0x57, 0x5c, 0xd2, 0x36, 0x60, 0x95, 0xf7, 0x1e, 0x16, 0xb4, 0x67, 0x23,
+ 0x48, 0x55, 0xa5, 0xd7, 0x55, 0x8e, 0xf1, 0xae, 0x45, 0x3e, 0x01, 0xc4,
+ 0xee, 0x9b, 0x2f, 0xa7, 0xe5, 0x15, 0x71, 0xae, 0xbe, 0x39, 0x68, 0xf4,
+ 0x6f, 0x8f, 0x1e, 0xde, 0x95, 0x4e, 0x79, 0xc0, 0x38, 0x2b, 0x2c, 0xc5,
+ 0xeb, 0xdf, 0x2b, 0xc2, 0x29, 0x4d, 0xc3, 0xd3, 0x72, 0x22, 0x6d, 0xdb,
+ 0xa6, 0x79, 0x3f, 0x4c, 0xfb, 0xf6, 0x0b, 0xbf, 0x2f, 0x5d, 0x9c, 0x54,
+ 0x5a, 0x86, 0x6c, 0x64, 0x38, 0x45, 0xc3, 0x57, 0xb9, 0x2d, 0x56, 0x0f,
+ 0x03, 0x17, 0x15, 0x89, 0xe4, 0x7b, 0x6b, 0x26, 0xe9, 0x4f, 0xeb, 0x5f,
+ 0xae, 0x73, 0x30, 0xf6, 0xfa, 0xeb, 0x75, 0x70, 0x30, 0xe2, 0x4b, 0x5a,
+ 0x8f, 0x49, 0x2e, 0xa7, 0x75, 0xbe, 0x15, 0x07, 0x2c, 0x3b, 0x08, 0x2a,
+ 0x5a, 0x2b, 0x5a, 0x8e, 0x18, 0x86, 0xaa, 0x91, 0x7e, 0xa0, 0x1f, 0xcc,
+ 0x04, 0x28, 0xd5, 0x8c, 0x51, 0x11, 0xcc, 0xe3, 0xb8, 0xe1, 0xe0, 0x15,
+ 0xb9, 0x74, 0x21, 0x96, 0x01, 0x55, 0xa2, 0xa6, 0x98, 0x02, 0x36, 0x73,
+ 0x2e, 0x8b, 0x05, 0xe5, 0x10, 0x4f, 0x1a, 0xae, 0xad, 0x86, 0xb3, 0x34,
+ 0x4c, 0x3e, 0x14, 0x8c, 0x01, 0x9e, 0x91, 0xb2, 0x9c, 0x57, 0x93, 0xe5,
+ 0x9c, 0x4c, 0x15, 0x13, 0x32, 0x90, 0xe1, 0xe2, 0x61, 0xf1, 0xa0, 0xe5,
+ 0x32, 0xf7, 0x07, 0xcc, 0xc6, 0x11, 0x36, 0x62, 0x4b, 0xbf, 0x08, 0x0f,
+ 0xa1, 0xa0, 0x28, 0x31, 0x52, 0x43, 0x2a, 0xb0, 0xe8, 0x12, 0xc2, 0x80,
+ 0xc8, 0x5b, 0x77, 0xf4, 0xf6, 0xe8, 0xfc, 0xfc, 0xe8, 0x9c, 0xd6, 0x7b,
+ 0xbf, 0x68, 0x55, 0x32, 0xb2, 0x00, 0x93, 0xce, 0xfd, 0xa7, 0x21, 0xaa,
+ 0x21, 0xa4, 0x36, 0xb3, 0xc2, 0x74, 0x3a, 0x25, 0x08, 0x63, 0x68, 0x10,
+ 0x8c, 0xa7, 0xc2, 0x15, 0x63, 0x7d, 0xf3, 0x22, 0x42, 0x94, 0xad, 0x29,
+ 0xdf, 0x2f, 0x20, 0xe6, 0xc9, 0x16, 0xae, 0x85, 0x4a, 0x2a, 0xe4, 0x2d,
+ 0x35, 0x73, 0xf9, 0x3a, 0x6b, 0x89, 0xa9, 0x43, 0x89, 0x2a, 0xcd, 0xc4,
+ 0xc1, 0x3d, 0xb3, 0xf6, 0x09, 0x4c, 0xf9, 0x92, 0xce, 0x28, 0xe9, 0x4e,
+ 0x58, 0x8c, 0xba, 0x59, 0x2e, 0xf2, 0xa9, 0xb5, 0xf6, 0x9a, 0xcf, 0x8d,
+ 0xf8, 0x97, 0xf0, 0x29, 0xaf, 0x35, 0xfe, 0x04, 0x9e, 0x46, 0x35, 0x46,
+ 0xf8, 0xd6, 0xb6, 0x0e, 0xce, 0x69, 0x82, 0xb4, 0x24, 0x0e, 0xe4, 0xd2,
+ 0x6a, 0x27, 0xed, 0x1c, 0x5c, 0xa1, 0xfd, 0x0c, 0x56, 0x46, 0xe2, 0x16,
+ 0x1a, 0x12, 0xe3, 0x73, 0x06, 0xb2, 0x65, 0xcd, 0x5d, 0x6c, 0x36, 0x85,
+ 0x95, 0xed, 0x31, 0x5a, 0x04, 0x52, 0xef, 0xaa, 0xbd, 0xe4, 0xc7, 0x3a,
+ 0x9f, 0xfc, 0xec, 0x2e, 0x0f, 0xe4, 0x59, 0xb8, 0xf0, 0x69, 0xb6, 0xd0,
+ 0x9b, 0xc9, 0xcb, 0x42, 0x89, 0x32, 0xcc, 0x29, 0xaf, 0x1f, 0x46, 0x47,
+ 0xe7, 0xc9, 0xfe, 0xd7, 0x84, 0x96, 0xfa, 0xbf, 0xb9, 0xc1, 0xf4, 0x9c,
+ 0xdc, 0x0e, 0x6b, 0x12, 0xf3, 0x29, 0x18, 0x10, 0x99, 0x9a, 0xc2, 0x19,
+ 0xbf, 0xa8, 0xb5, 0xb3, 0xb9, 0x96, 0x80, 0xf5, 0x92, 0xf5, 0x5b, 0x7b,
+ 0xb8, 0x96, 0x3c, 0xb9, 0x8b, 0x9f, 0xb2, 0x87, 0x74, 0xc8, 0xfc, 0x5d,
+ 0x64, 0xf4, 0x18, 0x76, 0x49, 0xe8, 0xde, 0xc8, 0xe8, 0xeb, 0x40, 0xed,
+ 0xe4, 0x5d, 0xda, 0x4f, 0xd6, 0xdf, 0x95, 0xff, 0x30, 0xc2, 0x40, 0xba,
+ 0xf5, 0x6c, 0xb8, 0x9d, 0x6c, 0x7c, 0x9f, 0x17, 0xaf, 0x5e, 0xfc, 0x25,
+ 0x39, 0xde, 0x5c, 0x6f, 0x05, 0x9e, 0x73, 0x4d, 0xb0, 0x71, 0x5a, 0xdc,
+ 0xd8, 0x2d, 0x3b, 0xc5, 0xc9, 0xe6, 0x40, 0x37, 0x2d, 0xa8, 0xc0, 0xa5,
+ 0x4b, 0x57, 0xb6, 0x88, 0x04, 0x39, 0x89, 0x61, 0x4f, 0xbe, 0xb3, 0xe8,
+ 0xc0, 0xa4, 0xe5, 0x9b, 0xa7, 0xa6, 0xb4, 0x74, 0xaf, 0x5e, 0x04, 0x4d,
+ 0x3c, 0xb7, 0x6d, 0x7c, 0xe0, 0x36, 0x7e, 0x61, 0x13, 0xbb, 0xc3, 0xed,
+ 0xdd, 0x64, 0xe3, 0x74, 0xb4, 0xb5, 0x6b, 0x5b, 0x08, 0x9b, 0xd8, 0x45,
+ 0x13, 0xf4, 0x50, 0xfb, 0xe5, 0xe7, 0xd4, 0xff, 0x8f, 0x59, 0xf1, 0x73,
+ 0xb2, 0xf1, 0xc3, 0xce, 0x8e, 0x69, 0xe0, 0x2f, 0xc9, 0xfe, 0xf1, 0x0f,
+ 0xc9, 0xf3, 0xa1, 0x69, 0xec, 0x7d, 0x7a, 0x2b, 0xcd, 0x09, 0xe8, 0xe7,
+ 0x08, 0x8d, 0x98, 0xef, 0x83, 0x36, 0x5e, 0x74, 0xda, 0x38, 0x31, 0x7a,
+ 0xe1, 0xbd, 0xb9, 0x56, 0xb6, 0x87, 0xcf, 0x76, 0x93, 0xfc, 0xc5, 0xe7,
+ 0x2f, 0xb5, 0x21, 0x69, 0x03, 0xdf, 0xb7, 0xad, 0x95, 0x0c, 0x2b, 0x61,
+ 0x44, 0x9d, 0xa3, 0x7b, 0xc3, 0xd0, 0xc0, 0x22, 0x80, 0x9c, 0x7f, 0x9d,
+ 0x56, 0x5a, 0x4f, 0x93, 0xc0, 0xd4, 0xcd, 0x4e, 0x09, 0xdc, 0x6e, 0x06,
+ 0xb3, 0xa5, 0xb9, 0x38, 0xf7, 0x82, 0xe1, 0x90, 0x6e, 0xaa, 0x8f, 0xfe,
+ 0x25, 0x79, 0x37, 0x3a, 0x3e, 0x32, 0x33, 0xda, 0x36, 0x43, 0x73, 0x6b,
+ 0xc8, 0x03, 0xc2, 0x57, 0x58, 0xdc, 0x57, 0x40, 0x6f, 0x94, 0x36, 0xfc,
+ 0xca, 0x8f, 0x20, 0x3a, 0x73, 0x71, 0xd7, 0xe8, 0x97, 0xc2, 0x44, 0x06,
+ 0xfb, 0x57, 0xa4, 0x42, 0xf0, 0x55, 0x8b, 0xae, 0xbf, 0x2d, 0x0b, 0x73,
+ 0x4c, 0xaa, 0xb2, 0xa2, 0x68, 0xa6, 0xf5, 0x96, 0xb4, 0xf0, 0xed, 0xe1,
+ 0x11, 0xa7, 0x1e, 0xbf, 0x4b, 0x0b, 0xc3, 0x23, 0x09, 0x42, 0xa8, 0xbe,
+ 0x21, 0x9f, 0x3c, 0xbb, 0x73, 0xf8, 0xfd, 0x93, 0x87, 0xe2, 0xde, 0xec,
+ 0xe3, 0x67, 0xc3, 0x1d, 0x02, 0x70, 0x20, 0xad, 0xf7, 0xed, 0x3b, 0xf3,
+ 0xf7, 0xce, 0xf3, 0xf5, 0x84, 0xbe, 0x6a, 0x6b, 0xf0, 0x7a, 0x5e, 0xd7,
+ 0x0e, 0x4e, 0x4f, 0xbf, 0x3d, 0xe6, 0xa0, 0x8c, 0x03, 0x31, 0xab, 0x92,
+ 0x70, 0x65, 0xb5, 0x62, 0xe6, 0xae, 0x46, 0x7b, 0x73, 0x59, 0x2e, 0x70,
+ 0xc6, 0xdd, 0x64, 0xd9, 0x82, 0x22, 0x04, 0x9a, 0x0e, 0x47, 0x68, 0x84,
+ 0x47, 0xdb, 0x78, 0x23, 0x12, 0x7f, 0x5a, 0xf0, 0x47, 0x35, 0x41, 0xca,
+ 0xaa, 0x09, 0x77, 0xfc, 0x60, 0xe1, 0x0d, 0x52, 0xeb, 0x32, 0xd3, 0x3a,
+ 0x0a, 0xd2, 0x94, 0x9a, 0xa0, 0xb9, 0x08, 0x81, 0x79, 0x51, 0x74, 0xdf,
+ 0xf5, 0x91, 0x91, 0xee, 0x79, 0xd0, 0x7b, 0x62, 0xb5, 0x5d, 0xf7, 0x40,
+ 0x78, 0x21, 0xd1, 0x2e, 0xa4, 0x48, 0x07, 0x4c, 0xc7, 0x0f, 0x46, 0x96,
+ 0xc0, 0x9c, 0x84, 0x37, 0xd7, 0xb0, 0x65, 0x23, 0x64, 0xee, 0xfd, 0xfe,
+ 0xbb, 0xa3, 0x37, 0xdf, 0xed, 0x9f, 0x7c, 0x38, 0x32, 0xaf, 0xe4, 0x80,
+ 0xbb, 0xb6, 0x61, 0x75, 0x18, 0xe3, 0x3c, 0x47, 0xd5, 0xc9, 0xda, 0x88,
+ 0x07, 0xeb, 0x6b, 0x1c, 0xf2, 0x9d, 0xf4, 0xe8, 0xad, 0x1d, 0x7e, 0xcd,
+ 0xd0, 0x05, 0xfd, 0xb5, 0xcb, 0x7f, 0xed, 0xfe, 0xa5, 0xb7, 0xd9, 0x9a,
+ 0x74, 0xa0, 0x25, 0x13, 0xbd, 0xdc, 0x71, 0xa5, 0x16, 0x0a, 0xd9, 0xe1,
+ 0x3c, 0x03, 0x5e, 0x95, 0x9e, 0xfa, 0x68, 0xf4, 0x6e, 0xa3, 0x67, 0x37,
+ 0xc6, 0x0f, 0xbe, 0x0e, 0xde, 0xa3, 0x97, 0xde, 0x40, 0xc0, 0xe8, 0x6d,
+ 0xf6, 0xad, 0xc8, 0x01, 0xf7, 0x35, 0xb5, 0xa1, 0x4d, 0x64, 0xf7, 0x0b,
+ 0x8a, 0x52, 0xdc, 0xe8, 0xf1, 0x2f, 0x6f, 0x0e, 0xf7, 0x2f, 0x8e, 0xe8,
+ 0x05, 0xed, 0x5e, 0xa1, 0xdc, 0x35, 0x1b, 0x80, 0xc6, 0xb3, 0xd1, 0xe3,
+ 0x0f, 0xdf, 0xd0, 0x84, 0x7a, 0x9b, 0xec, 0xcb, 0x80, 0xa3, 0xbb, 0x33,
+ 0xae, 0xb2, 0xd0, 0x60, 0x6a, 0x97, 0xce, 0x5b, 0x6b, 0x14, 0xc9, 0x46,
+ 0x8f, 0xbf, 0xeb, 0x59, 0x0b, 0xae, 0xd4, 0x75, 0x16, 0x77, 0xe5, 0x14,
+ 0xb9, 0x02, 0x41, 0x0a, 0x23, 0x87, 0x89, 0xb9, 0xfd, 0x11, 0x67, 0x05,
+ 0x5b, 0x9c, 0x3c, 0x54, 0x62, 0xbb, 0xf1, 0x92, 0x2f, 0x4c, 0x36, 0xa6,
+ 0xb2, 0xdc, 0xd9, 0x7d, 0xf6, 0x17, 0xac, 0xe7, 0x9b, 0xde, 0x96, 0xb9,
+ 0x1b, 0x7a, 0x7f, 0xa1, 0xae, 0x73, 0x57, 0xdf, 0xd5, 0xee, 0x07, 0xe9,
+ 0x53, 0x42, 0x51, 0x1c, 0xc2, 0x42, 0xbb, 0xee, 0xa1, 0xa0, 0x60, 0x41,
+ 0xef, 0x38, 0xa3, 0x49, 0x71, 0x43, 0xd4, 0xa1, 0x8f, 0xfd, 0x1a, 0x67,
+ 0x57, 0x79, 0x81, 0x1a, 0x5d, 0x6c, 0xd4, 0x45, 0x77, 0xfe, 0xfd, 0xd1,
+ 0xe7, 0x77, 0x79, 0x8e, 0x82, 0xb3, 0x42, 0x7d, 0xce, 0x1f, 0x34, 0xe9,
+ 0x09, 0x7d, 0x49, 0x41, 0x53, 0xcc, 0xa5, 0x2b, 0x1d, 0x8c, 0xc5, 0xb6,
+ 0xa3, 0xca, 0x08, 0x64, 0x02, 0xc3, 0x5a, 0x1e, 0x20, 0x28, 0x71, 0x04,
+ 0x80, 0x17, 0xf8, 0xa0, 0x77, 0x76, 0x3a, 0xa6, 0x6c, 0x5e, 0x9b, 0xe1,
+ 0xe1, 0x69, 0xe5, 0x76, 0xe9, 0xf5, 0xf8, 0xe5, 0x1e, 0x82, 0x0d, 0x5d,
+ 0x94, 0xbc, 0x96, 0xb5, 0xb5, 0x21, 0xc1, 0xdb, 0x28, 0xcf, 0xb6, 0xf7,
+ 0xa9, 0x93, 0x3b, 0x85, 0x69, 0xb0, 0x4a, 0xcf, 0xfa, 0xb1, 0x61, 0x35,
+ 0x45, 0x56, 0x3d, 0x1a, 0xf4, 0x10, 0x71, 0x46, 0x61, 0x8a, 0x5e, 0x32,
+ 0x1e, 0xbd, 0x33, 0x1c, 0x0e, 0x5d, 0x8d, 0x5c, 0xda, 0x16, 0xf1, 0x41,
+ 0xa1, 0xb6, 0x89, 0x87, 0xb3, 0x89, 0x35, 0xde, 0x80, 0x30, 0x0f, 0x81,
+ 0x7a, 0x53, 0x82, 0x61, 0xc4, 0x4e, 0x60, 0x8f, 0x86, 0x67, 0xe3, 0x58,
+ 0x97, 0x6e, 0xd7, 0x35, 0xb9, 0xfd, 0x26, 0xb6, 0x09, 0x8f, 0x8c, 0x8d,
+ 0x6d, 0x8f, 0x52, 0x19, 0xcf, 0xf2, 0xa9, 0xd2, 0xae, 0x05, 0x51, 0x30,
+ 0x05, 0x75, 0x83, 0x4e, 0x38, 0xb5, 0x93, 0x17, 0x4d, 0x86, 0xe2, 0x0a,
+ 0x40, 0x1b, 0x51, 0x0f, 0xd9, 0xe6, 0x5c, 0x0a, 0x63, 0x51, 0x91, 0xa6,
+ 0x47, 0x6b, 0xac, 0x37, 0xc8, 0xc2, 0x8a, 0xcd, 0xd2, 0x8e, 0xc0, 0xae,
+ 0x92, 0xce, 0x0c, 0xd9, 0xbf, 0xef, 0xa0, 0x59, 0xd7, 0x50, 0xac, 0x2f,
+ 0x13, 0xed, 0xd9, 0x0c, 0x15, 0x6e, 0x2f, 0x99, 0xbc, 0x33, 0x57, 0x51,
+ 0x04, 0xd8, 0x80, 0x81, 0x2f, 0x34, 0x69, 0x4e, 0xb9, 0x87, 0x40, 0x1f,
+ 0x3c, 0xe6, 0x2f, 0x9f, 0x68, 0x8b, 0xd6, 0x59, 0xde, 0x59, 0x1b, 0x77,
+ 0x2b, 0xb7, 0x59, 0x97, 0x59, 0x51, 0xb6, 0x2e, 0x33, 0xc4, 0x80, 0xe3,
+ 0x7b, 0x49, 0x7a, 0x47, 0xb5, 0x9a, 0x33, 0x8a, 0x99, 0x44, 0xa4, 0x03,
+ 0xac, 0x32, 0x27, 0x9e, 0x9d, 0xd1, 0x81, 0xcf, 0x4a, 0x39, 0xf8, 0xd4,
+ 0x15, 0x84, 0xd7, 0xaa, 0xaf, 0x0c, 0x2b, 0xaa, 0x06, 0xbd, 0x1c, 0xb5,
+ 0x69, 0x09, 0x06, 0x52, 0x24, 0x75, 0x55, 0xcf, 0x69, 0xe4, 0x9b, 0xa8,
+ 0xde, 0xc9, 0xe2, 0x3c, 0x62, 0x05, 0xc9, 0xce, 0xc1, 0x71, 0x15, 0xba,
+ 0x5a, 0x80, 0x62, 0xb7, 0x9d, 0x58, 0xff, 0xb4, 0x98, 0x9f, 0x28, 0xe4,
+ 0xb6, 0x18, 0xd8, 0xb2, 0xdb, 0x36, 0x1e, 0xab, 0xca, 0xaf, 0xae, 0xa4,
+ 0x60, 0x68, 0x77, 0x6a, 0x71, 0x22, 0x3b, 0xa1, 0x55, 0xa1, 0xc8, 0xe4,
+ 0x87, 0x55, 0xab, 0x79, 0xa1, 0x36, 0x1f, 0xb5, 0xba, 0xb4, 0x88, 0x59,
+ 0x7d, 0x92, 0xbc, 0x6f, 0x0d, 0xaa, 0x0a, 0x23, 0x15, 0x9c, 0x92, 0x26,
+ 0xda, 0x3e, 0xe4, 0xd3, 0xf3, 0x35, 0x40, 0x71, 0x17, 0x2e, 0xf3, 0x5d,
+ 0x37, 0x1d, 0x28, 0x66, 0x2e, 0x02, 0xc5, 0x45, 0x87, 0xde, 0xd9, 0xf0,
+ 0x27, 0xae, 0xe9, 0x35, 0x4e, 0x9d, 0xca, 0xb5, 0x96, 0xb4, 0xac, 0xbd,
+ 0x54, 0x76, 0xe2, 0xb8, 0x10, 0x3e, 0x54, 0xde, 0x66, 0x0e, 0x4a, 0xcf,
+ 0x19, 0x1c, 0x1d, 0xfc, 0xa9, 0x9c, 0x7e, 0xcb, 0x4c, 0x3a, 0x0e, 0x5e,
+ 0xcb, 0xaf, 0x30, 0xc9, 0xce, 0xaa, 0xf8, 0xf5, 0x2d, 0xc4, 0x54, 0x52,
+ 0xfa, 0x2c, 0x9e, 0xc7, 0x26, 0x7e, 0x6b, 0x6d, 0x91, 0x69, 0x84, 0xa1,
+ 0x30, 0x3c, 0xd5, 0x84, 0x0b, 0x33, 0x28, 0xa2, 0xb8, 0x8d, 0x9b, 0x73,
+ 0xfe, 0x5f, 0x9d, 0x65, 0xcf, 0x6e, 0x52, 0x0f, 0x69, 0x70, 0x63, 0x21,
+ 0x02, 0xd0, 0x00, 0x09, 0x74, 0xd6, 0x85, 0xbf, 0x3f, 0x4b, 0x29, 0x88,
+ 0xa5, 0xe4, 0xe8, 0x00, 0x6c, 0x19, 0x88, 0x1a, 0xc6, 0xb4, 0x0e, 0x4f,
+ 0x0d, 0x8e, 0x9f, 0x8d, 0xd6, 0x60, 0x5a, 0x03, 0x10, 0x2a, 0x35, 0x63,
+ 0xa8, 0x04, 0x11, 0xd6, 0x13, 0xbf, 0xe8, 0xeb, 0xea, 0x24, 0xf1, 0x71,
+ 0xeb, 0x8c, 0x3e, 0x75, 0x64, 0xcf, 0xce, 0x4f, 0xbf, 0x3e, 0x3f, 0x1a,
+ 0x8d, 0x92, 0x77, 0x47, 0x17, 0xac, 0xf6, 0x4b, 0x25, 0xed, 0x2b, 0xd2,
+ 0xdc, 0x13, 0xb8, 0x1d, 0x14, 0xf4, 0x46, 0xa3, 0x4f, 0xd4, 0xa6, 0x80,
+ 0x94, 0xa4, 0x92, 0x5c, 0x6a, 0x10, 0xe5, 0xa0, 0xcf, 0xcf, 0x24, 0xa0,
+ 0xee, 0x1a, 0x86, 0x7f, 0x84, 0x37, 0xc1, 0x37, 0x69, 0xed, 0xe8, 0xce,
+ 0xa2, 0x0a, 0x19, 0x99, 0x03, 0x9e, 0xae, 0x95, 0x73, 0x39, 0x6b, 0x3a,
+ 0xdd, 0xde, 0xe6, 0x5f, 0x4c, 0xef, 0x4f, 0xc9, 0x45, 0xd9, 0x10, 0x40,
+ 0x27, 0xfd, 0x7a, 0xae, 0xf4, 0xf1, 0xa7, 0xe4, 0x07, 0xd3, 0xe6, 0xd4,
+ 0xac, 0x3a, 0x19, 0x93, 0xcd, 0x85, 0x3b, 0x42, 0xc9, 0x42, 0x57, 0x87,
+ 0x05, 0x20, 0xe3, 0x7e, 0xa5, 0xe6, 0x65, 0x55, 0x0d, 0xe3, 0x65, 0x4c,
+ 0x5a, 0x75, 0x48, 0x18, 0x27, 0x46, 0xc2, 0xeb, 0x6c, 0xcf, 0x52, 0x8b,
+ 0x34, 0x49, 0x4e, 0xb2, 0xcb, 0x06, 0x02, 0x09, 0x75, 0x67, 0x9a, 0xdb,
+ 0x26, 0xc0, 0xdc, 0x1d, 0xaa, 0xaf, 0x64, 0x7e, 0x7d, 0xf6, 0xf9, 0xcb,
+ 0xed, 0xcf, 0xf9, 0x57, 0xfd, 0xf9, 0xea, 0xf9, 0xb6, 0x00, 0x4f, 0x9b,
+ 0xbf, 0x9e, 0xef, 0x3d, 0xdf, 0xd9, 0x23, 0x3c, 0xbc, 0xed, 0xbd, 0x6d,
+ 0xf3, 0xff, 0xcf, 0xe5, 0x13, 0x02, 0xfd, 0x7b, 0xb5, 0xfb, 0xf9, 0x67,
+ 0x08, 0x8c, 0x21, 0xfa, 0x98, 0x99, 0x4e, 0x06, 0x4d, 0x39, 0x00, 0x2c,
+ 0x0f, 0x84, 0xa0, 0x3f, 0xb5, 0x8d, 0x92, 0xe4, 0x69, 0x9f, 0x90, 0x5f,
+ 0xf5, 0x8a, 0xd5, 0x9b, 0x59, 0x06, 0x3c, 0xfe, 0x4b, 0x0f, 0x6a, 0x44,
+ 0x03, 0xb8, 0x39, 0xdb, 0x58, 0xa6, 0x21, 0x6f, 0x37, 0xf8, 0x1b, 0x38,
+ 0x57, 0xad, 0x77, 0x38, 0x0e, 0xdc, 0x83, 0xd4, 0xfa, 0xa5, 0x5d, 0x6b,
+ 0xfe, 0xf3, 0x1a, 0x80, 0xb2, 0x64, 0xab, 0xe4, 0xbd, 0x89, 0x96, 0x73,
+ 0xb5, 0x4f, 0x91, 0x44, 0x38, 0xe7, 0x94, 0x81, 0x4b, 0x8e, 0x26, 0xfe,
+ 0xa5, 0xfd, 0xb1, 0x11, 0x8b, 0xde, 0x12, 0x6a, 0x48, 0xc2, 0xde, 0x6c,
+ 0xaa, 0x40, 0xa4, 0xaf, 0x16, 0xf1, 0xac, 0xb9, 0xed, 0x77, 0x2b, 0x45,
+ 0x5c, 0x4d, 0x1e, 0xb2, 0x29, 0x56, 0x5c, 0x1d, 0x33, 0x32, 0xe5, 0xa0,
+ 0x39, 0x21, 0xa3, 0x5f, 0xd0, 0x9c, 0x9b, 0x11, 0x28, 0xd8, 0xee, 0xdc,
+ 0xc0, 0xdb, 0x9c, 0x9c, 0x63, 0xdc, 0x74, 0x35, 0x2c, 0x10, 0xa3, 0xde,
+ 0x78, 0xfc, 0xaa, 0x25, 0xd9, 0x01, 0xbf, 0x21, 0xe2, 0xa7, 0x4d, 0x5b,
+ 0x93, 0xc2, 0xdc, 0xf6, 0x79, 0xa5, 0xec, 0xa0, 0x2b, 0xa2, 0x46, 0xaf,
+ 0x3f, 0xe9, 0x03, 0xe7, 0xc9, 0x1e, 0xba, 0x47, 0xa7, 0xe6, 0x42, 0xdf,
+ 0x6d, 0x6d, 0xd0, 0x0d, 0x1b, 0x4a, 0x1e, 0x3b, 0x92, 0xee, 0x39, 0x44,
+ 0x97, 0xdb, 0xe6, 0xfc, 0x8b, 0x08, 0x95, 0x61, 0x31, 0x3e, 0xe0, 0xe9,
+ 0x2c, 0x09, 0x0e, 0x7d, 0x53, 0x59, 0xd8, 0xe0, 0x8f, 0x36, 0x82, 0x0b,
+ 0xf7, 0x9a, 0x94, 0x0f, 0x4c, 0x99, 0xf2, 0x67, 0x7e, 0xaa, 0xab, 0xe5,
+ 0x76, 0xe3, 0xb4, 0x6a, 0xc1, 0x8e, 0xaf, 0x09, 0xa0, 0xfd, 0x9c, 0x30,
+ 0xbd, 0xbc, 0x1a, 0xf0, 0x7f, 0x58, 0x5b, 0x1b, 0x9d, 0x1d, 0x1d, 0x1d,
+ 0x26, 0x27, 0xc7, 0xef, 0x8e, 0x2f, 0x3c, 0x81, 0xdc, 0x5e, 0x24, 0x6a,
+ 0x74, 0xd5, 0x12, 0x3d, 0x9d, 0xe5, 0x70, 0x30, 0xb7, 0x52, 0x3a, 0x41,
+ 0xae, 0xf2, 0x79, 0x26, 0x49, 0x0e, 0xb3, 0xee, 0x7b, 0x50, 0xbd, 0x01,
+ 0xa6, 0x33, 0x4c, 0xbe, 0xf2, 0x62, 0x24, 0x93, 0xda, 0x08, 0x37, 0x13,
+ 0x5b, 0x33, 0x75, 0xf0, 0x57, 0x09, 0xd9, 0x68, 0x4b, 0x4e, 0x82, 0xd6,
+ 0x69, 0x33, 0x6e, 0x24, 0xcc, 0xb5, 0x33, 0x2a, 0x5a, 0xdb, 0x8c, 0x23,
+ 0x9f, 0x3d, 0x0b, 0x1d, 0x22, 0xf8, 0xee, 0x32, 0x24, 0xe9, 0xcf, 0x73,
+ 0x4e, 0x85, 0xf4, 0xc3, 0x8b, 0x6d, 0x19, 0xc9, 0x8b, 0x92, 0xf9, 0xb8,
+ 0xdf, 0xa3, 0x5f, 0x1f, 0x58, 0x63, 0x6b, 0xb5, 0x2f, 0xbf, 0xf0, 0xec,
+ 0xb3, 0x6d, 0x9b, 0x4d, 0xb0, 0x00, 0xcf, 0x11, 0x51, 0x9f, 0x3a, 0xdb,
+ 0x49, 0x8c, 0x3c, 0xb2, 0x24, 0xa9, 0xbe, 0x5a, 0x16, 0xc1, 0x75, 0xf7,
+ 0x57, 0x7e, 0xd7, 0xcc, 0xff, 0xe5, 0x36, 0xae, 0xb7, 0xcb, 0xb4, 0x1a,
+ 0x18, 0xc9, 0xeb, 0x61, 0xa0, 0xd6, 0x55, 0xa6, 0x08, 0x09, 0x3d, 0x66,
+ 0xd3, 0x4f, 0xe6, 0x2a, 0x56, 0x76, 0xa4, 0x45, 0x97, 0x12, 0x52, 0xc2,
+ 0x45, 0x39, 0x93, 0x03, 0x40, 0x53, 0xa7, 0x44, 0x5c, 0x35, 0x76, 0x3a,
+ 0x59, 0xc7, 0x21, 0xb9, 0xea, 0x2e, 0x3a, 0x1e, 0x45, 0x09, 0x02, 0x60,
+ 0xab, 0xd4, 0x6a, 0x4e, 0xd3, 0x94, 0xb9, 0x84, 0xa2, 0xf5, 0x3c, 0xd9,
+ 0xf9, 0x9c, 0xe6, 0xf1, 0x69, 0xf3, 0x79, 0x5b, 0x56, 0x13, 0x9b, 0xf2,
+ 0x0b, 0x75, 0xc1, 0xcb, 0xff, 0xe4, 0xac, 0x05, 0x94, 0xb7, 0xe1, 0xd5,
+ 0xd5, 0xf8, 0x58, 0xc4, 0xef, 0x91, 0x7e, 0x22, 0xae, 0x75, 0x58, 0xa6,
+ 0xe0, 0xeb, 0x66, 0x09, 0x89, 0xee, 0x1a, 0x59, 0x17, 0xb2, 0xb5, 0x72,
+ 0xfc, 0xde, 0x7a, 0x65, 0xf3, 0x43, 0x79, 0x19, 0xc8, 0x3a, 0x62, 0x68,
+ 0xed, 0x2e, 0x9f, 0x42, 0xaa, 0x76, 0x98, 0x5e, 0x66, 0xbf, 0x98, 0xf8,
+ 0x38, 0x6c, 0x1a, 0xee, 0x4b, 0xf8, 0x3d, 0xed, 0xc8, 0x44, 0x80, 0xa1,
+ 0x65, 0x2d, 0x61, 0x5c, 0xd8, 0x80, 0xfc, 0x40, 0xe9, 0xc7, 0xce, 0x45,
+ 0x40, 0xaa, 0x14, 0xb1, 0xe6, 0x9e, 0xeb, 0x85, 0x42, 0xf9, 0x9b, 0x66,
+ 0xa6, 0x76, 0x85, 0x77, 0x96, 0xb0, 0xdb, 0x73, 0x26, 0x80, 0x11, 0x6f,
+ 0xda, 0x3b, 0xdb, 0x46, 0x7e, 0x9d, 0x95, 0xdd, 0xfa, 0xd6, 0xa1, 0x52,
+ 0x8a, 0x69, 0x0d, 0xb0, 0x3a, 0x3b, 0xdb, 0xdf, 0xae, 0x5e, 0x75, 0xa0,
+ 0x82, 0x3f, 0xfa, 0xf2, 0xee, 0xf3, 0x47, 0x36, 0xed, 0xb4, 0x82, 0x5e,
+ 0x9e, 0x69, 0x38, 0x24, 0x04, 0x41, 0xe7, 0x84, 0x09, 0xb6, 0xcd, 0x10,
+ 0x7e, 0x76, 0x95, 0xd2, 0xf0, 0x1f, 0x1b, 0xbd, 0xa6, 0x6c, 0x74, 0x86,
+ 0xf2, 0x4e, 0x02, 0xb4, 0xf9, 0xcb, 0x9a, 0x2c, 0x64, 0x0b, 0x40, 0xa2,
+ 0x39, 0x35, 0xd6, 0x66, 0x7b, 0x33, 0xee, 0x84, 0xf7, 0x36, 0x73, 0xce,
+ 0x7e, 0x9b, 0x49, 0x28, 0xf5, 0x54, 0xd9, 0xd5, 0x92, 0x81, 0x1d, 0x4a,
+ 0x56, 0xfb, 0x09, 0x00, 0x58, 0xce, 0xab, 0xe1, 0xcd, 0x14, 0x49, 0xc4,
+ 0xf4, 0x04, 0xc6, 0x3b, 0x49, 0x55, 0x64, 0x65, 0x91, 0xa3, 0x7b, 0x31,
+ 0x90, 0x7d, 0x76, 0x42, 0x0e, 0x31, 0x70, 0x83, 0xb5, 0xa4, 0x5b, 0xfa,
+ 0x96, 0x11, 0xee, 0x86, 0x48, 0xc4, 0x65, 0x42, 0xb1, 0xcc, 0x9e, 0xb2,
+ 0xbe, 0xc8, 0x31, 0xd6, 0xb0, 0x87, 0x00, 0x0d, 0xf4, 0x85, 0x6a, 0xd1,
+ 0x92, 0xed, 0x8a, 0x38, 0x7e, 0xad, 0x48, 0x83, 0x8c, 0x4b, 0x4e, 0x76,
+ 0xff, 0x83, 0xd3, 0xf7, 0x6f, 0x8f, 0xbf, 0xb6, 0x08, 0x3c, 0xcc, 0xc4,
+ 0xb5, 0x26, 0x27, 0xda, 0xb4, 0x25, 0x8a, 0xad, 0xd3, 0x5b, 0x6a, 0xd7,
+ 0x49, 0x20, 0xae, 0x61, 0x4f, 0x1f, 0xfd, 0x0f, 0xc0, 0x40, 0x8a, 0x67,
+ 0x64, 0x2b, 0x67, 0x44, 0x8b, 0x7a, 0xd3, 0x59, 0x1e, 0x3a, 0xf0, 0x60,
+ 0x9c, 0xb0, 0x91, 0x56, 0xcd, 0x72, 0x61, 0xe3, 0x09, 0xbd, 0xda, 0x77,
+ 0x82, 0x58, 0xac, 0x99, 0xe2, 0xcb, 0x05, 0xb3, 0x26, 0xc9, 0xf7, 0x6c,
+ 0x19, 0x76, 0xf9, 0x0e, 0x20, 0xcb, 0x82, 0x40, 0x80, 0xc8, 0x05, 0x10,
+ 0x84, 0xe8, 0xcc, 0x08, 0xe2, 0xd0, 0x0f, 0x9d, 0x57, 0x57, 0xce, 0x14,
+ 0xd5, 0x03, 0xfd, 0xaa, 0xc5, 0x73, 0xd6, 0xcc, 0x68, 0xde, 0x28, 0x36,
+ 0x6b, 0xe3, 0x72, 0x6c, 0x20, 0xb0, 0x73, 0x15, 0xd9, 0x72, 0x41, 0x2e,
+ 0x54, 0x49, 0xb3, 0x4c, 0x53, 0x78, 0x2d, 0xe1, 0xf6, 0xc4, 0x27, 0x6f,
+ 0xc8, 0x43, 0xb3, 0x47, 0xc0, 0xdd, 0x73, 0x06, 0xf1, 0xf2, 0xb3, 0x43,
+ 0x85, 0x4b, 0x3a, 0x74, 0xed, 0xe3, 0x4b, 0x2f, 0xe1, 0x8c, 0x43, 0x06,
+ 0x95, 0xe8, 0xd8, 0x5c, 0x4c, 0xb6, 0x96, 0xf5, 0x3f, 0xae, 0x0f, 0xea,
+ 0x87, 0xf9, 0xb8, 0x9c, 0x69, 0x0e, 0x86, 0xc5, 0x77, 0xd0, 0x87, 0xb4,
+ 0x1c, 0x55, 0xca, 0x35, 0xdc, 0xd1, 0xb5, 0x67, 0xa1, 0x74, 0x61, 0x53,
+ 0x6e, 0xfc, 0x5c, 0xcf, 0x05, 0x9e, 0x22, 0x9d, 0x85, 0x45, 0x1d, 0xc9,
+ 0x8a, 0xc9, 0xac, 0x14, 0xaa, 0xa6, 0xfc, 0x6f, 0xac, 0x54, 0x7b, 0xea,
+ 0xe4, 0xfc, 0x2b, 0x97, 0x64, 0xec, 0x40, 0xad, 0x06, 0x23, 0xee, 0xf4,
+ 0x04, 0xf0, 0x02, 0x13, 0xa4, 0xb7, 0xf9, 0x0b, 0x09, 0xd0, 0x57, 0xb8,
+ 0x16, 0xd3, 0x10, 0x17, 0x77, 0x30, 0x43, 0xfd, 0x89, 0x6d, 0x8b, 0xec,
+ 0x02, 0xfc, 0xab, 0x76, 0xae, 0x8f, 0x76, 0x96, 0xde, 0xd0, 0x53, 0x5a,
+ 0x5d, 0x09, 0x32, 0x9a, 0x38, 0xd5, 0xa0, 0x24, 0xda, 0x92, 0x1b, 0xd6,
+ 0x46, 0x49, 0x42, 0x89, 0x0d, 0xa0, 0x81, 0xf8, 0xb4, 0xe4, 0x94, 0x3f,
+ 0x49, 0x88, 0x62, 0xeb, 0xa4, 0x25, 0x44, 0x8f, 0xe3, 0xfc, 0xd1, 0x86,
+ 0xa5, 0xa4, 0xee, 0x2e, 0xd3, 0x52, 0x00, 0xce, 0x54, 0x2b, 0x97, 0x99,
+ 0xf7, 0x1a, 0xd9, 0xf3, 0xa0, 0x09, 0x67, 0x62, 0x43, 0xe1, 0xae, 0x20,
+ 0x4b, 0x10, 0x28, 0x20, 0xf2, 0x80, 0xb2, 0xda, 0x35, 0xc1, 0xdf, 0xbf,
+ 0x91, 0x02, 0x40, 0xe6, 0x3c, 0x0b, 0x90, 0x89, 0x40, 0xb6, 0x7d, 0xbe,
+ 0x2d, 0x96, 0xb8, 0x46, 0x22, 0x57, 0xeb, 0x64, 0xff, 0xfc, 0xc8, 0x48,
+ 0xb6, 0x57, 0x05, 0x20, 0x24, 0x8a, 0x46, 0x73, 0xde, 0xb2, 0x42, 0x6a,
+ 0x0e, 0x15, 0x7a, 0x3e, 0xa8, 0xc3, 0x3b, 0xef, 0x4d, 0x22, 0x26, 0x89,
+ 0x11, 0xe0, 0xf4, 0x6a, 0x47, 0x72, 0x13, 0xc5, 0x5f, 0x05, 0xd7, 0x21,
+ 0x14, 0x03, 0x26, 0x29, 0xf2, 0x96, 0x98, 0xae, 0x4a, 0xc5, 0x5e, 0x3d,
+ 0x0b, 0xd8, 0xba, 0x0f, 0xba, 0xaa, 0x6b, 0x8d, 0x53, 0xed, 0xb2, 0x12,
+ 0xfe, 0xae, 0x58, 0x88, 0xd2, 0x57, 0xcb, 0x03, 0xea, 0xc8, 0xa9, 0x1f,
+ 0xb7, 0x1e, 0xfd, 0x1d, 0xf7, 0x0c, 0xc9, 0x22, 0x5d, 0xb9, 0x20, 0xb3,
+ 0xc1, 0xf6, 0x6c, 0xc8, 0x9e, 0x7a, 0xc2, 0x2f, 0x67, 0xe8, 0xa1, 0x74,
+ 0x36, 0x6c, 0xd4, 0x24, 0xfc, 0xa4, 0xb5, 0x64, 0x43, 0x89, 0x3a, 0x30,
+ 0x95, 0xb3, 0x4a, 0x54, 0x41, 0x91, 0xc3, 0x63, 0x02, 0xff, 0xb9, 0x61,
+ 0x01, 0xc0, 0xe7, 0x4f, 0x51, 0x33, 0xef, 0x1f, 0xed, 0x6c, 0xdd, 0x18,
+ 0xec, 0x97, 0xf4, 0xd1, 0x1b, 0x0b, 0x90, 0x86, 0x12, 0xe0, 0xd4, 0x11,
+ 0x58, 0x2a, 0xdc, 0xa7, 0xf4, 0x0b, 0x3e, 0x46, 0x00, 0x9c, 0x22, 0x4c,
+ 0xb6, 0xf0, 0x8c, 0xa4, 0xc8, 0x88, 0x3f, 0x10, 0xf6, 0xf1, 0x81, 0x43,
+ 0x8f, 0x7d, 0xd1, 0x78, 0xf0, 0xed, 0x96, 0x96, 0x0d, 0x25, 0x53, 0x0e,
+ 0xe5, 0xf7, 0xea, 0x81, 0xaf, 0xb3, 0x56, 0x9d, 0x51, 0x9b, 0x34, 0xd4,
+ 0x1b, 0xf4, 0xcc, 0x5a, 0xac, 0xcf, 0x66, 0x8e, 0xe1, 0xeb, 0x63, 0xb4,
+ 0xab, 0xc8, 0xaf, 0x73, 0x02, 0x93, 0xf0, 0x2e, 0x2a, 0x60, 0xf0, 0xd0,
+ 0xca, 0x76, 0xa0, 0x0a, 0x50, 0x94, 0x0c, 0x64, 0xf1, 0xa8, 0x90, 0x31,
+ 0x82, 0x78, 0x81, 0xdb, 0xbc, 0x56, 0x3f, 0xa4, 0xa1, 0xed, 0x09, 0x87,
+ 0x47, 0x34, 0x8c, 0x17, 0x90, 0x35, 0x13, 0x6f, 0x29, 0xb3, 0xc9, 0x75,
+ 0xc9, 0xe1, 0xb5, 0x66, 0xd1, 0xbc, 0x44, 0xcc, 0x5e, 0xf2, 0x9f, 0x42,
+ 0x03, 0xdf, 0xba, 0xfc, 0x3d, 0x22, 0x84, 0x21, 0x63, 0xff, 0x0d, 0x1d,
+ 0x41, 0x1c, 0xfd, 0x70, 0x71, 0xbe, 0x9f, 0x7c, 0x73, 0xb4, 0x7f, 0x78,
+ 0x74, 0x3e, 0xea, 0x5c, 0xfa, 0x12, 0x09, 0xc2, 0x12, 0x1a, 0xd9, 0x83,
+ 0x21, 0x1a, 0x2b, 0x2e, 0x80, 0x84, 0xf0, 0x2b, 0xd7, 0x33, 0xc4, 0x43,
+ 0x07, 0xc9, 0x9c, 0x0f, 0x52, 0x88, 0xd8, 0x71, 0x00, 0xa0, 0xd8, 0x1a,
+ 0xcc, 0xc6, 0xb6, 0x31, 0x31, 0x1c, 0x8a, 0xe2, 0x19, 0xd4, 0x7a, 0xee,
+ 0x27, 0xcf, 0x38, 0x88, 0x39, 0x77, 0x99, 0x4c, 0x4b, 0xcd, 0x0b, 0x6c,
+ 0xef, 0xdc, 0x37, 0x2e, 0x1d, 0xdb, 0x63, 0x5b, 0x72, 0xc9, 0x88, 0x01,
+ 0xb1, 0xf7, 0xc3, 0xc0, 0xf4, 0x3b, 0x30, 0x8b, 0x3f, 0x20, 0x5c, 0xc0,
+ 0x87, 0xac, 0xee, 0x75, 0xac, 0x81, 0xed, 0xee, 0xc1, 0xa3, 0xaf, 0xc2,
+ 0x93, 0xf4, 0x4d, 0xb4, 0x25, 0x3a, 0x5d, 0x54, 0x18, 0x37, 0xd0, 0x20,
+ 0x70, 0xa9, 0x7a, 0x42, 0xb2, 0x9c, 0xa0, 0x20, 0xd3, 0x45, 0x62, 0x95,
+ 0x9c, 0x9a, 0x29, 0xa1, 0x61, 0x18, 0x88, 0x4c, 0x01, 0xb2, 0x8e, 0x39,
+ 0x7b, 0x7c, 0xa9, 0xc3, 0x2e, 0xa2, 0x90, 0xb5, 0x66, 0x58, 0xf2, 0x90,
+ 0x7f, 0x3f, 0xc0, 0x17, 0x22, 0xe1, 0xf8, 0x75, 0xcb, 0x55, 0x2a, 0x76,
+ 0x51, 0x29, 0x87, 0x26, 0xcd, 0xd1, 0x18, 0x2c, 0xcd, 0x6b, 0x14, 0x3f,
+ 0x75, 0xa9, 0x95, 0x18, 0xe4, 0x5d, 0x0e, 0x08, 0x23, 0xa5, 0x1e, 0xa6,
+ 0x4e, 0x2e, 0xeb, 0x48, 0xef, 0xa8, 0xbc, 0xea, 0xa5, 0x05, 0xf9, 0xc4,
+ 0x8c, 0xb2, 0x51, 0x08, 0x24, 0xb7, 0xcf, 0x65, 0xc9, 0x37, 0x65, 0x8d,
+ 0xbb, 0x20, 0x7c, 0x9c, 0x2e, 0xf9, 0xd8, 0xf2, 0xe3, 0x0d, 0x71, 0x75,
+ 0x59, 0x60, 0x4e, 0xe0, 0xd8, 0x82, 0x7d, 0x9d, 0xed, 0x5f, 0x7c, 0x03,
+ 0x47, 0x2b, 0x48, 0xf8, 0x10, 0x80, 0x26, 0xea, 0x5e, 0x0b, 0xb3, 0xb3,
+ 0xac, 0x02, 0xc7, 0xf2, 0xaf, 0xe2, 0x09, 0xaa, 0x3c, 0x09, 0x47, 0x5e,
+ 0xce, 0x31, 0x49, 0x33, 0x2e, 0xa3, 0x09, 0x1e, 0xdd, 0x2a, 0x66, 0x86,
+ 0x28, 0x78, 0x9b, 0x7a, 0x67, 0x43, 0x2f, 0xd7, 0x39, 0x4f, 0x7d, 0x9d,
+ 0xe7, 0x04, 0xa2, 0x27, 0x61, 0x8e, 0x34, 0x1e, 0x1f, 0xed, 0x15, 0x5f,
+ 0x50, 0x22, 0x32, 0xfb, 0xa2, 0xa6, 0x65, 0x1c, 0xae, 0xcf, 0x3b, 0xd2,
+ 0x5f, 0xce, 0x1f, 0x86, 0x21, 0x3e, 0x4e, 0xf2, 0xd5, 0xb2, 0x69, 0xb3,
+ 0x95, 0x0e, 0xe6, 0xac, 0x95, 0x2c, 0xab, 0xb2, 0x6c, 0xbc, 0x31, 0x40,
+ 0xfa, 0x49, 0x1b, 0x39, 0xd1, 0x8c, 0xcb, 0xc8, 0x63, 0xa1, 0xa6, 0x0a,
+ 0x91, 0xbb, 0x7d, 0xc1, 0x30, 0x1d, 0xd7, 0xe5, 0x6c, 0xd9, 0x78, 0x81,
+ 0xd8, 0xbf, 0x6c, 0xcc, 0xde, 0xa0, 0x37, 0x8e, 0x87, 0x8a, 0x51, 0x49,
+ 0x55, 0x90, 0x8d, 0x10, 0x6e, 0x34, 0x7d, 0x23, 0x5e, 0xc2, 0xef, 0x58,
+ 0x95, 0x45, 0xbb, 0xde, 0x16, 0x62, 0xbe, 0x37, 0xd7, 0xd6, 0x46, 0xba,
+ 0xd9, 0x04, 0x11, 0x1a, 0x6e, 0xfa, 0xf7, 0x90, 0x26, 0x69, 0x0c, 0xec,
+ 0x37, 0x98, 0x98, 0x5f, 0x14, 0xa3, 0x2d, 0xe3, 0x3d, 0x05, 0x0b, 0xe7,
+ 0x3d, 0xce, 0xeb, 0xf6, 0xa4, 0xf0, 0x95, 0xf5, 0x5c, 0x68, 0xaa, 0xd9,
+ 0x45, 0xa9, 0xd8, 0xe7, 0xe2, 0xb9, 0x73, 0x04, 0xd1, 0x4a, 0x56, 0x8f,
+ 0xa2, 0xfa, 0xd2, 0x25, 0xa0, 0xc5, 0x59, 0x6d, 0x64, 0x2e, 0x0d, 0x72,
+ 0xeb, 0x7f, 0x6d, 0x25, 0xfd, 0x44, 0xea, 0x66, 0x47, 0x30, 0x88, 0xfe,
+ 0x2f, 0xc4, 0x60, 0x09, 0xa4, 0x2a, 0xb5, 0xd9, 0xc1, 0x21, 0x1d, 0x1a,
+ 0x15, 0xea, 0xba, 0x9a, 0x38, 0xea, 0x37, 0xd2, 0x41, 0x76, 0x47, 0xfa,
+ 0x8b, 0xea, 0x08, 0x82, 0xe6, 0xc1, 0xf5, 0x51, 0x2d, 0x3e, 0x12, 0xd0,
+ 0x30, 0x2e, 0xad, 0x55, 0x8f, 0x4a, 0x15, 0x72, 0xe1, 0x3e, 0x16, 0xeb,
+ 0x51, 0xb6, 0x46, 0x3d, 0xa8, 0x9c, 0xf0, 0x6e, 0xf5, 0xf6, 0x3a, 0xa9,
+ 0x4b, 0xfe, 0x57, 0xf3, 0x8f, 0x24, 0xc6, 0x4b, 0xc8, 0xdf, 0x2b, 0x87,
+ 0x26, 0x75, 0x44, 0x91, 0xe5, 0x24, 0xc1, 0xa7, 0x1c, 0x58, 0xa7, 0x9e,
+ 0x49, 0x1d, 0xa4, 0x4a, 0x01, 0xe4, 0xb8, 0x04, 0x1a, 0xa3, 0x00, 0x83,
+ 0x50, 0x50, 0x19, 0x21, 0xc6, 0x72, 0xfe, 0x36, 0x15, 0xba, 0x53, 0x4d,
+ 0x46, 0xaf, 0x54, 0xcd, 0xe8, 0xb0, 0x3b, 0xe5, 0x86, 0x2f, 0x77, 0x3f,
+ 0x72, 0xe4, 0xe1, 0xa4, 0xbb, 0x4b, 0x09, 0xc6, 0xcc, 0x89, 0x04, 0x3a,
+ 0x25, 0x29, 0x96, 0xc9, 0x71, 0x1c, 0x7e, 0x6c, 0x8a, 0x0b, 0xde, 0xbc,
+ 0xa2, 0x84, 0x0f, 0x31, 0x49, 0x09, 0xd4, 0x08, 0xec, 0x5f, 0xd7, 0xb9,
+ 0x84, 0x98, 0xf2, 0xaa, 0xb7, 0xcb, 0x10, 0xc2, 0xc2, 0x47, 0xd1, 0x05,
+ 0xce, 0xc1, 0x6a, 0x63, 0x20, 0x86, 0xe1, 0x81, 0x19, 0x5a, 0x30, 0x50,
+ 0xb9, 0x44, 0x8e, 0xfd, 0xf4, 0x72, 0x0e, 0xc8, 0xb0, 0x61, 0xcf, 0x9f,
+ 0xd8, 0xbb, 0xdf, 0x25, 0xc5, 0xb3, 0x16, 0x09, 0xe7, 0x92, 0x08, 0x92,
+ 0x1b, 0x5d, 0x28, 0xbb, 0x3b, 0x50, 0x4c, 0x39, 0x7c, 0x03, 0xf0, 0x9a,
+ 0xda, 0x42, 0xab, 0xe8, 0x95, 0xb7, 0xf8, 0x9b, 0x7d, 0x59, 0x25, 0x9b,
+ 0x7c, 0x2f, 0xde, 0x66, 0x96, 0x0b, 0x3d, 0xbf, 0x53, 0xab, 0xda, 0x16,
+ 0x27, 0x74, 0xd7, 0x4d, 0xb5, 0x9c, 0xb4, 0x10, 0xf4, 0x40, 0x11, 0x2d,
+ 0x2f, 0xbd, 0x5d, 0xe3, 0xd2, 0xd7, 0xed, 0x8f, 0xcf, 0x44, 0xbd, 0x67,
+ 0xed, 0x83, 0x46, 0xb6, 0x91, 0xb6, 0xf2, 0x5d, 0x6c, 0x7d, 0x44, 0xbf,
+ 0xdf, 0x4d, 0x4b, 0x65, 0x83, 0x33, 0x9b, 0x5c, 0xdf, 0xa9, 0xa6, 0x4d,
+ 0x89, 0x0a, 0xde, 0xdd, 0x2b, 0x82, 0x18, 0x04, 0x8f, 0x2a, 0x11, 0x6c,
+ 0x44, 0x88, 0x35, 0x64, 0xb2, 0x5c, 0xb3, 0xf8, 0x85, 0x66, 0x48, 0x03,
+ 0x89, 0x5a, 0x65, 0x47, 0xf0, 0x96, 0x59, 0x48, 0xad, 0xa8, 0x62, 0xab,
+ 0x09, 0xd5, 0x0e, 0x03, 0xb1, 0x13, 0xb2, 0x0a, 0x04, 0x25, 0x2b, 0x1f,
+ 0x0a, 0x96, 0x9b, 0xac, 0xdf, 0xd0, 0x56, 0xb8, 0x97, 0x1e, 0xba, 0xe2,
+ 0x44, 0x78, 0x37, 0x9e, 0x31, 0x52, 0x49, 0x40, 0x47, 0x87, 0x6a, 0x53,
+ 0x05, 0xcb, 0xc1, 0xda, 0x90, 0x66, 0xa3, 0x9b, 0x64, 0xd6, 0x55, 0xbb,
+ 0x30, 0x43, 0xa0, 0x19, 0xaf, 0xcf, 0xb2, 0xed, 0x75, 0xaf, 0x1c, 0xd2,
+ 0x06, 0xc7, 0xff, 0x97, 0xd0, 0x7e, 0x2c, 0x96, 0x20, 0x5b, 0x2f, 0x28,
+ 0xce, 0x6d, 0x33, 0x32, 0x14, 0xd3, 0xc4, 0x2f, 0x1d, 0xcc, 0xce, 0xab,
+ 0xdd, 0xe1, 0xce, 0xcb, 0xcf, 0x87, 0xdb, 0xc3, 0x9d, 0x6d, 0xe2, 0x2f,
+ 0x34, 0x14, 0x6f, 0x70, 0xbc, 0x2e, 0x91, 0xae, 0x5a, 0xef, 0x85, 0x7d,
+ 0xbe, 0x3f, 0xba, 0xf8, 0xfe, 0xf4, 0xfc, 0xdb, 0xe4, 0xf8, 0xfd, 0xc5,
+ 0xd1, 0xf9, 0xdb, 0xfd, 0x83, 0x4f, 0x05, 0x49, 0xf7, 0xcd, 0xd6, 0x5e,
+ 0x39, 0xe0, 0xcc, 0x2d, 0x4c, 0x68, 0x1b, 0x74, 0x6b, 0x96, 0x35, 0xd7,
+ 0xdb, 0x7b, 0x3b, 0x8f, 0x22, 0x29, 0x47, 0xcc, 0x83, 0xee, 0x7d, 0x9d,
+ 0xd4, 0x0e, 0x4d, 0x6a, 0x75, 0x2b, 0x16, 0x39, 0x71, 0xc4, 0x61, 0x56,
+ 0x36, 0x44, 0x17, 0x6c, 0x1e, 0xd5, 0x66, 0xf2, 0x71, 0x95, 0xaa, 0x61,
+ 0x6a, 0xcc, 0x70, 0xae, 0x9c, 0x69, 0x2b, 0x18, 0x30, 0x12, 0x8e, 0x2e,
+ 0x3c, 0x77, 0x8d, 0x4b, 0xef, 0x36, 0x62, 0x4e, 0x61, 0x74, 0xd6, 0x29,
+ 0x44, 0x3c, 0xe5, 0xca, 0x92, 0xc6, 0x46, 0xd4, 0x22, 0x05, 0x21, 0x19,
+ 0x0f, 0x70, 0x6a, 0x53, 0x46, 0x2c, 0x20, 0xc1, 0x5a, 0xe2, 0xc9, 0xe9,
+ 0x18, 0x6b, 0xbb, 0x7a, 0xb2, 0x1f, 0x49, 0xdb, 0x81, 0x46, 0xad, 0x35,
+ 0xc4, 0x19, 0x13, 0x6b, 0x99, 0x46, 0x0f, 0x64, 0x20, 0x38, 0x0d, 0xde,
+ 0x68, 0xb8, 0x2b, 0x08, 0x54, 0x0a, 0xd0, 0xdd, 0x06, 0xf6, 0xe5, 0x3b,
+ 0x0a, 0x69, 0x14, 0x2c, 0xff, 0x69, 0x25, 0x01, 0x6a, 0xbd, 0x6e, 0x61,
+ 0x08, 0x26, 0x5c, 0x01, 0xc8, 0x7f, 0x9d, 0x45, 0x6d, 0x04, 0x6a, 0x4e,
+ 0xab, 0xf4, 0x0e, 0x65, 0x2c, 0x72, 0x87, 0x08, 0xba, 0xd6, 0xae, 0x62,
+ 0x44, 0x82, 0x93, 0x5b, 0xf3, 0xe4, 0xec, 0xe8, 0xdd, 0x40, 0xeb, 0xaf,
+ 0x9a, 0xdf, 0xd9, 0x18, 0xa5, 0xf0, 0x8f, 0x9c, 0xe6, 0xb3, 0xc8, 0x0a,
+ 0x0d, 0xab, 0x01, 0x4f, 0x94, 0x38, 0x20, 0x7f, 0x02, 0x74, 0x68, 0x2c,
+ 0x40, 0xa4, 0x44, 0x8f, 0x6a, 0xf8, 0x25, 0xa7, 0x19, 0x76, 0x51, 0x33,
+ 0x69, 0x3f, 0x25, 0x76, 0x39, 0xd9, 0xb0, 0xf1, 0xba, 0xd4, 0x1f, 0x82,
+ 0x52, 0x11, 0x33, 0x60, 0xc3, 0x04, 0x4a, 0x4d, 0xc2, 0x3e, 0xfb, 0xf6,
+ 0x60, 0xf4, 0xc7, 0x9d, 0x5d, 0x19, 0xce, 0xe6, 0xd0, 0x01, 0xed, 0x06,
+ 0xf9, 0xf9, 0x60, 0xd7, 0xfe, 0x18, 0x35, 0xdb, 0x1a, 0x07, 0x1c, 0x9b,
+ 0xb1, 0x61, 0x73, 0x84, 0x36, 0x5b, 0x49, 0x42, 0x08, 0x02, 0x7b, 0xb0,
+ 0x22, 0xa6, 0xad, 0x8f, 0x4a, 0x2e, 0x11, 0x94, 0xd1, 0x91, 0x42, 0x36,
+ 0x8d, 0x8d, 0xfa, 0x4b, 0x0b, 0xfd, 0x88, 0x5b, 0x96, 0xd6, 0x90, 0x4e,
+ 0xee, 0x22, 0x5b, 0xba, 0x7b, 0x4e, 0xeb, 0xed, 0xbe, 0x25, 0x18, 0x57,
+ 0xb9, 0xd9, 0x15, 0xaf, 0xc7, 0x75, 0x83, 0x03, 0x20, 0x81, 0xec, 0x53,
+ 0x2d, 0x95, 0x55, 0xb8, 0xd2, 0x13, 0xf4, 0xf4, 0xa9, 0xd9, 0x28, 0x73,
+ 0xb2, 0x18, 0xc2, 0x81, 0x98, 0x42, 0x39, 0x23, 0xd5, 0xc5, 0x3e, 0x72,
+ 0x58, 0x51, 0x89, 0x8f, 0x05, 0x87, 0x94, 0xbe, 0x1f, 0x26, 0xdf, 0x64,
+ 0x05, 0xe5, 0xd0, 0x53, 0xf0, 0x9d, 0xa6, 0x61, 0x21, 0x44, 0x90, 0x6a,
+ 0xf5, 0xa1, 0x76, 0xd9, 0x49, 0x96, 0x0a, 0x64, 0xa6, 0xe1, 0x75, 0x35,
+ 0x6b, 0xb8, 0x5a, 0xb7, 0x27, 0xa5, 0x40, 0x3d, 0xc1, 0xf7, 0xb4, 0xb8,
+ 0x17, 0xf4, 0x00, 0x37, 0xb0, 0xd1, 0xc6, 0xbd, 0x04, 0x8c, 0x3e, 0x9a,
+ 0x93, 0x63, 0x0e, 0x5f, 0x93, 0x58, 0x95, 0xaf, 0x81, 0x02, 0x4d, 0xd6,
+ 0x42, 0xd6, 0xb8, 0x1c, 0x53, 0x99, 0x56, 0xd7, 0x64, 0xfa, 0xa8, 0xcd,
+ 0x75, 0x93, 0x16, 0x93, 0x87, 0xe1, 0xd4, 0xc8, 0xb2, 0x64, 0x3c, 0x1b,
+ 0x2e, 0x6f, 0xb6, 0xbc, 0x63, 0x4a, 0x2c, 0xff, 0x9a, 0xe1, 0x02, 0xda,
+ 0x86, 0x6f, 0xad, 0x0b, 0x1b, 0x22, 0x7b, 0xa5, 0xad, 0x33, 0x41, 0x24,
+ 0xa1, 0x89, 0xff, 0x7c, 0x3c, 0x57, 0x62, 0x60, 0x1d, 0x25, 0x16, 0x80,
+ 0x98, 0x5a, 0x18, 0x2e, 0xb2, 0xf9, 0x9e, 0x4d, 0x4c, 0x56, 0xfe, 0x20,
+ 0x95, 0x0c, 0xac, 0x62, 0xe1, 0x19, 0x69, 0x8b, 0xec, 0x6a, 0x26, 0x02,
+ 0x85, 0xaf, 0xba, 0x38, 0x40, 0xe9, 0x30, 0x1b, 0x84, 0x15, 0x1e, 0xa9,
+ 0x2a, 0x03, 0x89, 0xdd, 0xd0, 0x61, 0x23, 0xd1, 0xb5, 0xfc, 0x30, 0x0a,
+ 0xb3, 0xbb, 0x46, 0x04, 0x44, 0x04, 0x58, 0xc8, 0x24, 0x0c, 0x8b, 0x89,
+ 0x47, 0x83, 0x92, 0xc4, 0xfd, 0x44, 0x38, 0xad, 0xa0, 0x10, 0xa0, 0x8f,
+ 0x4b, 0x80, 0x34, 0x9c, 0x9f, 0x5a, 0x7b, 0x95, 0xcf, 0x8a, 0xf9, 0xfa,
+ 0xf6, 0x19, 0x59, 0xbc, 0x2f, 0x4e, 0x46, 0xea, 0x15, 0x29, 0xb2, 0x3b,
+ 0x8f, 0xb4, 0x18, 0x31, 0x5f, 0xe8, 0x8f, 0x0c, 0x40, 0x8c, 0x78, 0x0c,
+ 0xe0, 0x03, 0x8c, 0x84, 0xb9, 0x82, 0x73, 0x93, 0xb9, 0x3c, 0x08, 0x5d,
+ 0x04, 0x89, 0x28, 0xa6, 0xa1, 0x68, 0x89, 0x28, 0x16, 0x86, 0x2c, 0xe8,
+ 0x0b, 0x41, 0xeb, 0x19, 0x61, 0xe9, 0x59, 0x3f, 0x19, 0xec, 0x02, 0x4a,
+ 0x67, 0xa7, 0xbd, 0x88, 0x69, 0xc3, 0x28, 0x7e, 0xd4, 0x86, 0x69, 0x49,
+ 0x5b, 0x11, 0x76, 0xb0, 0x21, 0x24, 0x7d, 0x6b, 0xde, 0xa7, 0x7f, 0x76,
+ 0x65, 0x42, 0xb7, 0x3b, 0x08, 0xde, 0x66, 0x58, 0xc9, 0xd9, 0x43, 0x28,
+ 0x32, 0xec, 0x3e, 0xba, 0xab, 0x48, 0x93, 0xb8, 0xcb, 0x2d, 0xbe, 0x33,
+ 0x63, 0xfd, 0xc3, 0x14, 0x2a, 0x88, 0x9d, 0x3a, 0x00, 0xb3, 0x84, 0x62,
+ 0xe4, 0x2e, 0x92, 0xdb, 0x5d, 0xf5, 0x35, 0xd3, 0x37, 0xba, 0x6e, 0x6c,
+ 0xac, 0x77, 0x4c, 0x24, 0xc8, 0x60, 0xa4, 0x80, 0x37, 0x8f, 0x6a, 0x29,
+ 0x01, 0xca, 0xd0, 0xac, 0xe1, 0x22, 0x2d, 0x2e, 0x53, 0x16, 0x62, 0x56,
+ 0xe0, 0xec, 0xf7, 0xb4, 0xe0, 0xcd, 0x30, 0x72, 0xb0, 0x0b, 0x73, 0x42,
+ 0x10, 0xb8, 0x17, 0x1c, 0x79, 0x5c, 0xd8, 0x9c, 0x09, 0x31, 0xe5, 0x03,
+ 0x41, 0x0f, 0xdb, 0x7f, 0x9d, 0xb3, 0x61, 0x02, 0x61, 0xa7, 0xb8, 0xce,
+ 0xcd, 0xc9, 0x5f, 0x4f, 0xcc, 0x61, 0x5a, 0x12, 0xc7, 0x6f, 0x6c, 0xbd,
+ 0xaa, 0x11, 0x23, 0x6f, 0xae, 0xfb, 0x6c, 0x6e, 0xf0, 0x05, 0x4d, 0xa5,
+ 0x5e, 0x77, 0x73, 0x17, 0x04, 0xf2, 0xf6, 0x44, 0xc4, 0xcf, 0xa1, 0x15,
+ 0x9a, 0xce, 0x2a, 0xad, 0x43, 0xbd, 0x7e, 0x74, 0x4f, 0x32, 0xce, 0xba,
+ 0xf4, 0xc4, 0x5f, 0x73, 0x7a, 0x3f, 0xd6, 0xe8, 0xec, 0xf8, 0x3d, 0x97,
+ 0x56, 0xb6, 0x67, 0x21, 0x23, 0x64, 0xc4, 0x35, 0xae, 0x0a, 0x8e, 0xf1,
+ 0xa4, 0x02, 0x21, 0x91, 0xb0, 0xe1, 0x88, 0x68, 0x86, 0x68, 0x3c, 0x97,
+ 0xbe, 0xce, 0x97, 0xdc, 0xfb, 0x3a, 0xdd, 0x73, 0x75, 0x3d, 0x5b, 0xef,
+ 0x94, 0x0b, 0xb5, 0x7b, 0xd2, 0xb9, 0x50, 0xac, 0x45, 0x6a, 0x32, 0xf5,
+ 0x0b, 0xa0, 0x4b, 0x2b, 0x2d, 0x3e, 0xd7, 0xef, 0x24, 0x3d, 0xfa, 0xa6,
+ 0xf0, 0x3f, 0x26, 0xc3, 0x2d, 0xd3, 0x61, 0xbd, 0xa5, 0x2f, 0x2e, 0x6e,
+ 0x26, 0xb5, 0xb9, 0xe1, 0x28, 0xc3, 0xf7, 0x47, 0x0b, 0x13, 0x4f, 0x23,
+ 0x9e, 0xfe, 0x9c, 0x0c, 0x26, 0x33, 0xcc, 0x2f, 0x41, 0x6d, 0xe2, 0x1f,
+ 0xcd, 0xce, 0xd3, 0x13, 0x3f, 0xdb, 0x3d, 0x7c, 0x9b, 0xd3, 0x79, 0xbb,
+ 0xef, 0xeb, 0xd4, 0x4f, 0x59, 0x61, 0x60, 0xf8, 0xd9, 0x64, 0x7f, 0x7a,
+ 0x4b, 0xf9, 0x77, 0x53, 0xf9, 0x93, 0xe6, 0x73, 0x54, 0xa0, 0xa4, 0x23,
+ 0x66, 0x9a, 0x8e, 0xb9, 0x8a, 0xf3, 0x77, 0xb9, 0x51, 0x3a, 0x0e, 0x3a,
+ 0xf2, 0x05, 0xa5, 0x02, 0xd2, 0x00, 0xf1, 0x96, 0xf7, 0xa5, 0xe6, 0x75,
+ 0xf4, 0x25, 0x7d, 0xc1, 0x45, 0xfe, 0x11, 0x77, 0xa6, 0xad, 0x1b, 0x26,
+ 0x5f, 0x91, 0x8f, 0xb3, 0xca, 0x3c, 0x70, 0x56, 0xb9, 0xf8, 0xb8, 0xf4,
+ 0x19, 0x6d, 0x46, 0xca, 0x50, 0x14, 0x43, 0x3b, 0x93, 0x20, 0x1d, 0xc6,
+ 0xce, 0xc9, 0x7e, 0xd3, 0x9e, 0x1c, 0xc6, 0xa5, 0xd9, 0xed, 0x66, 0x2a,
+ 0x9a, 0x3a, 0x91, 0x04, 0x53, 0xf1, 0x60, 0x23, 0x79, 0x84, 0x7c, 0x61,
+ 0x4e, 0x33, 0xcd, 0xf1, 0x2f, 0x7d, 0x60, 0x15, 0xb5, 0x1c, 0xa3, 0x29,
+ 0x95, 0x08, 0x2c, 0x49, 0xe0, 0x0e, 0x77, 0xa3, 0x3e, 0xb8, 0x36, 0xac,
+ 0x39, 0xb3, 0x43, 0x1d, 0xb1, 0x49, 0x4f, 0x87, 0x38, 0xa2, 0x3b, 0x4a,
+ 0x37, 0xc1, 0x7e, 0xa9, 0x89, 0x92, 0x90, 0x42, 0xb7, 0x98, 0x77, 0x59,
+ 0xda, 0xe5, 0xd5, 0x6d, 0x4f, 0x81, 0xf2, 0x1b, 0x47, 0x1f, 0xde, 0x51,
+ 0x45, 0x0e, 0x54, 0xfa, 0xbd, 0x38, 0xdf, 0x7f, 0x3f, 0x7a, 0xcb, 0xa6,
+ 0xf1, 0x8b, 0xd2, 0xd5, 0x10, 0x16, 0x7b, 0x90, 0xf5, 0x1f, 0x5b, 0xc4,
+ 0xb8, 0x3b, 0x2e, 0x13, 0xa1, 0xa1, 0xf5, 0x52, 0x5d, 0xb8, 0xdf, 0x85,
+ 0xc3, 0xe7, 0xea, 0xc4, 0xb4, 0x1a, 0x34, 0xb4, 0x8d, 0xd1, 0xa6, 0x15,
+ 0x84, 0x6a, 0xbf, 0x0e, 0x96, 0xab, 0xf0, 0xad, 0xc0, 0xcd, 0xf2, 0x10,
+ 0x2d, 0xcb, 0x81, 0x0e, 0x46, 0x3f, 0xe5, 0xbb, 0x77, 0x25, 0x56, 0xe8,
+ 0x81, 0x51, 0x15, 0x07, 0x52, 0x60, 0xc5, 0xab, 0xfa, 0x65, 0xcd, 0xa9,
+ 0x7c, 0xf7, 0x0a, 0xaa, 0x9f, 0x6d, 0xdc, 0x4f, 0x01, 0xd5, 0xa6, 0x37,
+ 0xfe, 0x75, 0x67, 0x33, 0xde, 0xfc, 0xc5, 0x2f, 0x6d, 0x3e, 0x3e, 0x76,
+ 0xd5, 0xcd, 0x5c, 0x76, 0xd1, 0xc6, 0xbf, 0xee, 0x6e, 0x3e, 0x3a, 0x23,
+ 0x3f, 0x41, 0xd2, 0xf5, 0x69, 0xde, 0xa0, 0xc1, 0x26, 0x6f, 0xb4, 0x5e,
+ 0xbc, 0xc8, 0x4c, 0x36, 0x42, 0xc7, 0x83, 0x03, 0x6e, 0x61, 0x77, 0x50,
+ 0x04, 0xb7, 0x95, 0xd4, 0x9d, 0xe3, 0x4d, 0x12, 0x4d, 0x8e, 0xff, 0xe7,
+ 0x91, 0x8f, 0xf2, 0x58, 0xac, 0x37, 0xfe, 0x15, 0x45, 0x40, 0x01, 0x75,
+ 0x39, 0x44, 0xdf, 0xbb, 0x8f, 0xf4, 0xed, 0x66, 0xe7, 0x99, 0x25, 0xc8,
+ 0x8b, 0x4d, 0x61, 0x70, 0x0a, 0x56, 0x2d, 0xfd, 0xac, 0xb9, 0xca, 0xd4,
+ 0xab, 0xfb, 0xbb, 0x38, 0x7e, 0x77, 0x44, 0xa0, 0xd6, 0x87, 0xc7, 0x84,
+ 0x43, 0x37, 0x12, 0x24, 0x48, 0xb5, 0x40, 0x58, 0xc0, 0x5c, 0xbf, 0x4c,
+ 0x0a, 0xbb, 0x77, 0x6d, 0xb4, 0x99, 0xe5, 0x1c, 0x76, 0x27, 0xa8, 0x6b,
+ 0x09, 0x87, 0xae, 0x35, 0xe9, 0xf2, 0xf8, 0x72, 0xf0, 0xae, 0x9c, 0x42,
+ 0x4b, 0x1e, 0x8c, 0x10, 0x2a, 0x68, 0xde, 0x32, 0x1f, 0x7e, 0x28, 0xe6,
+ 0xad, 0x8f, 0x87, 0x91, 0xa4, 0xdd, 0xb5, 0x55, 0xb5, 0x64, 0xfe, 0xb1,
+ 0x35, 0x18, 0xa0, 0x34, 0x3c, 0x87, 0x75, 0x89, 0x73, 0xa7, 0x05, 0xd5,
+ 0xa1, 0xac, 0xc5, 0x2c, 0x50, 0x3e, 0x7b, 0xe0, 0x40, 0x84, 0xd4, 0x85,
+ 0x8f, 0xb9, 0x44, 0xce, 0x2b, 0x4a, 0x26, 0x73, 0x26, 0x3e, 0x36, 0xe2,
+ 0xad, 0xf9, 0xd8, 0xa2, 0x50, 0xa4, 0xb2, 0x3b, 0x17, 0xff, 0x24, 0x65,
+ 0x6e, 0xcb, 0xc5, 0x03, 0x66, 0x79, 0xd7, 0x0a, 0xad, 0x88, 0xfa, 0x57,
+ 0xff, 0xc1, 0xef, 0xb4, 0xaa, 0x27, 0x09, 0x04, 0xb4, 0x47, 0x81, 0xf2,
+ 0x89, 0x14, 0x1b, 0x3a, 0xad, 0xbc, 0xeb, 0x4a, 0x86, 0xad, 0x15, 0xc5,
+ 0x3c, 0xdc, 0x51, 0x0f, 0x26, 0xb5, 0x3d, 0x4e, 0x1f, 0xa3, 0xb5, 0xa4,
+ 0x2c, 0xd8, 0xc3, 0xd2, 0x3a, 0xc7, 0x0c, 0xdb, 0x59, 0xb4, 0x0b, 0xc9,
+ 0x66, 0x89, 0xe6, 0x7b, 0x73, 0x3a, 0xff, 0xfa, 0x60, 0x1d, 0x65, 0x13,
+ 0xf2, 0x22, 0x32, 0x99, 0xc1, 0x2f, 0x9f, 0x4d, 0xe0, 0x7a, 0x4d, 0x7a,
+ 0x97, 0x84, 0x89, 0x41, 0x7e, 0xac, 0x1e, 0x0f, 0x80, 0x21, 0x63, 0x98,
+ 0xb8, 0xcc, 0x05, 0x41, 0x7c, 0x4d, 0x15, 0x49, 0x56, 0xaa, 0x6d, 0x64,
+ 0xac, 0x35, 0x92, 0xb3, 0x55, 0x92, 0x18, 0xe9, 0x72, 0x31, 0x45, 0x50,
+ 0x06, 0x87, 0xa3, 0xfe, 0x3b, 0x61, 0x56, 0x57, 0x0f, 0xc9, 0xce, 0x6e,
+ 0x3f, 0xd9, 0xdd, 0xde, 0xd9, 0x8d, 0xcc, 0xa1, 0xf7, 0xef, 0x14, 0x14,
+ 0xb5, 0x8b, 0xaf, 0x7b, 0x9f, 0x3a, 0x0b, 0x97, 0xda, 0x80, 0x9b, 0x44,
+ 0x92, 0x80, 0x0d, 0xf3, 0x21, 0xff, 0x2c, 0x70, 0x92, 0x51, 0x5d, 0x16,
+ 0xc8, 0x76, 0xb8, 0xb6, 0xd8, 0x48, 0xa8, 0x65, 0x0d, 0x6d, 0xc5, 0x2b,
+ 0x7a, 0x62, 0x4d, 0x0a, 0x7c, 0x22, 0xf2, 0xc5, 0x5a, 0x4a, 0xd3, 0x0a,
+ 0x35, 0x1b, 0xdb, 0x7b, 0x94, 0x37, 0xba, 0x2d, 0x14, 0x5a, 0x43, 0x7b,
+ 0x63, 0xe8, 0xfd, 0xf0, 0xf8, 0xe0, 0x42, 0xa1, 0x0f, 0x2f, 0x49, 0x78,
+ 0xaa, 0x1e, 0x3e, 0xad, 0x00, 0xde, 0xa3, 0xcf, 0x4c, 0xf7, 0xae, 0x33,
+ 0x23, 0x46, 0x17, 0xe3, 0xe5, 0xd5, 0xde, 0xdf, 0xd2, 0xea, 0xaa, 0x2c,
+ 0x9e, 0x7a, 0x7e, 0x8a, 0xdc, 0xb2, 0x3d, 0xc3, 0xa1, 0x76, 0x5e, 0xed,
+ 0x3c, 0xe3, 0xc4, 0x85, 0x9c, 0xaa, 0x65, 0x82, 0x41, 0xac, 0xcf, 0xd7,
+ 0x19, 0x6b, 0x03, 0x19, 0x13, 0x16, 0x60, 0xa3, 0x98, 0xae, 0xf3, 0x75,
+ 0x9f, 0xfa, 0xcf, 0x4e, 0xe5, 0x59, 0xce, 0x42, 0x5f, 0x5f, 0xe3, 0xd2,
+ 0x25, 0xeb, 0x94, 0xb1, 0xb9, 0x5c, 0xac, 0xb7, 0x11, 0xdc, 0x9f, 0x98,
+ 0x2b, 0x75, 0x61, 0xeb, 0xfd, 0x1d, 0x58, 0x5c, 0x7a, 0x24, 0x13, 0x55,
+ 0x59, 0x7a, 0xe3, 0xca, 0xcd, 0x3a, 0x20, 0x0e, 0x75, 0x79, 0x9c, 0xbf,
+ 0x3d, 0x60, 0x30, 0x53, 0x4d, 0x9d, 0xc2, 0x52, 0x27, 0xd6, 0x34, 0xb5,
+ 0x49, 0xa3, 0x7c, 0xa2, 0x7f, 0xca, 0x6d, 0xd8, 0x9b, 0x8e, 0x3f, 0xe1,
+ 0x21, 0x73, 0xee, 0x18, 0x37, 0x6e, 0xbf, 0x5d, 0x19, 0x87, 0x14, 0x35,
+ 0x94, 0xf7, 0xd0, 0xba, 0xb2, 0x1b, 0x5c, 0xfb, 0x93, 0x3d, 0x0e, 0x34,
+ 0x34, 0xad, 0xd8, 0xab, 0xd6, 0x1d, 0x33, 0x6e, 0x2a, 0xac, 0x79, 0xb8,
+ 0x7f, 0xe6, 0x29, 0xba, 0x50, 0x24, 0x9d, 0x51, 0x8f, 0x9e, 0x23, 0x45,
+ 0x07, 0xa5, 0xab, 0xd9, 0xf6, 0xf7, 0xd0, 0x77, 0x2a, 0x4a, 0x03, 0x3e,
+ 0x49, 0xb2, 0x11, 0x02, 0xe4, 0x4b, 0xb9, 0x4f, 0x60, 0x7f, 0x42, 0xb1,
+ 0x81, 0xd9, 0x34, 0x85, 0x23, 0x54, 0x6e, 0x21, 0xc8, 0x5c, 0x68, 0x2b,
+ 0x97, 0x68, 0x28, 0xb3, 0x37, 0xf7, 0x89, 0x24, 0x71, 0x48, 0xb6, 0x8a,
+ 0x94, 0x03, 0xc1, 0x63, 0x94, 0xa0, 0xfc, 0xa0, 0x13, 0x60, 0xfe, 0x6c,
+ 0x06, 0x9f, 0xd6, 0x37, 0x86, 0x95, 0xb2, 0x03, 0xdf, 0xf4, 0x9e, 0x8b,
+ 0x0b, 0x9c, 0x8c, 0x3e, 0x39, 0x07, 0xd2, 0x90, 0xf9, 0x09, 0x90, 0x48,
+ 0xad, 0x0d, 0xe3, 0x2b, 0x88, 0x34, 0xce, 0x59, 0x9d, 0x31, 0x80, 0x61,
+ 0x72, 0x71, 0x57, 0xb2, 0x8a, 0x51, 0x6b, 0x78, 0x2d, 0x87, 0xa2, 0xd6,
+ 0xcb, 0x9c, 0xa5, 0x48, 0xb3, 0x79, 0xe0, 0x07, 0x5e, 0xe5, 0xce, 0x9e,
+ 0xb5, 0x7c, 0x1d, 0x5a, 0xbf, 0xe7, 0xe8, 0xf0, 0xdb, 0x84, 0x52, 0xeb,
+ 0xa9, 0x8f, 0x03, 0x82, 0xdb, 0xa7, 0x10, 0x86, 0x39, 0xb4, 0xbf, 0xaf,
+ 0x97, 0x74, 0xde, 0x0f, 0xae, 0xd3, 0x05, 0x29, 0x40, 0x3b, 0xdb, 0x64,
+ 0x2e, 0xf9, 0x5e, 0x93, 0xf4, 0xe8, 0xa0, 0x6a, 0x61, 0xf0, 0xba, 0xe7,
+ 0x59, 0x52, 0xa6, 0x54, 0xd7, 0x9b, 0x34, 0xa0, 0xb6, 0x91, 0xd6, 0x5c,
+ 0x9f, 0xf5, 0x16, 0x83, 0xec, 0xd7, 0x86, 0x34, 0xaa, 0x7a, 0x7a, 0xb3,
+ 0x35, 0x31, 0x3f, 0x9e, 0x6d, 0x6f, 0x01, 0x53, 0xb3, 0x81, 0x4d, 0x93,
+ 0x68, 0x72, 0x77, 0xf7, 0xc5, 0x8b, 0x7e, 0xd2, 0x23, 0x2b, 0xa3, 0x76,
+ 0x40, 0x47, 0xc2, 0x9c, 0xac, 0x5e, 0xac, 0x84, 0xe9, 0x56, 0x75, 0x39,
+ 0xa1, 0xff, 0xd1, 0x6b, 0x5a, 0x88, 0xf0, 0x42, 0xb2, 0x6e, 0xb0, 0x0e,
+ 0x85, 0x0f, 0x93, 0xc3, 0x64, 0x45, 0xdf, 0x1d, 0x5b, 0x3b, 0x12, 0x39,
+ 0x8d, 0x16, 0x59, 0xb9, 0x50, 0xef, 0xf0, 0x5c, 0xca, 0x77, 0xa0, 0x7b,
+ 0xcf, 0xa5, 0x06, 0x7f, 0x3e, 0x87, 0xc3, 0x09, 0x1e, 0x42, 0xbd, 0x1c,
+ 0x0f, 0x24, 0x31, 0x98, 0xb5, 0xca, 0xdc, 0x9c, 0x5c, 0xf3, 0xe7, 0x4c,
+ 0xcd, 0xf5, 0x01, 0x47, 0xfe, 0x2a, 0xe9, 0x09, 0x6d, 0xd1, 0x3f, 0x43,
+ 0x38, 0x77, 0xb3, 0x09, 0x4d, 0xa3, 0x7c, 0x23, 0x7f, 0xfc, 0xdb, 0xbf,
+ 0x99, 0x66, 0xff, 0x8d, 0x5a, 0x79, 0xf3, 0xaf, 0x75, 0x73, 0xed, 0x3d,
+ 0xd3, 0x13, 0x82, 0x3f, 0x76, 0xae, 0x6d, 0x84, 0xab, 0x01, 0x71, 0x16,
+ 0xf9, 0x6b, 0xef, 0x4e, 0x84, 0x23, 0xf7, 0xbd, 0xf9, 0xe5, 0xc8, 0x2c,
+ 0x64, 0x23, 0xa9, 0x8d, 0x16, 0xf9, 0x8a, 0xdc, 0xce, 0x19, 0x65, 0xa4,
+ 0x9b, 0x8b, 0x04, 0x80, 0x82, 0x9b, 0x2a, 0x62, 0x1c, 0xbd, 0xff, 0xee,
+ 0xf8, 0xfc, 0xf4, 0xfd, 0xbb, 0xa3, 0xf7, 0x17, 0xc9, 0x77, 0xfb, 0xe7,
+ 0xc7, 0xfb, 0x5f, 0x9d, 0x48, 0xe2, 0x3b, 0x4d, 0x81, 0x82, 0x7c, 0x58,
+ 0xf6, 0xee, 0x00, 0xc2, 0x7a, 0x89, 0x48, 0xd1, 0xd2, 0x1e, 0x9d, 0x4a,
+ 0xb4, 0x1f, 0x05, 0x61, 0x1c, 0x9a, 0xc8, 0x47, 0x54, 0x29, 0xea, 0x93,
+ 0xf0, 0xf9, 0x51, 0x0b, 0x16, 0x91, 0xf2, 0xf4, 0xe0, 0xa5, 0x52, 0x53,
+ 0xfc, 0x11, 0x51, 0xa9, 0xf2, 0x27, 0x57, 0xc2, 0xce, 0xd6, 0xbe, 0xf8,
+ 0x9a, 0xb3, 0xf1, 0xb5, 0x10, 0x88, 0xbe, 0x2a, 0x99, 0x61, 0xb0, 0xbb,
+ 0xd9, 0x31, 0xec, 0x9f, 0x9c, 0xb8, 0xae, 0x1e, 0xaf, 0x11, 0x23, 0x48,
+ 0x4c, 0x9c, 0xbc, 0x85, 0x46, 0xc9, 0x31, 0x78, 0x55, 0x3a, 0xb8, 0xf4,
+ 0xe2, 0xc1, 0x47, 0x46, 0xa7, 0xce, 0xcc, 0x76, 0x6c, 0x30, 0x84, 0x06,
+ 0x79, 0x89, 0xcd, 0x01, 0xca, 0xeb, 0x9b, 0x7e, 0xb2, 0xfe, 0xaf, 0xeb,
+ 0x9c, 0x54, 0x97, 0x01, 0x37, 0x98, 0x2b, 0xd0, 0x6c, 0xba, 0x41, 0xbd,
+ 0x3f, 0x75, 0x63, 0x12, 0xc7, 0xa7, 0x1d, 0x80, 0x7d, 0xd1, 0xb9, 0xad,
+ 0x6b, 0x95, 0x67, 0x10, 0x2f, 0xea, 0x1e, 0x97, 0x32, 0x0d, 0x16, 0x19,
+ 0x40, 0x68, 0x94, 0x1c, 0x5b, 0xd1, 0x77, 0xa1, 0xb5, 0xa5, 0x13, 0x0f,
+ 0x1e, 0x1a, 0x73, 0x2d, 0xc8, 0xd4, 0x61, 0x4b, 0x67, 0xa9, 0x35, 0xd0,
+ 0x2c, 0x35, 0xd9, 0xf4, 0xc4, 0x9d, 0xb8, 0xac, 0x85, 0x83, 0x82, 0xaa,
+ 0xee, 0xb7, 0xb4, 0x12, 0x0d, 0x7c, 0x8c, 0x94, 0x0f, 0x50, 0xe5, 0x53,
+ 0x81, 0x1b, 0x8c, 0x52, 0xc5, 0x10, 0xae, 0xa9, 0xf3, 0x03, 0xa0, 0xb3,
+ 0x17, 0x54, 0x4b, 0xd0, 0x55, 0xba, 0x40, 0xec, 0xb0, 0xe1, 0x22, 0x15,
+ 0x25, 0xe4, 0x15, 0x22, 0x84, 0x20, 0x1e, 0x17, 0x32, 0x7a, 0x7a, 0x55,
+ 0xaa, 0xfc, 0x9d, 0x5a, 0xa7, 0xb9, 0xad, 0x07, 0xe6, 0xc9, 0xf4, 0x16,
+ 0x43, 0xcc, 0x9a, 0x2c, 0xe1, 0x5e, 0x57, 0x07, 0x01, 0x85, 0x97, 0xd1,
+ 0x96, 0x6b, 0xd1, 0xde, 0xda, 0xcb, 0xd2, 0x76, 0xd9, 0x0b, 0xc4, 0x4b,
+ 0x38, 0x48, 0x5f, 0x41, 0xbd, 0x00, 0xa4, 0xa6, 0x59, 0xdd, 0x08, 0x74,
+ 0xc4, 0xb0, 0xe8, 0x41, 0x34, 0x29, 0x31, 0xab, 0x68, 0x52, 0x6d, 0xd7,
+ 0xe6, 0xf4, 0xcc, 0x28, 0x81, 0x4c, 0x39, 0x51, 0x9a, 0x8c, 0xf3, 0x2b,
+ 0x46, 0x07, 0xa0, 0x54, 0x74, 0xa2, 0x12, 0x80, 0xbd, 0x19, 0xc5, 0x9e,
+ 0xb6, 0x0a, 0x50, 0x6e, 0x90, 0xdd, 0xaf, 0xcb, 0x99, 0x8f, 0x37, 0xa6,
+ 0x33, 0xa9, 0xa5, 0xd2, 0x99, 0x9a, 0x3e, 0xe1, 0xfa, 0x58, 0xd2, 0x3a,
+ 0x6a, 0x34, 0x9a, 0x00, 0x95, 0x4b, 0x6c, 0x1e, 0xd9, 0xd4, 0x81, 0x9a,
+ 0x58, 0x20, 0x13, 0x48, 0xb3, 0xaa, 0xb1, 0x0e, 0x1a, 0xb7, 0x4c, 0xdc,
+ 0x02, 0x76, 0x34, 0x2a, 0x5c, 0xb8, 0x61, 0x91, 0xc6, 0xa9, 0x95, 0x09,
+ 0x63, 0xb5, 0x12, 0xd1, 0xb3, 0x47, 0xb9, 0x5d, 0xae, 0x47, 0x36, 0x4b,
+ 0x50, 0xb4, 0x0c, 0x4d, 0xd0, 0xa0, 0xcd, 0x4a, 0x6d, 0x78, 0x8c, 0xa7,
+ 0x30, 0x24, 0xc2, 0x8f, 0xb1, 0x02, 0x29, 0x7f, 0x0d, 0x6c, 0xa5, 0x31,
+ 0xf1, 0x3b, 0x6f, 0xba, 0xb8, 0x03, 0x96, 0x02, 0x88, 0x5a, 0x27, 0x52,
+ 0x1b, 0x11, 0x1e, 0x7a, 0x2a, 0xe0, 0x08, 0x68, 0xa8, 0x96, 0xed, 0x31,
+ 0xd1, 0x7c, 0x9b, 0xd9, 0xcc, 0x83, 0x1a, 0x67, 0x73, 0x44, 0x1a, 0xc8,
+ 0x1e, 0xe4, 0x1c, 0xe2, 0x34, 0x54, 0x89, 0xfc, 0x61, 0x58, 0x62, 0x6f,
+ 0x22, 0x12, 0x53, 0x4e, 0xd2, 0x59, 0xc7, 0xa4, 0xe9, 0x31, 0x34, 0xf5,
+ 0x8e, 0xfb, 0x17, 0x93, 0x54, 0xbb, 0xc8, 0xd3, 0x39, 0xcb, 0x8e, 0x8e,
+ 0xfa, 0xe6, 0x0f, 0x1c, 0x75, 0xb8, 0xb6, 0x76, 0xf0, 0x61, 0x74, 0x71,
+ 0xfa, 0x2e, 0x39, 0xfd, 0x70, 0x71, 0xf6, 0xe1, 0x42, 0x6e, 0xae, 0x31,
+ 0xc7, 0x6c, 0x73, 0xe4, 0x02, 0x0b, 0x01, 0xba, 0x99, 0x73, 0xf1, 0xef,
+ 0x23, 0xc4, 0xa4, 0x04, 0xc0, 0xa0, 0x87, 0x2d, 0x64, 0x73, 0xb2, 0x80,
+ 0xba, 0xc5, 0xc8, 0xc5, 0x58, 0xf2, 0x3b, 0xb3, 0xe4, 0xc8, 0xa7, 0x85,
+ 0x21, 0x4f, 0x53, 0xbc, 0xa0, 0xf6, 0xe8, 0x59, 0x6b, 0x57, 0x92, 0xe9,
+ 0x54, 0xc4, 0x84, 0x73, 0xbe, 0x8d, 0xe5, 0xe4, 0xe2, 0xa8, 0xd4, 0xb6,
+ 0xe3, 0x4c, 0x3f, 0x7e, 0x48, 0x27, 0x82, 0x99, 0x26, 0x8d, 0x1a, 0xa0,
+ 0x35, 0xaa, 0x16, 0xa1, 0x46, 0xed, 0xc4, 0x42, 0x3f, 0xbf, 0xb1, 0x29,
+ 0xcd, 0x0c, 0xaf, 0x6d, 0x44, 0x3c, 0x45, 0x11, 0x21, 0x12, 0x90, 0x03,
+ 0x28, 0x28, 0xe4, 0x8e, 0x35, 0x06, 0xa3, 0x07, 0x92, 0xcb, 0x22, 0xb8,
+ 0x65, 0xef, 0x92, 0xf5, 0xef, 0x33, 0xbf, 0xc1, 0x3f, 0xfd, 0x07, 0xa5,
+ 0x6d, 0x7e, 0xd4, 0x4f, 0xfe, 0x8b, 0xbb, 0xfc, 0xa9, 0x58, 0x47, 0x00,
+ 0x5d, 0xdb, 0x53, 0xfe, 0xed, 0xd1, 0xf9, 0x57, 0x47, 0xe7, 0xa7, 0x23,
+ 0xf0, 0x03, 0x35, 0x77, 0x85, 0xb4, 0x7e, 0x93, 0x55, 0xe3, 0xac, 0x2a,
+ 0xa5, 0xca, 0x95, 0xfe, 0xf5, 0x62, 0xeb, 0xeb, 0xd1, 0x68, 0xff, 0xec,
+ 0xd8, 0xd6, 0x91, 0xb1, 0x09, 0x64, 0xac, 0x22, 0x15, 0x9c, 0xe2, 0x48,
+ 0xf3, 0xd7, 0x57, 0x0c, 0x5d, 0x4c, 0x6e, 0x38, 0xb0, 0x38, 0xf0, 0x49,
+ 0xab, 0x5d, 0x9d, 0x9c, 0xd1, 0x92, 0x57, 0x48, 0x0d, 0x2b, 0x26, 0x94,
+ 0x8f, 0x3b, 0xcf, 0x00, 0xf1, 0xe4, 0x0b, 0xe8, 0xdb, 0x08, 0xbc, 0x9b,
+ 0x6a, 0x3c, 0x30, 0xd4, 0x7e, 0xa3, 0xe5, 0x86, 0x39, 0x0f, 0xc2, 0xb0,
+ 0x4a, 0x0e, 0x90, 0x76, 0xb6, 0x86, 0x1b, 0x2a, 0x3b, 0xbe, 0x75, 0x43,
+ 0xe7, 0x83, 0x6a, 0x9c, 0xcc, 0x86, 0xcc, 0xdd, 0xf9, 0x40, 0x69, 0xd4,
+ 0x2b, 0xb1, 0xd8, 0xc7, 0x70, 0x2a, 0x4c, 0x6f, 0xb6, 0x30, 0x21, 0xdb,
+ 0xbb, 0xcc, 0x27, 0xcf, 0x2d, 0x60, 0x97, 0x5f, 0x91, 0xfa, 0xd2, 0x08,
+ 0xe0, 0x8b, 0xbb, 0xa9, 0x5c, 0x22, 0xc0, 0xab, 0x2e, 0xd8, 0x3d, 0xc1,
+ 0x3c, 0xbc, 0xeb, 0xa0, 0xa2, 0xe2, 0x89, 0x48, 0xd8, 0x90, 0x70, 0xf4,
+ 0x64, 0x3c, 0x4b, 0x8b, 0x1b, 0xdc, 0x66, 0xb8, 0x9f, 0x48, 0xe5, 0x54,
+ 0x18, 0x2a, 0x2a, 0x6a, 0x09, 0x7f, 0xa4, 0x20, 0x43, 0x40, 0x08, 0x9c,
+ 0x11, 0x73, 0x7b, 0x60, 0x5b, 0xbe, 0x45, 0xdb, 0xf2, 0x3c, 0x6f, 0x38,
+ 0x4e, 0x6e, 0x11, 0xc8, 0x74, 0x74, 0x74, 0x62, 0x2e, 0x26, 0x9b, 0x64,
+ 0x02, 0x15, 0x3d, 0x9b, 0x91, 0x29, 0x58, 0x23, 0x82, 0x38, 0xaf, 0x32,
+ 0x07, 0x23, 0x63, 0xee, 0xa1, 0x50, 0xea, 0xf0, 0x1f, 0x81, 0x5c, 0x90,
+ 0x3e, 0x5a, 0xdb, 0x82, 0x23, 0xc2, 0xb9, 0x99, 0x89, 0x01, 0x27, 0xd4,
+ 0xd5, 0x1f, 0xf1, 0xab, 0xd3, 0x48, 0xb8, 0xdd, 0x81, 0x8b, 0x07, 0xb2,
+ 0xe5, 0xba, 0x78, 0x10, 0x4e, 0x2c, 0xb5, 0x1e, 0xc6, 0x56, 0x76, 0xcb,
+ 0xca, 0x6d, 0xe2, 0xd7, 0x63, 0x46, 0x00, 0x86, 0x37, 0x9b, 0x8a, 0xbf,
+ 0xc3, 0x22, 0x03, 0x69, 0xc8, 0x72, 0x3b, 0x4c, 0x58, 0x07, 0xce, 0xd1,
+ 0x00, 0x64, 0xbc, 0x9d, 0x35, 0xea, 0x34, 0x44, 0x88, 0xab, 0xdc, 0xc0,
+ 0xcd, 0x14, 0x2c, 0xa7, 0x6a, 0x81, 0xd6, 0xfa, 0xd1, 0xb9, 0x0c, 0x5e,
+ 0x01, 0xdb, 0x20, 0xe7, 0x6b, 0x40, 0x8b, 0xb1, 0xf2, 0xed, 0xe0, 0x3d,
+ 0x5d, 0x17, 0xe5, 0x60, 0xbc, 0x84, 0x5e, 0xe6, 0x95, 0xd1, 0xe2, 0x1c,
+ 0x4e, 0xaa, 0x3a, 0x0f, 0x5c, 0x35, 0x7c, 0x4f, 0xfe, 0x28, 0x64, 0xc7,
+ 0xb3, 0x8b, 0x0a, 0xe9, 0x92, 0x6d, 0xcc, 0x1d, 0x8b, 0xb4, 0xc2, 0x39,
+ 0x08, 0x88, 0xc5, 0xd6, 0xc2, 0x6b, 0x3c, 0x42, 0xd9, 0x64, 0x1b, 0x2d,
+ 0x58, 0x48, 0x11, 0x56, 0x78, 0x56, 0xda, 0x11, 0xd7, 0x8d, 0x85, 0xbe,
+ 0xbf, 0x80, 0x98, 0x90, 0x09, 0x20, 0xbc, 0x86, 0x52, 0x6b, 0xe2, 0xc6,
+ 0x6d, 0x43, 0x85, 0x9f, 0x18, 0x24, 0x22, 0x9d, 0x71, 0xc5, 0x8e, 0x95,
+ 0x57, 0x09, 0x1f, 0xa6, 0xe6, 0xe2, 0xe2, 0xaf, 0x67, 0x47, 0x6f, 0xf4,
+ 0xcd, 0xc7, 0xf6, 0x8c, 0xb1, 0xd3, 0x10, 0x33, 0x93, 0x09, 0x56, 0xa9,
+ 0x57, 0xd2, 0xd9, 0x10, 0xd9, 0xa0, 0x51, 0x5f, 0x3e, 0x77, 0x33, 0x48,
+ 0x7e, 0x38, 0x3c, 0x1e, 0x9d, 0x9d, 0x9c, 0x1e, 0xbc, 0x79, 0xfd, 0x83,
+ 0xb2, 0xe4, 0x2f, 0xc8, 0x45, 0xc0, 0x72, 0x9a, 0xfd, 0xcc, 0x61, 0x3b,
+ 0xc8, 0x7b, 0xef, 0x8f, 0xbe, 0xff, 0x68, 0xb4, 0x83, 0x37, 0x84, 0xf0,
+ 0xde, 0xbf, 0x4d, 0x67, 0xf2, 0x12, 0xa9, 0x58, 0x11, 0xd9, 0x6e, 0xd8,
+ 0x06, 0xe3, 0xeb, 0x2e, 0xac, 0xad, 0x1e, 0xea, 0xf2, 0x14, 0x1e, 0x34,
+ 0x8c, 0xce, 0x2b, 0x14, 0x95, 0xb6, 0xd2, 0x6a, 0x23, 0xb5, 0x7e, 0xdd,
+ 0xf5, 0xbf, 0xde, 0x70, 0x4c, 0x25, 0x85, 0x10, 0xf8, 0x9e, 0x79, 0xc4,
+ 0xad, 0xca, 0x37, 0x2e, 0x9e, 0x57, 0x90, 0x94, 0x2b, 0x0a, 0x60, 0xb1,
+ 0x50, 0x94, 0x52, 0x70, 0x19, 0x3e, 0x6f, 0xc1, 0xab, 0x14, 0x10, 0x26,
+ 0x0a, 0xa1, 0xd5, 0x68, 0x7a, 0xe5, 0x63, 0x22, 0xc2, 0xd8, 0xb1, 0xa4,
+ 0x5a, 0xca, 0x16, 0xb5, 0x79, 0xce, 0x8e, 0xce, 0x47, 0xc7, 0xa3, 0x0b,
+ 0x52, 0xa3, 0xa4, 0xae, 0xa2, 0xd8, 0xa0, 0xb5, 0xe8, 0x25, 0x30, 0x1b,
+ 0xda, 0xd0, 0xa3, 0x7e, 0xdd, 0x90, 0xd6, 0x89, 0xb6, 0x6c, 0xae, 0x9d,
+ 0xc4, 0x49, 0x37, 0x00, 0x67, 0x86, 0x92, 0x20, 0xca, 0x00, 0xba, 0xe9,
+ 0xa5, 0x1e, 0xe0, 0x52, 0x48, 0xa3, 0x53, 0x3e, 0x03, 0xa5, 0x6f, 0xb0,
+ 0x3b, 0xb3, 0x7c, 0xec, 0xac, 0xe6, 0x1d, 0x17, 0x32, 0x45, 0x27, 0x08,
+ 0x58, 0x87, 0x7f, 0x84, 0xd4, 0x1e, 0xee, 0x32, 0xa3, 0xa5, 0xd4, 0xae,
+ 0x5c, 0x6b, 0x92, 0xd5, 0xe8, 0xe7, 0xaf, 0x5a, 0x45, 0x15, 0xca, 0x89,
+ 0xca, 0x69, 0xf6, 0x53, 0x2f, 0x08, 0x55, 0xf0, 0x9f, 0x00, 0x5d, 0x2b,
+ 0x2c, 0x9b, 0x98, 0x72, 0xce, 0x99, 0x68, 0x64, 0x68, 0x31, 0x52, 0x0b,
+ 0x32, 0xeb, 0x11, 0x27, 0x24, 0x33, 0x0b, 0x44, 0x10, 0x11, 0x1d, 0xaf,
+ 0x28, 0x85, 0x0d, 0x20, 0x5b, 0x53, 0x92, 0xb7, 0x60, 0x81, 0xf3, 0x3b,
+ 0xd3, 0xeb, 0x94, 0x56, 0x70, 0xbc, 0xf4, 0x0b, 0xb5, 0xd9, 0xd1, 0x73,
+ 0x7d, 0x12, 0x2c, 0x3c, 0x22, 0x24, 0xd3, 0x0a, 0x28, 0x96, 0x8d, 0x80,
+ 0xc6, 0xab, 0xe2, 0x23, 0xe1, 0x8e, 0xc3, 0x36, 0x9e, 0x8f, 0xd2, 0xa5,
+ 0x16, 0x13, 0x7d, 0x6c, 0x45, 0xbd, 0xca, 0x8e, 0x44, 0xbe, 0x55, 0xa6,
+ 0x71, 0x4b, 0x6c, 0x66, 0xa8, 0xc9, 0xe1, 0x50, 0x4c, 0xec, 0x65, 0x4c,
+ 0x49, 0x47, 0xe4, 0x5f, 0xac, 0x04, 0x2b, 0xc9, 0xb0, 0x3f, 0xb2, 0x2c,
+ 0xa3, 0x1c, 0x24, 0xea, 0x24, 0x93, 0xd7, 0x4d, 0x71, 0xf4, 0x5c, 0x18,
+ 0x37, 0x2f, 0xb7, 0x47, 0x56, 0x6c, 0x5e, 0x7f, 0x90, 0x0e, 0x6d, 0x82,
+ 0xbc, 0x6e, 0x56, 0x9f, 0xf3, 0xad, 0x52, 0xa4, 0xf7, 0xa8, 0x5d, 0xd7,
+ 0x4b, 0x13, 0xad, 0x25, 0xf9, 0xd6, 0xba, 0xa7, 0xc1, 0xf0, 0x5a, 0x35,
+ 0x71, 0x69, 0x76, 0x2d, 0xd7, 0xa0, 0x91, 0x2f, 0x17, 0x28, 0xa6, 0x34,
+ 0x11, 0x34, 0x79, 0x04, 0xed, 0xda, 0x06, 0xf5, 0x12, 0x71, 0x8b, 0x65,
+ 0x56, 0xf5, 0xdd, 0x87, 0x93, 0x8b, 0xe3, 0x33, 0xdf, 0xfd, 0x98, 0x7c,
+ 0x7f, 0x7c, 0xf1, 0x8d, 0x91, 0xda, 0x47, 0xc7, 0xef, 0xbf, 0x3e, 0x21,
+ 0x1f, 0xcf, 0xbb, 0x77, 0xfb, 0xef, 0x09, 0x5d, 0xe0, 0x3d, 0x22, 0x1b,
+ 0xf7, 0xa1, 0x38, 0x10, 0x3b, 0x32, 0x4b, 0x4c, 0xb4, 0x43, 0x79, 0xe7,
+ 0xfd, 0xd0, 0xd5, 0xd0, 0x39, 0x7e, 0x5c, 0xf3, 0xb8, 0x68, 0x2f, 0xd2,
+ 0x1a, 0x2a, 0x58, 0x43, 0x33, 0x78, 0x20, 0xc3, 0x0e, 0x8e, 0x2d, 0x29,
+ 0x5b, 0xb4, 0xd0, 0x5d, 0x18, 0x79, 0xe4, 0x38, 0xb2, 0x84, 0x0e, 0x37,
+ 0x3a, 0xdf, 0xdd, 0xce, 0x7d, 0x81, 0x1d, 0xb5, 0x20, 0xb4, 0xd0, 0x63,
+ 0x8c, 0xcc, 0x54, 0x88, 0x5e, 0xc3, 0xf7, 0x65, 0x3b, 0xe7, 0xc0, 0xf4,
+ 0x88, 0x21, 0x21, 0x8e, 0xa0, 0x74, 0x16, 0x41, 0xd2, 0x38, 0x49, 0x69,
+ 0x3e, 0x3f, 0xf1, 0x2f, 0xd4, 0x76, 0x3d, 0x7a, 0x0d, 0x0f, 0xbc, 0x2a,
+ 0x33, 0x77, 0x72, 0x07, 0xa7, 0xda, 0x8c, 0x9a, 0x7f, 0xa1, 0x86, 0xf1,
+ 0xe5, 0x32, 0x20, 0xbe, 0x36, 0x30, 0x5b, 0xb2, 0x69, 0x2b, 0x0e, 0x89,
+ 0xf9, 0x6c, 0x8f, 0xc5, 0x4a, 0x0b, 0xb3, 0xac, 0xc5, 0xf3, 0x4c, 0x73,
+ 0xda, 0xb2, 0x84, 0xa2, 0x20, 0x1e, 0x5b, 0xd2, 0x9a, 0x64, 0xce, 0xe0,
+ 0x96, 0xfa, 0x58, 0x2b, 0x2b, 0x9b, 0xef, 0xbb, 0x53, 0x35, 0xed, 0x69,
+ 0x5a, 0x1b, 0x92, 0x59, 0x09, 0x7e, 0xc7, 0x79, 0x4e, 0x51, 0x64, 0xad,
+ 0x2c, 0x87, 0xd9, 0x7d, 0x46, 0x4e, 0x4e, 0xfa, 0xf5, 0x6f, 0x8b, 0x2b,
+ 0x3f, 0xe3, 0x8d, 0xcb, 0x3e, 0x2f, 0x62, 0x3b, 0x2b, 0x98, 0xce, 0x2c,
+ 0x16, 0x49, 0xa9, 0xb9, 0xd6, 0x08, 0xa4, 0x7e, 0xdc, 0xce, 0xaa, 0x0e,
+ 0xe5, 0xfb, 0xdd, 0xf0, 0xfb, 0x5d, 0x36, 0x3b, 0x1e, 0x9f, 0xdd, 0xbe,
+ 0xb4, 0x58, 0xa8, 0x9c, 0xc7, 0xed, 0x8b, 0x6f, 0x2a, 0x14, 0x10, 0x85,
+ 0xd1, 0xa3, 0x7c, 0xe7, 0xa4, 0xcc, 0x13, 0xd9, 0xf6, 0x4f, 0x11, 0x64,
+ 0xcb, 0x0a, 0xf9, 0xa9, 0x78, 0x04, 0x66, 0x62, 0x0e, 0xfb, 0x45, 0x90,
+ 0x1d, 0xf8, 0x14, 0x5d, 0x57, 0xa6, 0x41, 0xf3, 0xfd, 0x73, 0x1b, 0x8b,
+ 0xef, 0x78, 0x1a, 0xca, 0xb5, 0x49, 0x36, 0xd4, 0x20, 0x5f, 0xdc, 0x6a,
+ 0x0d, 0x5e, 0xf3, 0xeb, 0x4b, 0x5b, 0xaa, 0xa7, 0x6e, 0xf9, 0xa8, 0x5a,
+ 0xb8, 0xc3, 0xca, 0xfc, 0x31, 0x38, 0x84, 0x45, 0x12, 0x67, 0x70, 0x4a,
+ 0x46, 0x67, 0x5c, 0x59, 0x3b, 0x20, 0xdb, 0x2b, 0x22, 0x0a, 0x03, 0xf3,
+ 0x0c, 0x99, 0xb1, 0xe0, 0x47, 0x1e, 0x73, 0xf1, 0x31, 0xff, 0x65, 0xd7,
+ 0x7f, 0xdc, 0xdd, 0xde, 0xde, 0xd9, 0xdb, 0xf9, 0xfc, 0xd5, 0xf6, 0xde,
+ 0xce, 0xce, 0xce, 0xee, 0xde, 0xce, 0xde, 0xde, 0xee, 0xf6, 0xcf, 0x5b,
+ 0x64, 0x3f, 0xba, 0xcd, 0xb3, 0x3b, 0x75, 0x4c, 0x71, 0x2e, 0x1e, 0xc8,
+ 0x9a, 0x6b, 0xa9, 0x8b, 0x06, 0x2f, 0x7a, 0xae, 0x4a, 0x3e, 0x16, 0x55,
+ 0x82, 0x43, 0xe6, 0x19, 0x4c, 0x6e, 0xe1, 0x32, 0x4d, 0x71, 0x06, 0x3d,
+ 0xc0, 0x6b, 0x8c, 0xea, 0xef, 0x4b, 0x9a, 0xe9, 0x98, 0xc4, 0x01, 0xc8,
+ 0x34, 0xb5, 0xcd, 0xeb, 0xbb, 0x9a, 0x95, 0xe3, 0x31, 0x32, 0x17, 0x6c,
+ 0x6a, 0xeb, 0x30, 0x21, 0x54, 0xd5, 0x1b, 0x26, 0x09, 0xf1, 0x1c, 0x20,
+ 0xa8, 0x90, 0x0f, 0xba, 0x5b, 0x1d, 0x16, 0xbc, 0x24, 0x90, 0x7a, 0x52,
+ 0x52, 0x85, 0x81, 0x29, 0x31, 0x25, 0xb3, 0x48, 0x95, 0x4d, 0x79, 0x49,
+ 0x2e, 0xb3, 0xcf, 0xb7, 0xf7, 0xf6, 0xa8, 0x08, 0xc8, 0x9f, 0x76, 0xfa,
+ 0x12, 0x0f, 0xea, 0x07, 0xb9, 0xf7, 0xed, 0xf5, 0xc4, 0x6d, 0x90, 0xfa,
+ 0xe1, 0xcf, 0xb3, 0x58, 0xce, 0xb3, 0xca, 0x28, 0x22, 0x54, 0xda, 0x15,
+ 0x01, 0x91, 0x30, 0x7a, 0x33, 0xda, 0x1a, 0x00, 0x59, 0x3a, 0xc1, 0xf8,
+ 0x74, 0x23, 0x30, 0x6a, 0xac, 0x4d, 0x42, 0x67, 0xb8, 0x20, 0x37, 0x45,
+ 0xdb, 0x36, 0x0a, 0xe1, 0xc0, 0x8e, 0xcf, 0xa9, 0x2c, 0x9c, 0xc4, 0xc3,
+ 0xf7, 0xad, 0x70, 0x06, 0x1c, 0xae, 0x82, 0x0b, 0x8e, 0xd2, 0xe3, 0x2c,
+ 0xc3, 0xc3, 0x62, 0xe2, 0x09, 0xb7, 0x92, 0xbf, 0xf3, 0xa3, 0x37, 0xd9,
+ 0xdd, 0x17, 0x3b, 0x3f, 0x73, 0xb8, 0x22, 0x1d, 0x08, 0xb7, 0x6a, 0x52,
+ 0x18, 0x6e, 0xea, 0x67, 0x68, 0x28, 0x21, 0x6d, 0x64, 0xc3, 0xab, 0xa1,
+ 0x4a, 0x15, 0x62, 0x6d, 0xec, 0xfb, 0x41, 0xe3, 0x8c, 0x58, 0xce, 0x65,
+ 0x84, 0xa1, 0xa7, 0xa9, 0x41, 0x49, 0x0d, 0xc2, 0x6c, 0xcc, 0x6c, 0x55,
+ 0xf8, 0x31, 0x37, 0xcc, 0xd1, 0xc5, 0xbe, 0xb9, 0x3c, 0xbe, 0x0d, 0x15,
+ 0xfd, 0x77, 0x99, 0xd1, 0xca, 0x69, 0xb3, 0x37, 0x70, 0x1e, 0x6e, 0x2d,
+ 0x4e, 0x30, 0xad, 0xdd, 0xf3, 0x64, 0x83, 0x7c, 0x16, 0x2f, 0x3e, 0x7f,
+ 0xf1, 0x7c, 0x93, 0x8b, 0x32, 0xf0, 0x6b, 0x19, 0xe5, 0x87, 0xc0, 0x2a,
+ 0x29, 0xe0, 0x34, 0x64, 0x4e, 0xb6, 0x2c, 0xe9, 0xc3, 0xf9, 0x31, 0x1f,
+ 0xe9, 0x6b, 0xc6, 0x10, 0x60, 0xa5, 0xb7, 0x8b, 0x2b, 0x87, 0xfb, 0xd6,
+ 0x13, 0x32, 0xe6, 0x39, 0x61, 0x1e, 0x22, 0xf7, 0x9a, 0x2e, 0x46, 0x9b,
+ 0xfb, 0x8f, 0x1b, 0xd6, 0x1c, 0xd0, 0x12, 0xa5, 0x0a, 0xa5, 0x02, 0x14,
+ 0x06, 0x03, 0x90, 0x44, 0xc2, 0x68, 0x15, 0x3a, 0xb3, 0x1a, 0x18, 0xe9,
+ 0x41, 0xcc, 0x8f, 0x98, 0xfb, 0x77, 0x70, 0xb9, 0x37, 0xd9, 0xe3, 0x0f,
+ 0xa1, 0x90, 0xc8, 0xd0, 0x3c, 0xa8, 0xa1, 0xa3, 0x34, 0xe2, 0x56, 0x36,
+ 0x9a, 0x93, 0x36, 0x3d, 0x4c, 0x27, 0x85, 0x73, 0x11, 0x56, 0x64, 0x97,
+ 0x90, 0xdd, 0xd9, 0x0d, 0x2c, 0x8b, 0x79, 0xcb, 0xe4, 0x23, 0xb9, 0xf4,
+ 0xc8, 0x69, 0x47, 0xc8, 0xf1, 0xdc, 0x5c, 0x47, 0xd5, 0x83, 0x48, 0xd8,
+ 0x50, 0x13, 0x6c, 0x65, 0xb5, 0x4e, 0x40, 0x00, 0xa3, 0x46, 0xf8, 0x91,
+ 0xf4, 0x16, 0x34, 0x45, 0x95, 0xe6, 0xd6, 0x00, 0x5a, 0x6c, 0x7f, 0x30,
+ 0xd7, 0xaf, 0xbc, 0x78, 0x19, 0x3f, 0xbd, 0x4c, 0x7f, 0xd7, 0xe7, 0xbc,
+ 0x50, 0xca, 0xb4, 0x3b, 0xb1, 0x15, 0x43, 0x63, 0x6c, 0x4d, 0x84, 0x4f,
+ 0x59, 0xed, 0x67, 0x03, 0x23, 0xd9, 0xda, 0xda, 0x5c, 0x31, 0x1a, 0xf9,
+ 0x3a, 0xd6, 0xfb, 0x19, 0x30, 0x49, 0xbc, 0x8c, 0x4e, 0xb3, 0xe7, 0xed,
+ 0xc6, 0x69, 0x69, 0xf3, 0x9a, 0x76, 0x72, 0x2a, 0x71, 0xb1, 0x6c, 0x46,
+ 0x55, 0xf5, 0x8a, 0x07, 0xaf, 0xcc, 0xab, 0x3d, 0x09, 0x09, 0xc5, 0x51,
+ 0x8c, 0x28, 0xae, 0xf9, 0xcc, 0xee, 0xcd, 0x61, 0xb2, 0x4f, 0xd4, 0xd0,
+ 0xea, 0xd8, 0x1b, 0xb2, 0xda, 0x73, 0x15, 0x01, 0x5d, 0x85, 0x58, 0x6b,
+ 0xce, 0xeb, 0x7b, 0x5f, 0xaa, 0x98, 0xa7, 0x90, 0x00, 0xd6, 0xd8, 0x3b,
+ 0xce, 0x18, 0xfe, 0xc4, 0x72, 0x4e, 0x0f, 0xd9, 0x38, 0x2f, 0x5a, 0x25,
+ 0x43, 0xa5, 0x11, 0x38, 0xba, 0xed, 0x24, 0x00, 0x9a, 0x58, 0x29, 0x18,
+ 0xaf, 0x5f, 0x46, 0x10, 0x08, 0x04, 0x12, 0xd4, 0xce, 0x82, 0xb5, 0x25,
+ 0x62, 0xf6, 0xb6, 0x8e, 0x99, 0xbc, 0x5a, 0xeb, 0xd1, 0x67, 0x8a, 0xe7,
+ 0x20, 0x06, 0x8e, 0xb7, 0x35, 0x87, 0x84, 0x18, 0xc6, 0xfe, 0xf1, 0x09,
+ 0x45, 0xc5, 0x9d, 0x18, 0x15, 0x6f, 0xa4, 0xa2, 0x12, 0xa2, 0x44, 0x11,
+ 0xaf, 0x57, 0xe4, 0x24, 0xae, 0xf7, 0x6d, 0xe9, 0x11, 0x4d, 0x96, 0x82,
+ 0xde, 0x42, 0xce, 0x3d, 0x56, 0xfd, 0x05, 0x23, 0xd0, 0xec, 0x96, 0x91,
+ 0x97, 0x6a, 0x36, 0xda, 0x02, 0x8a, 0x97, 0x40, 0xea, 0xe1, 0x48, 0x85,
+ 0x4a, 0xcd, 0x6c, 0x1a, 0x95, 0x8f, 0xaa, 0x6c, 0x96, 0xdd, 0x8a, 0x75,
+ 0x95, 0x81, 0x4d, 0xbf, 0x16, 0x1f, 0x26, 0x97, 0x3e, 0x6d, 0x9c, 0x2b,
+ 0xb6, 0xe5, 0x26, 0xa5, 0x3e, 0xb7, 0x18, 0x13, 0xc6, 0x41, 0x7d, 0x50,
+ 0xf7, 0x0e, 0x8d, 0x5f, 0x5d, 0xc6, 0xf4, 0xde, 0x80, 0x74, 0x5c, 0x09,
+ 0x6d, 0xfd, 0x50, 0x0b, 0x9a, 0x43, 0x37, 0x56, 0x9c, 0x6d, 0x85, 0x5a,
+ 0x3c, 0x8f, 0x8d, 0xef, 0x7d, 0xc5, 0x4b, 0x66, 0x8f, 0x01, 0x5d, 0x3c,
+ 0x7d, 0x32, 0xd4, 0x72, 0x81, 0x76, 0xa3, 0x90, 0x51, 0x65, 0x8c, 0x3e,
+ 0x27, 0x8e, 0x82, 0x36, 0xca, 0x99, 0xf9, 0x13, 0xe1, 0x54, 0x1c, 0x60,
+ 0x69, 0x9e, 0x25, 0xbc, 0x57, 0x2f, 0xa2, 0xd5, 0xfc, 0xc9, 0xc9, 0x10,
+ 0xf2, 0x17, 0x9a, 0xaa, 0x96, 0x80, 0x15, 0xee, 0xf3, 0x65, 0x48, 0x4e,
+ 0xc7, 0x66, 0x32, 0xb4, 0xa3, 0x17, 0x9f, 0x3f, 0x8f, 0xff, 0x50, 0x5d,
+ 0xd2, 0x2a, 0x86, 0x94, 0x95, 0xae, 0x2e, 0xef, 0xc2, 0x98, 0x6b, 0x1d,
+ 0x7e, 0xb5, 0x24, 0x67, 0x98, 0xad, 0xe4, 0x43, 0xa3, 0x98, 0xd3, 0x55,
+ 0x94, 0x71, 0x59, 0x51, 0xdb, 0x38, 0x69, 0x74, 0x4b, 0xb3, 0xbb, 0xdc,
+ 0xfa, 0x49, 0x79, 0x47, 0x35, 0x51, 0x2f, 0x2f, 0xf3, 0x09, 0x15, 0xba,
+ 0x71, 0xf0, 0xc1, 0xc4, 0xe2, 0xf9, 0xc1, 0xb9, 0x96, 0x61, 0x32, 0x73,
+ 0x4b, 0x16, 0xcb, 0xf1, 0xcc, 0xdc, 0xd5, 0x1a, 0xcd, 0x6e, 0x0e, 0x15,
+ 0x56, 0xc9, 0x28, 0x5b, 0x68, 0x8e, 0x7d, 0xf9, 0xd0, 0x37, 0x3b, 0x11,
+ 0xd4, 0x52, 0xbc, 0x9d, 0x24, 0xf0, 0x39, 0x8a, 0xc3, 0x52, 0x98, 0xf1,
+ 0xbc, 0x2c, 0x34, 0x19, 0x66, 0x59, 0x33, 0x98, 0xa4, 0x56, 0x7a, 0x5f,
+ 0x63, 0xcf, 0x44, 0x3e, 0x13, 0xf4, 0x76, 0xd1, 0xcc, 0xf1, 0x86, 0x3f,
+ 0x99, 0xe9, 0x60, 0x71, 0xbd, 0xd0, 0x9d, 0x56, 0x79, 0x88, 0x85, 0x25,
+ 0x49, 0xbf, 0xc0, 0xc9, 0x3b, 0xfb, 0xe6, 0x6c, 0x98, 0x1c, 0x51, 0x4b,
+ 0x3c, 0x26, 0x91, 0x73, 0x61, 0xa2, 0x31, 0xdf, 0x99, 0xc9, 0x5e, 0xd1,
+ 0xfd, 0x75, 0x5a, 0xd1, 0x5f, 0x68, 0x4d, 0xbe, 0x64, 0xab, 0x2c, 0xbe,
+ 0x6d, 0xf7, 0x6a, 0x1a, 0xd2, 0x20, 0xeb, 0x33, 0xfc, 0x6e, 0x8e, 0x8a,
+ 0x91, 0xbe, 0xec, 0x36, 0xb9, 0x1e, 0xca, 0xaa, 0x05, 0xbd, 0xc3, 0x6f,
+ 0x26, 0x46, 0x28, 0x83, 0x68, 0xb5, 0x78, 0xc0, 0xfe, 0x79, 0xbc, 0x91,
+ 0xc5, 0x4f, 0x6e, 0xc0, 0x23, 0x2d, 0x21, 0x3f, 0x1b, 0xbe, 0xc7, 0xe7,
+ 0xaa, 0x62, 0xd0, 0x99, 0x2a, 0x93, 0x60, 0xc7, 0x52, 0xbc, 0xa4, 0x6c,
+ 0xd0, 0xa8, 0xb3, 0xce, 0x71, 0xf5, 0xd4, 0x37, 0xfd, 0x82, 0xb4, 0x6e,
+ 0x1a, 0x8b, 0x11, 0x5a, 0xcc, 0x16, 0x0c, 0xd7, 0xfe, 0x6f, 0x9c, 0x7c,
+ 0x7e, 0x85, 0xdf, 0x6c, 0x02, 0x00,
+};
+#define BUF_SIZE 0x10000
+static voidpf zalloc_func(voidpf opaque, unsigned int items, unsigned int size)
+{
+ (void) opaque;
+ /* not a typo, keep it calloc() */
+ return (voidpf) calloc(items, size);
+}
+static void zfree_func(voidpf opaque, voidpf ptr)
+{
+ (void) opaque;
+ free(ptr);
+}
+/* Decompress and send to stdout a gzip-compressed buffer */
+void hugehelp(void)
+{
+ unsigned char* buf;
+ int status,headerlen;
+ z_stream z;
+
+ /* Make sure no gzip options are set */
+ if (hugehelpgz[3] & 0xfe)
+ return;
+
+ headerlen = 10;
+ memset(&z, 0, sizeof(z_stream));
+ z.zalloc = (alloc_func)zalloc_func;
+ z.zfree = (free_func)zfree_func;
+ z.avail_in = (unsigned int)(sizeof(hugehelpgz) - headerlen);
+ z.next_in = (unsigned char *)hugehelpgz + headerlen;
+
+ if (inflateInit2(&z, -MAX_WBITS) != Z_OK)
+ return;
+
+ buf = malloc(BUF_SIZE);
+ if (buf) {
+ while(1) {
+ z.avail_out = BUF_SIZE;
+ z.next_out = buf;
+ status = inflate(&z, Z_SYNC_FLUSH);
+ if (status == Z_OK || status == Z_STREAM_END) {
+ fwrite(buf, BUF_SIZE - z.avail_out, 1, stdout);
+ if (status == Z_STREAM_END)
+ break;
+ }
+ else
+ break; /* Error */
+ }
+ free(buf);
+ }
+ inflateEnd(&z);
+}
+#else /* !USE_MANUAL */
+/* built-in manual is disabled, blank function */
+#include "tool_hugehelp.h"
+void hugehelp(void) {}
+#endif /* USE_MANUAL */
+#endif /* HAVE_LIBZ */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_hugehelp.h b/external/libcurl_android/jni/libcurl/src/tool_hugehelp.h
new file mode 100755
index 00000000..442579e5
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_hugehelp.h
@@ -0,0 +1,28 @@
+#ifndef HEADER_CURL_TOOL_HUGEHELP_H
+#define HEADER_CURL_TOOL_HUGEHELP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void hugehelp(void);
+
+#endif /* HEADER_CURL_TOOL_HUGEHELP_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_libinfo.c b/external/libcurl_android/jni/libcurl/src/tool_libinfo.c
new file mode 100755
index 00000000..81b6680c
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_libinfo.c
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_libinfo.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* global variable definitions, for libcurl run-time info */
+
+curl_version_info_data *curlinfo = NULL;
+long built_in_protos = 0;
+
+/*
+ * libcurl_info_init: retrieves run-time information about libcurl,
+ * setting a global pointer 'curlinfo' to libcurl's run-time info
+ * struct, and a global bit pattern 'built_in_protos' composed of
+ * CURLPROTO_* bits indicating which protocols are actually built
+ * into library being used.
+ */
+
+CURLcode get_libcurl_info(void)
+{
+ static struct proto_name_pattern {
+ const char *proto_name;
+ long proto_pattern;
+ } const possibly_built_in[] = {
+ { "dict", CURLPROTO_DICT },
+ { "file", CURLPROTO_FILE },
+ { "ftp", CURLPROTO_FTP },
+ { "ftps", CURLPROTO_FTPS },
+ { "gopher", CURLPROTO_GOPHER },
+ { "http", CURLPROTO_HTTP },
+ { "https", CURLPROTO_HTTPS },
+ { "imap", CURLPROTO_IMAP },
+ { "imaps", CURLPROTO_IMAPS },
+ { "ldap", CURLPROTO_LDAP },
+ { "ldaps", CURLPROTO_LDAPS },
+ { "pop3", CURLPROTO_POP3 },
+ { "pop3s", CURLPROTO_POP3S },
+ { "rtmp", CURLPROTO_RTMP },
+ { "rtsp", CURLPROTO_RTSP },
+ { "scp", CURLPROTO_SCP },
+ { "sftp", CURLPROTO_SFTP },
+ { "smtp", CURLPROTO_SMTP },
+ { "smtps", CURLPROTO_SMTPS },
+ { "telnet", CURLPROTO_TELNET },
+ { "tftp", CURLPROTO_TFTP },
+ { NULL, 0 }
+ };
+
+ struct proto_name_pattern const *p;
+ const char *const *proto;
+
+ /* Pointer to libcurl's run-time version information */
+ curlinfo = curl_version_info(CURLVERSION_NOW);
+ if(!curlinfo)
+ return CURLE_FAILED_INIT;
+
+ /* Build CURLPROTO_* bit pattern with libcurl's built-in protocols */
+ built_in_protos = 0;
+ if(curlinfo->protocols) {
+ for(proto = curlinfo->protocols; *proto; proto++) {
+ for(p = possibly_built_in; p->proto_name; p++) {
+ if(curlx_raw_equal(*proto, p->proto_name)) {
+ built_in_protos |= p->proto_pattern;
+ break;
+ }
+ }
+ }
+ }
+
+ return CURLE_OK;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_libinfo.h b/external/libcurl_android/jni/libcurl/src/tool_libinfo.h
new file mode 100755
index 00000000..5c149d91
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_libinfo.h
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_TOOL_LIBINFO_H
+#define HEADER_CURL_TOOL_LIBINFO_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/* global variable declarations, for libcurl run-time info */
+
+extern curl_version_info_data *curlinfo;
+extern long built_in_protos;
+
+CURLcode get_libcurl_info(void);
+
+#endif /* HEADER_CURL_TOOL_LIBINFO_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_main.c b/external/libcurl_android/jni/libcurl/src/tool_main.c
new file mode 100755
index 00000000..8c8acc6d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_main.c
@@ -0,0 +1,275 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include <sys/stat.h>
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef USE_NSS
+#include <nspr.h>
+#include <plarenas.h>
+#endif
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_convert.h"
+#include "tool_msgs.h"
+#include "tool_operate.h"
+#include "tool_panykey.h"
+#include "tool_vms.h"
+#include "tool_main.h"
+#include "tool_libinfo.h"
+
+/*
+ * This is low-level hard-hacking memory leak tracking and similar. Using
+ * the library level code from this client-side is ugly, but we do this
+ * anyway for convenience.
+ */
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef __VMS
+/*
+ * vms_show is a global variable, used in main() as parameter for
+ * function vms_special_exit() to allow proper curl tool exiting.
+ * Its value may be set in other tool_*.c source files thanks to
+ * forward declaration present in tool_vms.h
+ */
+int vms_show = 0;
+#endif
+
+/* if we build a static library for unit tests, there is no main() function */
+#ifndef UNITTESTS
+
+/*
+ * Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
+ * open before starting to run. Otherwise, the first three network
+ * sockets opened by curl could be used for input sources, downloaded data
+ * or error logs as they will effectively be stdin, stdout and/or stderr.
+ */
+static void main_checkfds(void)
+{
+#ifdef HAVE_PIPE
+ int fd[2] = { STDIN_FILENO, STDIN_FILENO };
+ while(fd[0] == STDIN_FILENO ||
+ fd[0] == STDOUT_FILENO ||
+ fd[0] == STDERR_FILENO ||
+ fd[1] == STDIN_FILENO ||
+ fd[1] == STDOUT_FILENO ||
+ fd[1] == STDERR_FILENO)
+ if(pipe(fd) < 0)
+ return; /* Out of handles. This isn't really a big problem now, but
+ will be when we try to create a socket later. */
+ close(fd[0]);
+ close(fd[1]);
+#endif
+}
+
+#ifdef CURLDEBUG
+static void memory_tracking_init(void)
+{
+ char *env;
+ /* if CURL_MEMDEBUG is set, this starts memory tracking message logging */
+ env = curlx_getenv("CURL_MEMDEBUG");
+ if(env) {
+ /* use the value as file name */
+ char fname[CURL_MT_LOGFNAME_BUFSIZE];
+ if(strlen(env) >= CURL_MT_LOGFNAME_BUFSIZE)
+ env[CURL_MT_LOGFNAME_BUFSIZE-1] = '\0';
+ strcpy(fname, env);
+ curl_free(env);
+ curl_memdebug(fname);
+ /* this weird stuff here is to make curl_free() get called
+ before curl_memdebug() as otherwise memory tracking will
+ log a free() without an alloc! */
+ }
+ /* if CURL_MEMLIMIT is set, this enables fail-on-alloc-number-N feature */
+ env = curlx_getenv("CURL_MEMLIMIT");
+ if(env) {
+ char *endptr;
+ long num = strtol(env, &endptr, 10);
+ if((endptr != env) && (endptr == env + strlen(env)) && (num > 0))
+ curl_memlimit(num);
+ curl_free(env);
+ }
+}
+#else
+# define memory_tracking_init() Curl_nop_stmt
+#endif
+
+/*
+ * This is the main global constructor for the app. Call this before
+ * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
+ * used, or havoc may be the result.
+ */
+static CURLcode main_init(struct GlobalConfig *config)
+{
+ CURLcode result = CURLE_OK;
+
+#if defined(__DJGPP__) || defined(__GO32__)
+ /* stop stat() wasting time */
+ _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
+#endif
+
+ /* Initialise the global config */
+ config->showerror = -1; /* Will show errors */
+ config->errors = stderr; /* Default errors to stderr */
+
+ /* Allocate the initial operate config */
+ config->first = config->last = malloc(sizeof(struct OperationConfig));
+ if(config->first) {
+ /* Perform the libcurl initialization */
+ result = curl_global_init(CURL_GLOBAL_DEFAULT);
+ if(!result) {
+ /* Get information about libcurl */
+ result = get_libcurl_info();
+
+ if(!result) {
+ /* Get a curl handle to use for all forthcoming curl transfers */
+ config->easy = curl_easy_init();
+ if(config->easy) {
+ /* Initialise the config */
+ config_init(config->first);
+ config->first->easy = config->easy;
+ config->first->global = config;
+ }
+ else {
+ helpf(stderr, "error initializing curl easy handle\n");
+ result = CURLE_FAILED_INIT;
+ free(config->first);
+ }
+ }
+ else {
+ helpf(stderr, "error retrieving curl library information\n");
+ free(config->first);
+ }
+ }
+ else {
+ helpf(stderr, "error initializing curl library\n");
+ free(config->first);
+ }
+ }
+ else {
+ helpf(stderr, "error initializing curl\n");
+ result = CURLE_FAILED_INIT;
+ }
+
+ return result;
+}
+
+static void free_config_fields(struct GlobalConfig *config)
+{
+ Curl_safefree(config->trace_dump);
+
+ if(config->errors_fopened && config->errors)
+ fclose(config->errors);
+ config->errors = NULL;
+
+ if(config->trace_fopened && config->trace_stream)
+ fclose(config->trace_stream);
+ config->trace_stream = NULL;
+
+ Curl_safefree(config->libcurl);
+}
+
+/*
+ * This is the main global destructor for the app. Call this after
+ * _all_ libcurl usage is done.
+ */
+static void main_free(struct GlobalConfig *config)
+{
+ /* Cleanup the easy handle */
+ curl_easy_cleanup(config->easy);
+ config->easy = NULL;
+
+ /* Main cleanup */
+ curl_global_cleanup();
+ convert_cleanup();
+ metalink_cleanup();
+#ifdef USE_NSS
+ if(PR_Initialized()) {
+ /* prevent valgrind from reporting still reachable mem from NSRP arenas */
+ PL_ArenaFinish();
+ /* prevent valgrind from reporting possibly lost memory (fd cache, ...) */
+ PR_Cleanup();
+ }
+#endif
+ free_config_fields(config);
+
+ /* Free the config structures */
+ config_free(config->last);
+ config->first = NULL;
+ config->last = NULL;
+}
+
+/*
+** curl tool main function.
+*/
+int main(int argc, char *argv[])
+{
+ CURLcode result = CURLE_OK;
+ struct GlobalConfig global;
+ memset(&global, 0, sizeof(global));
+
+ main_checkfds();
+
+#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
+ (void)signal(SIGPIPE, SIG_IGN);
+#endif
+
+ /* Initialize memory tracking */
+ memory_tracking_init();
+
+ /* Initialize the curl library - do not call any libcurl functions before
+ this point */
+ result = main_init(&global);
+ if(!result) {
+ /* Start our curl operation */
+ result = operate(&global, argc, argv);
+
+#ifdef __SYMBIAN32__
+ if(global.showerror)
+ tool_pressanykey();
+#endif
+
+ /* Perform the main cleanup */
+ main_free(&global);
+ }
+
+#ifdef __NOVELL_LIBC__
+ if(getenv("_IN_NETWARE_BASH_") == NULL)
+ tool_pressanykey();
+#endif
+
+#ifdef __VMS
+ vms_special_exit(res, vms_show);
+#else
+ return (int)result;
+#endif
+}
+
+#endif /* ndef UNITTESTS */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_main.h b/external/libcurl_android/jni/libcurl/src/tool_main.h
new file mode 100755
index 00000000..9a7972fd
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_main.h
@@ -0,0 +1,44 @@
+#ifndef HEADER_CURL_TOOL_MAIN_H
+#define HEADER_CURL_TOOL_MAIN_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define DEFAULT_MAXREDIRS 50L
+
+#define RETRY_SLEEP_DEFAULT 1000L /* ms */
+#define RETRY_SLEEP_MAX 600000L /* ms == 10 minutes */
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO fileno(stdin)
+#endif
+
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO fileno(stdout)
+#endif
+
+#ifndef STDERR_FILENO
+# define STDERR_FILENO fileno(stderr)
+#endif
+
+#endif /* HEADER_CURL_TOOL_MAIN_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_metalink.c b/external/libcurl_android/jni/libcurl/src/tool_metalink.c
new file mode 100755
index 00000000..3573b058
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_metalink.c
@@ -0,0 +1,963 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef USE_METALINK
+
+#include <sys/stat.h>
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef USE_SSLEAY
+# ifdef USE_OPENSSL
+# include <openssl/md5.h>
+# include <openssl/sha.h>
+# else
+# include <md5.h>
+# include <sha.h>
+# endif
+#elif defined(USE_GNUTLS_NETTLE)
+# include <nettle/md5.h>
+# include <nettle/sha.h>
+# define MD5_CTX struct md5_ctx
+# define SHA_CTX struct sha1_ctx
+# define SHA256_CTX struct sha256_ctx
+#elif defined(USE_GNUTLS)
+# include <gcrypt.h>
+# define MD5_CTX gcry_md_hd_t
+# define SHA_CTX gcry_md_hd_t
+# define SHA256_CTX gcry_md_hd_t
+#elif defined(USE_NSS)
+# include <nss.h>
+# include <pk11pub.h>
+# define MD5_CTX void *
+# define SHA_CTX void *
+# define SHA256_CTX void *
+ static NSSInitContext *nss_context;
+#elif defined(USE_POLARSSL)
+# include <polarssl/md5.h>
+# include <polarssl/sha1.h>
+# include <polarssl/sha256.h>
+# define MD5_CTX md5_context
+# define SHA_CTX sha1_context
+# define SHA256_CTX sha256_context
+#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
+ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
+ (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
+/* For Apple operating systems: CommonCrypto has the functions we need.
+ The library's headers are even backward-compatible with OpenSSL's
+ headers as long as we define COMMON_DIGEST_FOR_OPENSSL first.
+
+ These functions are available on Tiger and later, as well as iOS 2.0
+ and later. If you're building for an older cat, well, sorry. */
+# define COMMON_DIGEST_FOR_OPENSSL
+# include <CommonCrypto/CommonDigest.h>
+#elif defined(_WIN32)
+/* For Windows: If no other crypto library is provided, we fallback
+ to the hash functions provided within the Microsoft Windows CryptoAPI */
+# include <wincrypt.h>
+/* Custom structure in order to store the required provider and hash handle */
+struct win32_crypto_hash {
+ HCRYPTPROV hCryptProv;
+ HCRYPTHASH hHash;
+};
+/* Custom Microsoft AES Cryptographic Provider defines required for MinGW */
+# ifndef ALG_SID_SHA_256
+# define ALG_SID_SHA_256 12
+# endif
+# ifndef CALG_SHA_256
+# define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
+# endif
+# define MD5_CTX struct win32_crypto_hash
+# define SHA_CTX struct win32_crypto_hash
+# define SHA256_CTX struct win32_crypto_hash
+#else
+# error "Can't compile METALINK support without a crypto library."
+#endif
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_getparam.h"
+#include "tool_paramhlp.h"
+#include "tool_cfgable.h"
+#include "tool_metalink.h"
+#include "tool_msgs.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* Copied from tool_getparam.c */
+#define GetStr(str,val) do { \
+ if(*(str)) { \
+ free(*(str)); \
+ *(str) = NULL; \
+ } \
+ if((val)) \
+ *(str) = strdup((val)); \
+ if(!(val)) \
+ return PARAM_NO_MEM; \
+} WHILE_FALSE
+
+#ifdef USE_GNUTLS_NETTLE
+
+static int MD5_Init(MD5_CTX *ctx)
+{
+ md5_init(ctx);
+ return 1;
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ md5_update(ctx, inputLen, input);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+{
+ md5_digest(ctx, 16, digest);
+}
+
+static int SHA1_Init(SHA_CTX *ctx)
+{
+ sha1_init(ctx);
+ return 1;
+}
+
+static void SHA1_Update(SHA_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ sha1_update(ctx, inputLen, input);
+}
+
+static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
+{
+ sha1_digest(ctx, 20, digest);
+}
+
+static int SHA256_Init(SHA256_CTX *ctx)
+{
+ sha256_init(ctx);
+ return 1;
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ sha256_update(ctx, inputLen, input);
+}
+
+static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
+{
+ sha256_digest(ctx, 32, digest);
+}
+
+#elif defined(USE_GNUTLS)
+
+static int MD5_Init(MD5_CTX *ctx)
+{
+ gcry_md_open(ctx, GCRY_MD_MD5, 0);
+ return 1;
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ gcry_md_write(*ctx, input, inputLen);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+{
+ memcpy(digest, gcry_md_read(*ctx, 0), 16);
+ gcry_md_close(*ctx);
+}
+
+static int SHA1_Init(SHA_CTX *ctx)
+{
+ gcry_md_open(ctx, GCRY_MD_SHA1, 0);
+ return 1;
+}
+
+static void SHA1_Update(SHA_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ gcry_md_write(*ctx, input, inputLen);
+}
+
+static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
+{
+ memcpy(digest, gcry_md_read(*ctx, 0), 20);
+ gcry_md_close(*ctx);
+}
+
+static int SHA256_Init(SHA256_CTX *ctx)
+{
+ gcry_md_open(ctx, GCRY_MD_SHA256, 0);
+ return 1;
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ gcry_md_write(*ctx, input, inputLen);
+}
+
+static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
+{
+ memcpy(digest, gcry_md_read(*ctx, 0), 32);
+ gcry_md_close(*ctx);
+}
+
+#elif defined(USE_NSS)
+
+static int nss_hash_init(void **pctx, SECOidTag hash_alg)
+{
+ PK11Context *ctx;
+
+ /* we have to initialize NSS if not initialized alraedy */
+ if(!NSS_IsInitialized() && !nss_context) {
+ static NSSInitParameters params;
+ params.length = sizeof params;
+ nss_context = NSS_InitContext("", "", "", "", &params, NSS_INIT_READONLY
+ | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
+ | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
+ }
+
+ ctx = PK11_CreateDigestContext(hash_alg);
+ if(!ctx)
+ return /* failure */ 0;
+
+ if(PK11_DigestBegin(ctx) != SECSuccess) {
+ PK11_DestroyContext(ctx, PR_TRUE);
+ return /* failure */ 0;
+ }
+
+ *pctx = ctx;
+ return /* success */ 1;
+}
+
+static void nss_hash_final(void **pctx, unsigned char *out, unsigned int len)
+{
+ PK11Context *ctx = *pctx;
+ unsigned int outlen;
+ PK11_DigestFinal(ctx, out, &outlen, len);
+ PK11_DestroyContext(ctx, PR_TRUE);
+}
+
+static int MD5_Init(MD5_CTX *pctx)
+{
+ return nss_hash_init(pctx, SEC_OID_MD5);
+}
+
+static void MD5_Update(MD5_CTX *pctx,
+ const unsigned char *input,
+ unsigned int input_len)
+{
+ PK11_DigestOp(*pctx, input, input_len);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *pctx)
+{
+ nss_hash_final(pctx, digest, 16);
+}
+
+static int SHA1_Init(SHA_CTX *pctx)
+{
+ return nss_hash_init(pctx, SEC_OID_SHA1);
+}
+
+static void SHA1_Update(SHA_CTX *pctx,
+ const unsigned char *input,
+ unsigned int input_len)
+{
+ PK11_DigestOp(*pctx, input, input_len);
+}
+
+static void SHA1_Final(unsigned char digest[20], SHA_CTX *pctx)
+{
+ nss_hash_final(pctx, digest, 20);
+}
+
+static int SHA256_Init(SHA256_CTX *pctx)
+{
+ return nss_hash_init(pctx, SEC_OID_SHA256);
+}
+
+static void SHA256_Update(SHA256_CTX *pctx,
+ const unsigned char *input,
+ unsigned int input_len)
+{
+ PK11_DigestOp(*pctx, input, input_len);
+}
+
+static void SHA256_Final(unsigned char digest[32], SHA256_CTX *pctx)
+{
+ nss_hash_final(pctx, digest, 32);
+}
+
+#elif defined(USE_POLARSSL)
+
+static int MD5_Init(MD5_CTX *ctx)
+{
+ md5_starts(ctx);
+ return 1;
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ md5_update(ctx, input, inputLen);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+{
+ md5_finish(ctx, digest);
+}
+
+static int SHA1_Init(SHA_CTX *ctx)
+{
+ sha1_starts(ctx);
+ return 1;
+}
+
+static void SHA1_Update(SHA_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ sha1_update(ctx, input, inputLen);
+}
+
+static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
+{
+ sha1_finish(ctx, digest);
+}
+
+static int SHA256_Init(SHA256_CTX *ctx)
+{
+ sha256_starts(ctx, 0); /* 0 = sha256 */
+ return 1;
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ sha256_update(ctx, input, inputLen);
+}
+
+static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
+{
+ sha256_finish(ctx, digest);
+}
+
+#elif defined(_WIN32) && !defined(USE_SSLEAY)
+
+static void win32_crypto_final(struct win32_crypto_hash *ctx,
+ unsigned char *digest,
+ unsigned int digestLen)
+{
+ unsigned long length;
+ CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
+ if(length == digestLen)
+ CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
+ if(ctx->hHash)
+ CryptDestroyHash(ctx->hHash);
+ if(ctx->hCryptProv)
+ CryptReleaseContext(ctx->hCryptProv, 0);
+}
+
+static int MD5_Init(MD5_CTX *ctx)
+{
+ if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash);
+ }
+ return 1;
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
+}
+
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+{
+ win32_crypto_final(ctx, digest, 16);
+}
+
+static int SHA1_Init(SHA_CTX *ctx)
+{
+ if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ CryptCreateHash(ctx->hCryptProv, CALG_SHA1, 0, 0, &ctx->hHash);
+ }
+ return 1;
+}
+
+static void SHA1_Update(SHA_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
+}
+
+static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
+{
+ win32_crypto_final(ctx, digest, 20);
+}
+
+static int SHA256_Init(SHA256_CTX *ctx)
+{
+ if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
+ PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
+ CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash);
+ }
+ return 1;
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
+}
+
+static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
+{
+ win32_crypto_final(ctx, digest, 32);
+}
+
+#endif /* CRYPTO LIBS */
+
+const digest_params MD5_DIGEST_PARAMS[] = {
+ {
+ (Curl_digest_init_func) MD5_Init,
+ (Curl_digest_update_func) MD5_Update,
+ (Curl_digest_final_func) MD5_Final,
+ sizeof(MD5_CTX),
+ 16
+ }
+};
+
+const digest_params SHA1_DIGEST_PARAMS[] = {
+ {
+ (Curl_digest_init_func) SHA1_Init,
+ (Curl_digest_update_func) SHA1_Update,
+ (Curl_digest_final_func) SHA1_Final,
+ sizeof(SHA_CTX),
+ 20
+ }
+};
+
+const digest_params SHA256_DIGEST_PARAMS[] = {
+ {
+ (Curl_digest_init_func) SHA256_Init,
+ (Curl_digest_update_func) SHA256_Update,
+ (Curl_digest_final_func) SHA256_Final,
+ sizeof(SHA256_CTX),
+ 32
+ }
+};
+
+static const metalink_digest_def SHA256_DIGEST_DEF[] = {
+ {"sha-256", SHA256_DIGEST_PARAMS}
+};
+
+static const metalink_digest_def SHA1_DIGEST_DEF[] = {
+ {"sha-1", SHA1_DIGEST_PARAMS}
+};
+
+static const metalink_digest_def MD5_DIGEST_DEF[] = {
+ {"md5", MD5_DIGEST_PARAMS}
+};
+
+/*
+ * The alias of supported hash functions in the order by preference
+ * (basically stronger hash comes first). We included "sha-256" and
+ * "sha256". The former is the name defined in the IANA registry named
+ * "Hash Function Textual Names". The latter is widely (and
+ * historically) used in Metalink version 3.
+ */
+static const metalink_digest_alias digest_aliases[] = {
+ {"sha-256", SHA256_DIGEST_DEF},
+ {"sha256", SHA256_DIGEST_DEF},
+ {"sha-1", SHA1_DIGEST_DEF},
+ {"sha1", SHA1_DIGEST_DEF},
+ {"md5", MD5_DIGEST_DEF},
+ {NULL, NULL}
+};
+
+digest_context *Curl_digest_init(const digest_params *dparams)
+{
+ digest_context *ctxt;
+
+ /* Create digest context */
+ ctxt = malloc(sizeof *ctxt);
+
+ if(!ctxt)
+ return ctxt;
+
+ ctxt->digest_hashctx = malloc(dparams->digest_ctxtsize);
+
+ if(!ctxt->digest_hashctx) {
+ free(ctxt);
+ return NULL;
+ }
+
+ ctxt->digest_hash = dparams;
+
+ if(dparams->digest_init(ctxt->digest_hashctx) != 1) {
+ free(ctxt);
+ return NULL;
+ }
+
+ return ctxt;
+}
+
+int Curl_digest_update(digest_context *context,
+ const unsigned char *data,
+ unsigned int len)
+{
+ (*context->digest_hash->digest_update)(context->digest_hashctx, data, len);
+
+ return 0;
+}
+
+int Curl_digest_final(digest_context *context, unsigned char *result)
+{
+ (*context->digest_hash->digest_final)(result, context->digest_hashctx);
+
+ free(context->digest_hashctx);
+ free(context);
+
+ return 0;
+}
+
+static unsigned char hex_to_uint(const char *s)
+{
+ int v[2];
+ int i;
+ for(i = 0; i < 2; ++i) {
+ v[i] = Curl_raw_toupper(s[i]);
+ if('0' <= v[i] && v[i] <= '9') {
+ v[i] -= '0';
+ }
+ else if('A' <= v[i] && v[i] <= 'Z') {
+ v[i] -= 'A'-10;
+ }
+ }
+ return (unsigned char)((v[0] << 4) | v[1]);
+}
+
+/*
+ * Check checksum of file denoted by filename. The expected hash value
+ * is given in hex_hash which is hex-encoded string.
+ *
+ * This function returns 1 if it succeeds or one of the following
+ * integers:
+ *
+ * 0:
+ * Checksum didn't match.
+ * -1:
+ * Could not open file; or could not read data from file.
+ * -2:
+ * Hash algorithm not available.
+ */
+static int check_hash(const char *filename,
+ const metalink_digest_def *digest_def,
+ const unsigned char *digest, FILE *error)
+{
+ unsigned char *result;
+ digest_context *dctx;
+ int check_ok, flags, fd;
+
+ flags = O_RDONLY;
+#ifdef O_BINARY
+ /* O_BINARY is required in order to avoid binary EOF in text mode */
+ flags |= O_BINARY;
+#endif
+
+ fd = open(filename, flags);
+ if(fd == -1) {
+ fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
+ digest_def->hash_name, strerror(errno));
+ return -1;
+ }
+
+ dctx = Curl_digest_init(digest_def->dparams);
+ if(!dctx) {
+ fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
+ digest_def->hash_name, "failed to initialize hash algorithm");
+ close(fd);
+ return -2;
+ }
+
+ result = malloc(digest_def->dparams->digest_resultlen);
+ while(1) {
+ unsigned char buf[4096];
+ ssize_t len = read(fd, buf, sizeof(buf));
+ if(len == 0) {
+ break;
+ }
+ else if(len == -1) {
+ fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
+ digest_def->hash_name, strerror(errno));
+ Curl_digest_final(dctx, result);
+ close(fd);
+ return -1;
+ }
+ Curl_digest_update(dctx, buf, (unsigned int)len);
+ }
+ Curl_digest_final(dctx, result);
+ check_ok = memcmp(result, digest,
+ digest_def->dparams->digest_resultlen) == 0;
+ /* sha*sum style verdict output */
+ if(check_ok)
+ fprintf(error, "Metalink: validating (%s) [%s] OK\n", filename,
+ digest_def->hash_name);
+ else
+ fprintf(error, "Metalink: validating (%s) [%s] FAILED (digest mismatch)\n",
+ filename, digest_def->hash_name);
+
+ free(result);
+ close(fd);
+ return check_ok;
+}
+
+int metalink_check_hash(struct GlobalConfig *config,
+ metalinkfile *mlfile,
+ const char *filename)
+{
+ int rv;
+ fprintf(config->errors, "Metalink: validating (%s)...\n", filename);
+ if(mlfile->checksum == NULL) {
+ fprintf(config->errors,
+ "Metalink: validating (%s) FAILED (digest missing)\n", filename);
+ return -2;
+ }
+ rv = check_hash(filename, mlfile->checksum->digest_def,
+ mlfile->checksum->digest, config->errors);
+ return rv;
+}
+
+static metalink_checksum *new_metalink_checksum_from_hex_digest
+(const metalink_digest_def *digest_def, const char *hex_digest)
+{
+ metalink_checksum *chksum;
+ unsigned char *digest;
+ size_t i;
+ size_t len = strlen(hex_digest);
+ digest = malloc(len/2);
+ for(i = 0; i < len; i += 2) {
+ digest[i/2] = hex_to_uint(hex_digest+i);
+ }
+ chksum = malloc(sizeof(metalink_checksum));
+ chksum->digest_def = digest_def;
+ chksum->digest = digest;
+ return chksum;
+}
+
+static metalink_resource *new_metalink_resource(const char *url)
+{
+ metalink_resource *res;
+ res = malloc(sizeof(metalink_resource));
+ res->next = NULL;
+ res->url = strdup(url);
+ return res;
+}
+
+/* Returns nonzero if hex_digest is properly formatted; that is each
+ letter is in [0-9A-Za-z] and the length of the string equals to the
+ result length of digest * 2. */
+static int check_hex_digest(const char *hex_digest,
+ const metalink_digest_def *digest_def)
+{
+ size_t i;
+ for(i = 0; hex_digest[i]; ++i) {
+ char c = hex_digest[i];
+ if(!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') ||
+ ('A' <= c && c <= 'Z'))) {
+ return 0;
+ }
+ }
+ return digest_def->dparams->digest_resultlen * 2 == i;
+}
+
+static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
+{
+ metalinkfile *f;
+ f = (metalinkfile*)malloc(sizeof(metalinkfile));
+ f->next = NULL;
+ f->filename = strdup(fileinfo->name);
+ f->checksum = NULL;
+ f->resource = NULL;
+ if(fileinfo->checksums) {
+ const metalink_digest_alias *digest_alias;
+ for(digest_alias = digest_aliases; digest_alias->alias_name;
+ ++digest_alias) {
+ metalink_checksum_t **p;
+ for(p = fileinfo->checksums; *p; ++p) {
+ if(Curl_raw_equal(digest_alias->alias_name, (*p)->type) &&
+ check_hex_digest((*p)->hash, digest_alias->digest_def)) {
+ f->checksum =
+ new_metalink_checksum_from_hex_digest(digest_alias->digest_def,
+ (*p)->hash);
+ break;
+ }
+ }
+ if(f->checksum) {
+ break;
+ }
+ }
+ }
+ if(fileinfo->resources) {
+ metalink_resource_t **p;
+ metalink_resource root, *tail;
+ root.next = NULL;
+ tail = &root;
+ for(p = fileinfo->resources; *p; ++p) {
+ metalink_resource *res;
+ /* Filter by type if it is non-NULL. In Metalink v3, type
+ includes the type of the resource. In curl, we are only
+ interested in HTTP, HTTPS and FTP. In addition to them,
+ Metalink v3 file may contain bittorrent type URL, which
+ points to the BitTorrent metainfo file. We ignore it here.
+ In Metalink v4, type was deprecated and all
+ fileinfo->resources point to the target file. BitTorrent
+ metainfo file URL may be appeared in fileinfo->metaurls.
+ */
+ if((*p)->type == NULL ||
+ Curl_raw_equal((*p)->type, "http") ||
+ Curl_raw_equal((*p)->type, "https") ||
+ Curl_raw_equal((*p)->type, "ftp") ||
+ Curl_raw_equal((*p)->type, "ftps")) {
+ res = new_metalink_resource((*p)->url);
+ tail->next = res;
+ tail = res;
+ }
+ }
+ f->resource = root.next;
+ }
+ return f;
+}
+
+int parse_metalink(struct OperationConfig *config, struct OutStruct *outs,
+ const char *metalink_url)
+{
+ metalink_error_t r;
+ metalink_t* metalink;
+ metalink_file_t **files;
+ bool warnings = FALSE;
+
+ /* metlaink_parse_final deletes outs->metalink_parser */
+ r = metalink_parse_final(outs->metalink_parser, NULL, 0, &metalink);
+ outs->metalink_parser = NULL;
+ if(r != 0) {
+ return -1;
+ }
+ if(metalink->files == NULL) {
+ fprintf(config->global->errors, "Metalink: parsing (%s) WARNING "
+ "(missing or invalid file name)\n",
+ metalink_url);
+ metalink_delete(metalink);
+ return -1;
+ }
+ for(files = metalink->files; *files; ++files) {
+ struct getout *url;
+ /* Skip an entry which has no resource. */
+ if(!(*files)->resources) {
+ fprintf(config->global->errors, "Metalink: parsing (%s) WARNING "
+ "(missing or invalid resource)\n",
+ metalink_url, (*files)->name);
+ continue;
+ }
+ if(config->url_get ||
+ ((config->url_get = config->url_list) != NULL)) {
+ /* there's a node here, if it already is filled-in continue to
+ find an "empty" node */
+ while(config->url_get && (config->url_get->flags & GETOUT_URL))
+ config->url_get = config->url_get->next;
+ }
+
+ /* now there might or might not be an available node to fill in! */
+
+ if(config->url_get)
+ /* existing node */
+ url = config->url_get;
+ else
+ /* there was no free node, create one! */
+ url = new_getout(config);
+
+ if(url) {
+ metalinkfile *mlfile;
+ mlfile = new_metalinkfile(*files);
+ if(!mlfile->checksum) {
+ warnings = TRUE;
+ fprintf(config->global->errors,
+ "Metalink: parsing (%s) WARNING (digest missing)\n",
+ metalink_url);
+ }
+ /* Set name as url */
+ GetStr(&url->url, mlfile->filename);
+
+ /* set flag metalink here */
+ url->flags |= GETOUT_URL | GETOUT_METALINK;
+
+ if(config->metalinkfile_list) {
+ config->metalinkfile_last->next = mlfile;
+ config->metalinkfile_last = mlfile;
+ }
+ else {
+ config->metalinkfile_list = config->metalinkfile_last = mlfile;
+ }
+ }
+ }
+ metalink_delete(metalink);
+ return (warnings) ? -2 : 0;
+}
+
+size_t metalink_write_cb(void *buffer, size_t sz, size_t nmemb,
+ void *userdata)
+{
+ struct OutStruct *outs = userdata;
+ struct OperationConfig *config = outs->config;
+ int rv;
+
+ /*
+ * Once that libcurl has called back tool_write_cb() the returned value
+ * is checked against the amount that was intended to be written, if
+ * it does not match then it fails with CURLE_WRITE_ERROR. So at this
+ * point returning a value different from sz*nmemb indicates failure.
+ */
+ const size_t failure = (sz * nmemb) ? 0 : 1;
+
+ if(!config)
+ return failure;
+
+ rv = metalink_parse_update(outs->metalink_parser, buffer, sz *nmemb);
+ if(rv == 0)
+ return sz * nmemb;
+ else {
+ fprintf(config->global->errors, "Metalink: parsing FAILED\n");
+ return failure;
+ }
+}
+
+/*
+ * Returns nonzero if content_type includes mediatype.
+ */
+static int check_content_type(const char *content_type, const char *media_type)
+{
+ const char *ptr = content_type;
+ size_t media_type_len = strlen(media_type);
+ for(; *ptr && (*ptr == ' ' || *ptr == '\t'); ++ptr);
+ if(!*ptr) {
+ return 0;
+ }
+ return Curl_raw_nequal(ptr, media_type, media_type_len) &&
+ (*(ptr+media_type_len) == '\0' || *(ptr+media_type_len) == ' ' ||
+ *(ptr+media_type_len) == '\t' || *(ptr+media_type_len) == ';');
+}
+
+int check_metalink_content_type(const char *content_type)
+{
+ return check_content_type(content_type, "application/metalink+xml");
+}
+
+int count_next_metalink_resource(metalinkfile *mlfile)
+{
+ int count = 0;
+ metalink_resource *res;
+ for(res = mlfile->resource; res; res = res->next, ++count);
+ return count;
+}
+
+static void delete_metalink_checksum(metalink_checksum *chksum)
+{
+ if(chksum == NULL) {
+ return;
+ }
+ Curl_safefree(chksum->digest);
+ Curl_safefree(chksum);
+}
+
+static void delete_metalink_resource(metalink_resource *res)
+{
+ if(res == NULL) {
+ return;
+ }
+ Curl_safefree(res->url);
+ Curl_safefree(res);
+}
+
+static void delete_metalinkfile(metalinkfile *mlfile)
+{
+ metalink_resource *res;
+ if(mlfile == NULL) {
+ return;
+ }
+ Curl_safefree(mlfile->filename);
+ delete_metalink_checksum(mlfile->checksum);
+ for(res = mlfile->resource; res;) {
+ metalink_resource *next;
+ next = res->next;
+ delete_metalink_resource(res);
+ res = next;
+ }
+ Curl_safefree(mlfile);
+}
+
+void clean_metalink(struct OperationConfig *config)
+{
+ while(config->metalinkfile_list) {
+ metalinkfile *mlfile = config->metalinkfile_list;
+ config->metalinkfile_list = config->metalinkfile_list->next;
+ delete_metalinkfile(mlfile);
+ }
+ config->metalinkfile_last = 0;
+}
+
+void metalink_cleanup(void)
+{
+#ifdef USE_NSS
+ if(nss_context) {
+ NSS_ShutdownContext(nss_context);
+ nss_context = NULL;
+ }
+#endif
+}
+
+#endif /* USE_METALINK */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_metalink.h b/external/libcurl_android/jni/libcurl/src/tool_metalink.h
new file mode 100755
index 00000000..36859068
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_metalink.h
@@ -0,0 +1,167 @@
+#ifndef HEADER_CURL_TOOL_METALINK_H
+#define HEADER_CURL_TOOL_METALINK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+struct GlobalConfig;
+struct OperationConfig;
+
+/* returns 1 for success, 0 otherwise (we use OpenSSL *_Init fncs directly) */
+typedef int (* Curl_digest_init_func)(void *context);
+
+typedef void (* Curl_digest_update_func)(void *context,
+ const unsigned char *data,
+ unsigned int len);
+typedef void (* Curl_digest_final_func)(unsigned char *result, void *context);
+
+typedef struct {
+ Curl_digest_init_func digest_init; /* Initialize context procedure */
+ Curl_digest_update_func digest_update; /* Update context with data */
+ Curl_digest_final_func digest_final; /* Get final result procedure */
+ unsigned int digest_ctxtsize; /* Context structure size */
+ unsigned int digest_resultlen; /* Result length (bytes) */
+} digest_params;
+
+typedef struct {
+ const digest_params *digest_hash; /* Hash function definition */
+ void *digest_hashctx; /* Hash function context */
+} digest_context;
+
+digest_context * Curl_digest_init(const digest_params *dparams);
+int Curl_digest_update(digest_context *context,
+ const unsigned char *data,
+ unsigned int len);
+int Curl_digest_final(digest_context *context, unsigned char *result);
+
+typedef struct {
+ const char *hash_name;
+ const digest_params *dparams;
+} metalink_digest_def;
+
+typedef struct {
+ const char *alias_name;
+ const metalink_digest_def *digest_def;
+} metalink_digest_alias;
+
+typedef struct metalink_checksum {
+ const metalink_digest_def *digest_def;
+ /* raw digest value, not ascii hex digest */
+ unsigned char *digest;
+} metalink_checksum;
+
+typedef struct metalink_resource {
+ struct metalink_resource *next;
+ char *url;
+} metalink_resource;
+
+typedef struct metalinkfile {
+ struct metalinkfile *next;
+ char *filename;
+ metalink_checksum *checksum;
+ metalink_resource *resource;
+} metalinkfile;
+
+#ifdef USE_METALINK
+
+/*
+ * curl requires libmetalink 0.1.0 or newer
+ */
+#define CURL_REQ_LIBMETALINK_MAJOR 0
+#define CURL_REQ_LIBMETALINK_MINOR 1
+#define CURL_REQ_LIBMETALINK_PATCH 0
+
+#define CURL_REQ_LIBMETALINK_VERS ((CURL_REQ_LIBMETALINK_MAJOR * 10000) + \
+ (CURL_REQ_LIBMETALINK_MINOR * 100) + \
+ CURL_REQ_LIBMETALINK_PATCH)
+
+extern const digest_params MD5_DIGEST_PARAMS[1];
+extern const digest_params SHA1_DIGEST_PARAMS[1];
+extern const digest_params SHA256_DIGEST_PARAMS[1];
+
+#include <metalink/metalink.h>
+
+/*
+ * Counts the resource in the metalinkfile.
+ */
+int count_next_metalink_resource(metalinkfile *mlfile);
+void clean_metalink(struct OperationConfig *config);
+
+/*
+ * Performs final parse operation and extracts information from
+ * Metalink and creates metalinkfile structs.
+ *
+ * This function returns 0 if it succeeds without warnings, or one of
+ * the following negative error codes:
+ *
+ * -1: Parsing failed; or no file is found
+ * -2: Parsing succeeded with some warnings.
+ */
+int parse_metalink(struct OperationConfig *config, struct OutStruct *outs,
+ const char *metalink_url);
+
+/*
+ * Callback function for CURLOPT_WRITEFUNCTION
+ */
+size_t metalink_write_cb(void *buffer, size_t sz, size_t nmemb,
+ void *userdata);
+
+/*
+ * Returns nonzero if content_type includes "application/metalink+xml"
+ * media-type. The check is done in case-insensitive manner.
+ */
+int check_metalink_content_type(const char *content_type);
+
+/*
+ * Check checksum of file denoted by filename.
+ *
+ * This function returns 1 if the checksum matches or one of the
+ * following integers:
+ *
+ * 0:
+ * Checksum didn't match.
+ * -1:
+ * Could not open file; or could not read data from file.
+ * -2:
+ * No checksum in Metalink supported, hash algorithm not available, or
+ * Metalink does not contain checksum.
+ */
+int metalink_check_hash(struct GlobalConfig *config,
+ metalinkfile *mlfile,
+ const char *filename);
+
+/*
+ * Release resources allocated at global scope.
+ */
+void metalink_cleanup(void);
+
+#else /* USE_METALINK */
+
+#define count_next_metalink_resource(x) 0
+#define clean_metalink(x) (void)x
+
+/* metalink_cleanup() takes no arguments */
+#define metalink_cleanup() Curl_nop_stmt
+
+#endif /* USE_METALINK */
+
+#endif /* HEADER_CURL_TOOL_METALINK_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_mfiles.c b/external/libcurl_android/jni/libcurl/src/tool_mfiles.c
new file mode 100755
index 00000000..3eda45f9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_mfiles.c
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_mfiles.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+static void AppendNode(struct multi_files **first,
+ struct multi_files **last,
+ struct multi_files *new)
+{
+ DEBUGASSERT(((*first) && (*last)) || ((!*first) && (!*last)));
+
+ if(*last)
+ (*last)->next = new;
+ else
+ *first = new;
+ *last = new;
+}
+
+/*
+ * AddMultiFiles: Add a new list node possibly followed with a type_name.
+ *
+ * multi_first argument is the address of a pointer to the first element
+ * of the multi_files linked list. A NULL pointer indicates empty list.
+ *
+ * multi_last argument is the address of a pointer to the last element
+ * of the multi_files linked list. A NULL pointer indicates empty list.
+ *
+ * Pointers stored in multi_first and multi_last are modified while
+ * function is executed. An out of memory condition free's the whole
+ * list and returns with pointers stored in multi_first and multi_last
+ * set to NULL and a NULL function result.
+ *
+ * Function returns same pointer as stored at multi_last.
+ */
+
+struct multi_files *AddMultiFiles(const char *file_name,
+ const char *type_name,
+ const char *show_filename,
+ struct multi_files **multi_first,
+ struct multi_files **multi_last)
+{
+ struct multi_files *multi;
+ struct multi_files *multi_type;
+ struct multi_files *multi_name;
+
+ multi = calloc(1, sizeof(struct multi_files));
+ if(multi) {
+ multi->form.option = CURLFORM_FILE;
+ multi->form.value = file_name;
+ AppendNode(multi_first, multi_last, multi);
+ }
+ else {
+ FreeMultiInfo(multi_first, multi_last);
+ return NULL;
+ }
+
+ if(type_name) {
+ multi_type = calloc(1, sizeof(struct multi_files));
+ if(multi_type) {
+ multi_type->form.option = CURLFORM_CONTENTTYPE;
+ multi_type->form.value = type_name;
+ AppendNode(multi_first, multi_last, multi_type);
+ }
+ else {
+ FreeMultiInfo(multi_first, multi_last);
+ return NULL;
+ }
+ }
+
+ if(show_filename) {
+ multi_name = calloc(1, sizeof(struct multi_files));
+ if(multi_name) {
+ multi_name->form.option = CURLFORM_FILENAME;
+ multi_name->form.value = show_filename;
+ AppendNode(multi_first, multi_last, multi_name);
+ }
+ else {
+ FreeMultiInfo(multi_first, multi_last);
+ return NULL;
+ }
+ }
+
+ return *multi_last;
+}
+
+/*
+ * FreeMultiInfo: Free the items of the list.
+ */
+
+void FreeMultiInfo(struct multi_files **multi_first,
+ struct multi_files **multi_last)
+{
+ struct multi_files *next;
+ struct multi_files *item = *multi_first;
+
+ while(item) {
+ next = item->next;
+ Curl_safefree(item);
+ item = next;
+ }
+ *multi_first = NULL;
+ if(multi_last)
+ *multi_last = NULL;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_mfiles.h b/external/libcurl_android/jni/libcurl/src/tool_mfiles.h
new file mode 100755
index 00000000..1ea6f4a4
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_mfiles.h
@@ -0,0 +1,46 @@
+#ifndef HEADER_CURL_TOOL_MFILES_H
+#define HEADER_CURL_TOOL_MFILES_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+ * Structure for storing the information needed to build
+ * a multiple files section.
+ */
+
+struct multi_files {
+ struct curl_forms form;
+ struct multi_files *next;
+};
+
+struct multi_files *AddMultiFiles(const char *file_name,
+ const char *type_name,
+ const char *show_filename,
+ struct multi_files **multi_first,
+ struct multi_files **multi_last);
+
+void FreeMultiInfo(struct multi_files **multi_first,
+ struct multi_files **multi_last);
+
+#endif /* HEADER_CURL_TOOL_MFILES_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_msgs.c b/external/libcurl_android/jni/libcurl/src/tool_msgs.c
new file mode 100755
index 00000000..3311b55f
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_msgs.c
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#define WARN_PREFIX "Warning: "
+#define WARN_TEXTWIDTH (79 - (int)strlen(WARN_PREFIX))
+
+/*
+ * Emit warning formatted message on configured 'errors' stream unless
+ * mute (--silent) was selected.
+ */
+
+void warnf(struct OperationConfig *config, const char *fmt, ...)
+{
+ if(!config->global->mute) {
+ va_list ap;
+ int len;
+ char *ptr;
+ char print_buffer[256];
+
+ va_start(ap, fmt);
+ len = vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
+ va_end(ap);
+
+ ptr = print_buffer;
+ while(len > 0) {
+ fputs(WARN_PREFIX, config->global->errors);
+
+ if(len > (int)WARN_TEXTWIDTH) {
+ int cut = WARN_TEXTWIDTH-1;
+
+ while(!ISSPACE(ptr[cut]) && cut) {
+ cut--;
+ }
+ if(0 == cut)
+ /* not a single cutting position was found, just cut it at the
+ max text width then! */
+ cut = WARN_TEXTWIDTH-1;
+
+ (void)fwrite(ptr, cut + 1, 1, config->global->errors);
+ fputs("\n", config->global->errors);
+ ptr += cut+1; /* skip the space too */
+ len -= cut;
+ }
+ else {
+ fputs(ptr, config->global->errors);
+ len = 0;
+ }
+ }
+ }
+}
+
+/*
+ * Emit help formatted message on given stream.
+ */
+
+void helpf(FILE *errors, const char *fmt, ...)
+{
+ va_list ap;
+ if(fmt) {
+ va_start(ap, fmt);
+ fputs("curl: ", errors); /* prefix it */
+ vfprintf(errors, fmt, ap);
+ va_end(ap);
+ }
+ fprintf(errors, "curl: try 'curl --help' "
+#ifdef USE_MANUAL
+ "or 'curl --manual' "
+#endif
+ "for more information\n");
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_msgs.h b/external/libcurl_android/jni/libcurl/src/tool_msgs.h
new file mode 100755
index 00000000..15754690
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_msgs.h
@@ -0,0 +1,31 @@
+#ifndef HEADER_CURL_TOOL_MSGS_H
+#define HEADER_CURL_TOOL_MSGS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void warnf(struct OperationConfig *config, const char *fmt, ...);
+
+void helpf(FILE *errors, const char *fmt, ...);
+
+#endif /* HEADER_CURL_TOOL_MSGS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_operate.c b/external/libcurl_android/jni/libcurl/src/tool_operate.c
new file mode 100755
index 00000000..fd2fd6dd
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_operate.c
@@ -0,0 +1,1858 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_UTIME_H
+# include <utime.h>
+#elif defined(HAVE_SYS_UTIME_H)
+# include <sys/utime.h>
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+
+#ifdef __VMS
+# include <fabdef.h>
+#endif
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_binmode.h"
+#include "tool_cfgable.h"
+#include "tool_cb_dbg.h"
+#include "tool_cb_hdr.h"
+#include "tool_cb_prg.h"
+#include "tool_cb_rea.h"
+#include "tool_cb_see.h"
+#include "tool_cb_wrt.h"
+#include "tool_dirhie.h"
+#include "tool_doswin.h"
+#include "tool_easysrc.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+#include "tool_homedir.h"
+#include "tool_libinfo.h"
+#include "tool_main.h"
+#include "tool_metalink.h"
+#include "tool_msgs.h"
+#include "tool_operate.h"
+#include "tool_operhlp.h"
+#include "tool_paramhlp.h"
+#include "tool_parsecfg.h"
+#include "tool_setopt.h"
+#include "tool_sleep.h"
+#include "tool_urlglob.h"
+#include "tool_util.h"
+#include "tool_writeenv.h"
+#include "tool_writeout.h"
+#include "tool_xattr.h"
+#include "tool_vms.h"
+#include "tool_help.h"
+#include "tool_hugehelp.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef CURLDEBUG
+/* libcurl's debug builds provide an extra function */
+CURLcode curl_easy_perform_ev(CURL *easy);
+#endif
+
+#define CURLseparator "--_curl_--"
+
+#ifndef O_BINARY
+/* since O_BINARY as used in bitmasks, setting it to zero makes it usable in
+ source code but yet it doesn't ruin anything */
+# define O_BINARY 0
+#endif
+
+#define CURL_CA_CERT_ERRORMSG1 \
+ "More details here: http://curl.haxx.se/docs/sslcerts.html\n\n" \
+ "curl performs SSL certificate verification by default, " \
+ "using a \"bundle\"\n" \
+ " of Certificate Authority (CA) public keys (CA certs). If the default\n" \
+ " bundle file isn't adequate, you can specify an alternate file\n" \
+ " using the --cacert option.\n"
+
+#define CURL_CA_CERT_ERRORMSG2 \
+ "If this HTTPS server uses a certificate signed by a CA represented in\n" \
+ " the bundle, the certificate verification probably failed due to a\n" \
+ " problem with the certificate (it might be expired, or the name might\n" \
+ " not match the domain name in the URL).\n" \
+ "If you'd like to turn off curl's verification of the certificate, use\n" \
+ " the -k (or --insecure) option.\n"
+
+static bool is_fatal_error(CURLcode code)
+{
+ switch(code) {
+ /* TODO: Should CURLE_SSL_CACERT be included as critical error ? */
+ case CURLE_FAILED_INIT:
+ case CURLE_OUT_OF_MEMORY:
+ case CURLE_UNKNOWN_OPTION:
+ case CURLE_FUNCTION_NOT_FOUND:
+ case CURLE_BAD_FUNCTION_ARGUMENT:
+ /* critical error */
+ return TRUE;
+ default:
+ break;
+ }
+
+ /* no error or not critical */
+ return FALSE;
+}
+
+#ifdef __VMS
+/*
+ * get_vms_file_size does what it takes to get the real size of the file
+ *
+ * For fixed files, find out the size of the EOF block and adjust.
+ *
+ * For all others, have to read the entire file in, discarding the contents.
+ * Most posted text files will be small, and binary files like zlib archives
+ * and CD/DVD images should be either a STREAM_LF format or a fixed format.
+ *
+ */
+static curl_off_t vms_realfilesize(const char * name,
+ const struct_stat * stat_buf)
+{
+ char buffer[8192];
+ curl_off_t count;
+ int ret_stat;
+ FILE * file;
+
+ file = fopen(name, "r");
+ if(file == NULL) {
+ return 0;
+ }
+ count = 0;
+ ret_stat = 1;
+ while(ret_stat > 0) {
+ ret_stat = fread(buffer, 1, sizeof(buffer), file);
+ if(ret_stat != 0)
+ count += ret_stat;
+ }
+ fclose(file);
+
+ return count;
+}
+
+/*
+ *
+ * VmsSpecialSize checks to see if the stat st_size can be trusted and
+ * if not to call a routine to get the correct size.
+ *
+ */
+static curl_off_t VmsSpecialSize(const char * name,
+ const struct_stat * stat_buf)
+{
+ switch(stat_buf->st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ return vms_realfilesize(name, stat_buf);
+ break;
+ default:
+ return stat_buf->st_size;
+ }
+}
+#endif /* __VMS */
+
+static CURLcode operate_do(struct GlobalConfig *global,
+ struct OperationConfig *config)
+{
+ char errorbuffer[CURL_ERROR_SIZE];
+ struct ProgressData progressbar;
+ struct getout *urlnode;
+
+ struct HdrCbData hdrcbdata;
+ struct OutStruct heads;
+
+ metalinkfile *mlfile_last = NULL;
+
+ CURL *curl = config->easy;
+ char *httpgetfields = NULL;
+
+ CURLcode res = CURLE_OK;
+ unsigned long li;
+
+ /* Save the values of noprogress and isatty to restore them later on */
+ bool orig_noprogress = global->noprogress;
+ bool orig_isatty = global->isatty;
+
+ errorbuffer[0] = '\0';
+
+ /* default headers output stream is stdout */
+ memset(&hdrcbdata, 0, sizeof(struct HdrCbData));
+ memset(&heads, 0, sizeof(struct OutStruct));
+ heads.stream = stdout;
+ heads.config = config;
+
+ /*
+ ** Beyond this point no return'ing from this function allowed.
+ ** Jump to label 'quit_curl' in order to abandon this function
+ ** from outside of nested loops further down below.
+ */
+
+ /* Check we have a url */
+ if(!config->url_list || !config->url_list->url) {
+ helpf(global->errors, "no URL specified!\n");
+ res = CURLE_FAILED_INIT;
+ goto quit_curl;
+ }
+
+ /* On WIN32 we can't set the path to curl-ca-bundle.crt
+ * at compile time. So we look here for the file in two ways:
+ * 1: look at the environment variable CURL_CA_BUNDLE for a path
+ * 2: if #1 isn't found, use the windows API function SearchPath()
+ * to find it along the app's path (includes app's dir and CWD)
+ *
+ * We support the environment variable thing for non-Windows platforms
+ * too. Just for the sake of it.
+ */
+ if(!config->cacert &&
+ !config->capath &&
+ !config->insecure_ok) {
+ char *env;
+ env = curlx_getenv("CURL_CA_BUNDLE");
+ if(env) {
+ config->cacert = strdup(env);
+ if(!config->cacert) {
+ curl_free(env);
+ helpf(global->errors, "out of memory\n");
+ res = CURLE_OUT_OF_MEMORY;
+ goto quit_curl;
+ }
+ }
+ else {
+ env = curlx_getenv("SSL_CERT_DIR");
+ if(env) {
+ config->capath = strdup(env);
+ if(!config->capath) {
+ curl_free(env);
+ helpf(global->errors, "out of memory\n");
+ res = CURLE_OUT_OF_MEMORY;
+ goto quit_curl;
+ }
+ }
+ else {
+ env = curlx_getenv("SSL_CERT_FILE");
+ if(env) {
+ config->cacert = strdup(env);
+ if(!config->cacert) {
+ curl_free(env);
+ helpf(global->errors, "out of memory\n");
+ res = CURLE_OUT_OF_MEMORY;
+ goto quit_curl;
+ }
+ }
+ }
+ }
+
+ if(env)
+ curl_free(env);
+#ifdef WIN32
+ else {
+ res = FindWin32CACert(config, "curl-ca-bundle.crt");
+ if(res)
+ goto quit_curl;
+ }
+#endif
+ }
+
+ if(config->postfields) {
+ if(config->use_httpget) {
+ /* Use the postfields data for a http get */
+ httpgetfields = strdup(config->postfields);
+ Curl_safefree(config->postfields);
+ if(!httpgetfields) {
+ helpf(global->errors, "out of memory\n");
+ res = CURLE_OUT_OF_MEMORY;
+ goto quit_curl;
+ }
+ if(SetHTTPrequest(config,
+ (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
+ &config->httpreq)) {
+ res = CURLE_FAILED_INIT;
+ goto quit_curl;
+ }
+ }
+ else {
+ if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq)) {
+ res = CURLE_FAILED_INIT;
+ goto quit_curl;
+ }
+ }
+ }
+
+ /* Single header file for all URLs */
+ if(config->headerfile) {
+ /* open file for output: */
+ if(!curlx_strequal(config->headerfile, "-")) {
+ FILE *newfile = fopen(config->headerfile, "wb");
+ if(!newfile) {
+ warnf(config, "Failed to open %s\n", config->headerfile);
+ res = CURLE_WRITE_ERROR;
+ goto quit_curl;
+ }
+ else {
+ heads.filename = config->headerfile;
+ heads.s_isreg = TRUE;
+ heads.fopened = TRUE;
+ heads.stream = newfile;
+ }
+ }
+ else {
+ /* always use binary mode for protocol header output */
+ set_binmode(heads.stream);
+ }
+ }
+
+ /*
+ ** Nested loops start here.
+ */
+
+ /* loop through the list of given URLs */
+
+ for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) {
+
+ unsigned long up; /* upload file counter within a single upload glob */
+ char *infiles; /* might be a glob pattern */
+ char *outfiles;
+ unsigned long infilenum;
+ URLGlob *inglob;
+
+ int metalink = 0; /* nonzero for metalink download. */
+ metalinkfile *mlfile;
+ metalink_resource *mlres;
+
+ outfiles = NULL;
+ infilenum = 1;
+ inglob = NULL;
+
+ if(urlnode->flags & GETOUT_METALINK) {
+ metalink = 1;
+ if(mlfile_last == NULL) {
+ mlfile_last = config->metalinkfile_list;
+ }
+ mlfile = mlfile_last;
+ mlfile_last = mlfile_last->next;
+ mlres = mlfile->resource;
+ }
+ else {
+ mlfile = NULL;
+ mlres = NULL;
+ }
+
+ /* urlnode->url is the full URL (it might be NULL) */
+
+ if(!urlnode->url) {
+ /* This node has no URL. Free node data without destroying the
+ node itself nor modifying next pointer and continue to next */
+ Curl_safefree(urlnode->outfile);
+ Curl_safefree(urlnode->infile);
+ urlnode->flags = 0;
+ continue; /* next URL please */
+ }
+
+ /* save outfile pattern before expansion */
+ if(urlnode->outfile) {
+ outfiles = strdup(urlnode->outfile);
+ if(!outfiles) {
+ helpf(global->errors, "out of memory\n");
+ res = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ infiles = urlnode->infile;
+
+ if(!config->globoff && infiles) {
+ /* Unless explicitly shut off */
+ res = (CURLcode) glob_url(&inglob, infiles, &infilenum,
+ global->showerror?global->errors:NULL);
+ if(res) {
+ Curl_safefree(outfiles);
+ break;
+ }
+ }
+
+ /* Here's the loop for uploading multiple files within the same
+ single globbed string. If no upload, we enter the loop once anyway. */
+ for(up = 0 ; up < infilenum; up++) {
+
+ char *uploadfile; /* a single file, never a glob */
+ int separator;
+ URLGlob *urls;
+ unsigned long urlnum;
+
+ uploadfile = NULL;
+ urls = NULL;
+ urlnum = 0;
+
+ if(!up && !infiles)
+ Curl_nop_stmt;
+ else {
+ if(inglob) {
+ res = (CURLcode) glob_next_url(&uploadfile, inglob);
+ if(res == CURLE_OUT_OF_MEMORY)
+ helpf(global->errors, "out of memory\n");
+ }
+ else if(!up) {
+ uploadfile = strdup(infiles);
+ if(!uploadfile) {
+ helpf(global->errors, "out of memory\n");
+ res = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else
+ uploadfile = NULL;
+ if(!uploadfile)
+ break;
+ }
+
+ if(metalink) {
+ /* For Metalink download, we don't use glob. Instead we use
+ the number of resources as urlnum. */
+ urlnum = count_next_metalink_resource(mlfile);
+ }
+ else
+ if(!config->globoff) {
+ /* Unless explicitly shut off, we expand '{...}' and '[...]'
+ expressions and return total number of URLs in pattern set */
+ res = (CURLcode) glob_url(&urls, urlnode->url, &urlnum,
+ global->showerror?global->errors:NULL);
+ if(res) {
+ Curl_safefree(uploadfile);
+ break;
+ }
+ }
+ else
+ urlnum = 1; /* without globbing, this is a single URL */
+
+ /* if multiple files extracted to stdout, insert separators! */
+ separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
+
+ /* Here's looping around each globbed URL */
+ for(li = 0 ; li < urlnum; li++) {
+
+ int infd;
+ bool infdopen;
+ char *outfile;
+ struct OutStruct outs;
+ struct InStruct input;
+ struct timeval retrystart;
+ curl_off_t uploadfilesize;
+ long retry_numretries;
+ long retry_sleep_default;
+ long retry_sleep;
+ char *this_url = NULL;
+ int metalink_next_res = 0;
+
+ outfile = NULL;
+ infdopen = FALSE;
+ infd = STDIN_FILENO;
+ uploadfilesize = -1; /* -1 means unknown */
+
+ /* default output stream is stdout */
+ memset(&outs, 0, sizeof(struct OutStruct));
+ outs.stream = stdout;
+ outs.config = config;
+
+ if(metalink) {
+ /* For Metalink download, use name in Metalink file as
+ filename. */
+ outfile = strdup(mlfile->filename);
+ if(!outfile) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+ this_url = strdup(mlres->url);
+ if(!this_url) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+ }
+ else {
+ if(urls) {
+ res = (CURLcode) glob_next_url(&this_url, urls);
+ if(res)
+ goto show_error;
+ }
+ else if(!li) {
+ this_url = strdup(urlnode->url);
+ if(!this_url) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+ }
+ else
+ this_url = NULL;
+ if(!this_url)
+ break;
+
+ if(outfiles) {
+ outfile = strdup(outfiles);
+ if(!outfile) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+ }
+ }
+
+ if(((urlnode->flags&GETOUT_USEREMOTE) ||
+ (outfile && !curlx_strequal("-", outfile))) &&
+ (metalink || !config->use_metalink)) {
+
+ /*
+ * We have specified a file name to store the result in, or we have
+ * decided we want to use the remote file name.
+ */
+
+ if(!outfile) {
+ /* extract the file name from the URL */
+ res = get_url_file_name(&outfile, this_url);
+ if(res)
+ goto show_error;
+ if((!outfile || !*outfile) && !config->content_disposition) {
+ helpf(global->errors, "Remote file name has no length!\n");
+ res = CURLE_WRITE_ERROR;
+ goto quit_urls;
+ }
+#if defined(MSDOS) || defined(WIN32)
+ /* For DOS and WIN32, we do some major replacing of
+ bad characters in the file name before using it */
+ outfile = sanitize_dos_name(outfile);
+ if(!outfile) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+#endif /* MSDOS || WIN32 */
+ }
+ else if(urls) {
+ /* fill '#1' ... '#9' terms from URL pattern */
+ char *storefile = outfile;
+ res = (CURLcode) glob_match_url(&outfile, storefile, urls);
+ Curl_safefree(storefile);
+ if(res) {
+ /* bad globbing */
+ warnf(config, "bad output glob!\n");
+ goto quit_urls;
+ }
+ }
+
+ /* Create the directory hierarchy, if not pre-existent to a multiple
+ file output call */
+
+ if(config->create_dirs || metalink) {
+ res = create_dir_hierarchy(outfile, global->errors);
+ /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
+ if(res == CURLE_WRITE_ERROR)
+ goto quit_urls;
+ if(res) {
+ goto show_error;
+ }
+ }
+
+ if((urlnode->flags & GETOUT_USEREMOTE)
+ && config->content_disposition) {
+ /* Our header callback MIGHT set the filename */
+ DEBUGASSERT(!outs.filename);
+ }
+
+ if(config->resume_from_current) {
+ /* We're told to continue from where we are now. Get the size
+ of the file as it is now and open it for append instead */
+ struct_stat fileinfo;
+ /* VMS -- Danger, the filesize is only valid for stream files */
+ if(0 == stat(outfile, &fileinfo))
+ /* set offset to current file size: */
+ config->resume_from = fileinfo.st_size;
+ else
+ /* let offset be 0 */
+ config->resume_from = 0;
+ }
+
+ if(config->resume_from) {
+#ifdef __VMS
+ /* open file for output, forcing VMS output format into stream
+ mode which is needed for stat() call above to always work. */
+ FILE *file = fopen(outfile, config->resume_from?"ab":"wb",
+ "ctx=stm", "rfm=stmlf", "rat=cr", "mrs=0");
+#else
+ /* open file for output: */
+ FILE *file = fopen(outfile, config->resume_from?"ab":"wb");
+#endif
+ if(!file) {
+ helpf(global->errors, "Can't open '%s'!\n", outfile);
+ res = CURLE_WRITE_ERROR;
+ goto quit_urls;
+ }
+ outs.fopened = TRUE;
+ outs.stream = file;
+ outs.init = config->resume_from;
+ }
+ else {
+ outs.stream = NULL; /* open when needed */
+ }
+ outs.filename = outfile;
+ outs.s_isreg = TRUE;
+ }
+
+ if(uploadfile && !stdin_upload(uploadfile)) {
+ /*
+ * We have specified a file to upload and it isn't "-".
+ */
+ struct_stat fileinfo;
+
+ this_url = add_file_name_to_url(curl, this_url, uploadfile);
+ if(!this_url) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+ /* VMS Note:
+ *
+ * Reading binary from files can be a problem... Only FIXED, VAR
+ * etc WITHOUT implied CC will work Others need a \n appended to a
+ * line
+ *
+ * - Stat gives a size but this is UNRELIABLE in VMS As a f.e. a
+ * fixed file with implied CC needs to have a byte added for every
+ * record processed, this can by derived from Filesize & recordsize
+ * for VARiable record files the records need to be counted! for
+ * every record add 1 for linefeed and subtract 2 for the record
+ * header for VARIABLE header files only the bare record data needs
+ * to be considered with one appended if implied CC
+ */
+#ifdef __VMS
+ /* Calculate the real upload site for VMS */
+ infd = -1;
+ if(stat(uploadfile, &fileinfo) == 0) {
+ fileinfo.st_size = VmsSpecialSize(uploadfile, &fileinfo);
+ switch (fileinfo.st_fab_rfm) {
+ case FAB$C_VAR:
+ case FAB$C_VFC:
+ case FAB$C_STMCR:
+ infd = open(uploadfile, O_RDONLY | O_BINARY);
+ break;
+ default:
+ infd = open(uploadfile, O_RDONLY | O_BINARY,
+ "rfm=stmlf", "ctx=stm");
+ }
+ }
+ if(infd == -1)
+#else
+ infd = open(uploadfile, O_RDONLY | O_BINARY);
+ if((infd == -1) || fstat(infd, &fileinfo))
+#endif
+ {
+ helpf(global->errors, "Can't open '%s'!\n", uploadfile);
+ if(infd != -1) {
+ close(infd);
+ infd = STDIN_FILENO;
+ }
+ res = CURLE_READ_ERROR;
+ goto quit_urls;
+ }
+ infdopen = TRUE;
+
+ /* we ignore file size for char/block devices, sockets, etc. */
+ if(S_ISREG(fileinfo.st_mode))
+ uploadfilesize = fileinfo.st_size;
+
+ }
+ else if(uploadfile && stdin_upload(uploadfile)) {
+ /* count to see if there are more than one auth bit set
+ in the authtype field */
+ int authbits = 0;
+ int bitcheck = 0;
+ while(bitcheck < 32) {
+ if(config->authtype & (1UL << bitcheck++)) {
+ authbits++;
+ if(authbits > 1) {
+ /* more than one, we're done! */
+ break;
+ }
+ }
+ }
+
+ /*
+ * If the user has also selected --anyauth or --proxy-anyauth
+ * we should warn him/her.
+ */
+ if(config->proxyanyauth || (authbits>1)) {
+ warnf(config,
+ "Using --anyauth or --proxy-anyauth with upload from stdin"
+ " involves a big risk of it not working. Use a temporary"
+ " file or a fixed auth type instead!\n");
+ }
+
+ DEBUGASSERT(infdopen == FALSE);
+ DEBUGASSERT(infd == STDIN_FILENO);
+
+ set_binmode(stdin);
+ if(curlx_strequal(uploadfile, ".")) {
+ if(curlx_nonblock((curl_socket_t)infd, TRUE) < 0)
+ warnf(config,
+ "fcntl failed on fd=%d: %s\n", infd, strerror(errno));
+ }
+ }
+
+ if(uploadfile && config->resume_from_current)
+ config->resume_from = -1; /* -1 will then force get-it-yourself */
+
+ if(output_expected(this_url, uploadfile) && outs.stream &&
+ isatty(fileno(outs.stream)))
+ /* we send the output to a tty, therefore we switch off the progress
+ meter */
+ global->noprogress = global->isatty = TRUE;
+ else {
+ /* progress meter is per download, so restore config
+ values */
+ global->noprogress = orig_noprogress;
+ global->isatty = orig_isatty;
+ }
+
+ if(urlnum > 1 && !global->mute) {
+ fprintf(global->errors, "\n[%lu/%lu]: %s --> %s\n",
+ li+1, urlnum, this_url, outfile ? outfile : "<stdout>");
+ if(separator)
+ printf("%s%s\n", CURLseparator, this_url);
+ }
+ if(httpgetfields) {
+ char *urlbuffer;
+ /* Find out whether the url contains a file name */
+ const char *pc = strstr(this_url, "://");
+ char sep = '?';
+ if(pc)
+ pc += 3;
+ else
+ pc = this_url;
+
+ pc = strrchr(pc, '/'); /* check for a slash */
+
+ if(pc) {
+ /* there is a slash present in the URL */
+
+ if(strchr(pc, '?'))
+ /* Ouch, there's already a question mark in the URL string, we
+ then append the data with an ampersand separator instead! */
+ sep='&';
+ }
+ /*
+ * Then append ? followed by the get fields to the url.
+ */
+ if(pc)
+ urlbuffer = aprintf("%s%c%s", this_url, sep, httpgetfields);
+ else
+ /* Append / before the ? to create a well-formed url
+ if the url contains a hostname only
+ */
+ urlbuffer = aprintf("%s/?%s", this_url, httpgetfields);
+
+ if(!urlbuffer) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+
+ Curl_safefree(this_url); /* free previous URL */
+ this_url = urlbuffer; /* use our new URL instead! */
+ }
+
+ if(!global->errors)
+ global->errors = stderr;
+
+ if((!outfile || !strcmp(outfile, "-")) && !config->use_ascii) {
+ /* We get the output to stdout and we have not got the ASCII/text
+ flag, then set stdout to be binary */
+ set_binmode(stdout);
+ }
+
+ if(config->tcp_nodelay)
+ my_setopt(curl, CURLOPT_TCP_NODELAY, 1L);
+
+ /* where to store */
+ my_setopt(curl, CURLOPT_WRITEDATA, &outs);
+ if(metalink || !config->use_metalink)
+ /* what call to write */
+ my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
+#ifdef USE_METALINK
+ else
+ /* Set Metalink specific write callback function to parse
+ XML data progressively. */
+ my_setopt(curl, CURLOPT_WRITEFUNCTION, metalink_write_cb);
+#endif /* USE_METALINK */
+
+ /* for uploads */
+ input.fd = infd;
+ input.config = config;
+ /* Note that if CURLOPT_READFUNCTION is fread (the default), then
+ * lib/telnet.c will Curl_poll() on the input file descriptor
+ * rather then calling the READFUNCTION at regular intervals.
+ * The circumstances in which it is preferable to enable this
+ * behaviour, by omitting to set the READFUNCTION & READDATA options,
+ * have not been determined.
+ */
+ my_setopt(curl, CURLOPT_READDATA, &input);
+ /* what call to read */
+ my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
+
+ /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
+ CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
+ my_setopt(curl, CURLOPT_SEEKDATA, &input);
+ my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
+
+ if(config->recvpersecond)
+ /* tell libcurl to use a smaller sized buffer as it allows us to
+ make better sleeps! 7.9.9 stuff! */
+ my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
+
+ /* size of uploaded file: */
+ if(uploadfilesize != -1)
+ my_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
+ my_setopt_str(curl, CURLOPT_URL, this_url); /* what to fetch */
+ my_setopt(curl, CURLOPT_NOPROGRESS, global->noprogress?1L:0L);
+ if(config->no_body) {
+ my_setopt(curl, CURLOPT_NOBODY, 1L);
+ my_setopt(curl, CURLOPT_HEADER, 1L);
+ }
+ /* If --metalink is used, we ignore --include (headers in
+ output) option because mixing headers to the body will
+ confuse XML parser and/or hash check will fail. */
+ else if(!config->use_metalink)
+ my_setopt(curl, CURLOPT_HEADER, config->include_headers?1L:0L);
+
+ if(config->xoauth2_bearer)
+ my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->xoauth2_bearer);
+
+#if !defined(CURL_DISABLE_PROXY)
+ {
+ /* TODO: Make this a run-time check instead of compile-time one. */
+
+ my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
+ my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
+
+ /* new in libcurl 7.3 */
+ my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel?1L:0L);
+
+ /* new in libcurl 7.5 */
+ if(config->proxy)
+ my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->proxyver);
+
+ /* new in libcurl 7.10 */
+ if(config->socksproxy) {
+ my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
+ my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->socksver);
+ }
+
+ /* new in libcurl 7.10.6 */
+ if(config->proxyanyauth)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_ANY);
+ else if(config->proxynegotiate)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_GSSNEGOTIATE);
+ else if(config->proxyntlm)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_NTLM);
+ else if(config->proxydigest)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_DIGEST);
+ else if(config->proxybasic)
+ my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
+ (long)CURLAUTH_BASIC);
+
+ /* new in libcurl 7.19.4 */
+ my_setopt(curl, CURLOPT_NOPROXY, config->noproxy);
+ }
+#endif
+
+ my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror?1L:0L);
+ my_setopt(curl, CURLOPT_UPLOAD, uploadfile?1L:0L);
+ my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly?1L:0L);
+ my_setopt(curl, CURLOPT_APPEND, config->ftp_append?1L:0L);
+
+ if(config->netrc_opt)
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL);
+ else if(config->netrc || config->netrc_file)
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_REQUIRED);
+ else
+ my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_IGNORED);
+
+ if(config->netrc_file)
+ my_setopt(curl, CURLOPT_NETRC_FILE, config->netrc_file);
+
+ my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii?1L:0L);
+ if(config->login_options)
+ my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
+ my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
+ my_setopt_str(curl, CURLOPT_RANGE, config->range);
+ my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
+ my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
+
+ if(built_in_protos & CURLPROTO_HTTP) {
+
+ long postRedir = 0;
+
+ my_setopt(curl, CURLOPT_FOLLOWLOCATION,
+ config->followlocation?1L:0L);
+ my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
+ config->unrestricted_auth?1L:0L);
+
+ switch(config->httpreq) {
+ case HTTPREQ_SIMPLEPOST:
+ my_setopt_str(curl, CURLOPT_POSTFIELDS,
+ config->postfields);
+ my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
+ config->postfieldsize);
+ break;
+ case HTTPREQ_POST:
+ my_setopt_httppost(curl, CURLOPT_HTTPPOST, config->httppost);
+ break;
+ default:
+ break;
+ }
+
+ my_setopt_str(curl, CURLOPT_REFERER, config->referer);
+ my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer?1L:0L);
+ my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
+ my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
+
+ /* new in libcurl 7.36.0 */
+ if(config->proxyheaders) {
+ my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
+ my_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
+ }
+
+ /* new in libcurl 7.5 */
+ my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
+
+ /* new in libcurl 7.9.1 */
+ if(config->httpversion)
+ my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
+
+ /* new in libcurl 7.10.6 (default is Basic) */
+ if(config->authtype)
+ my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype);
+
+ /* curl 7.19.1 (the 301 version existed in 7.18.2),
+ 303 was added in 7.26.0 */
+ if(config->post301)
+ postRedir |= CURL_REDIR_POST_301;
+ if(config->post302)
+ postRedir |= CURL_REDIR_POST_302;
+ if(config->post303)
+ postRedir |= CURL_REDIR_POST_303;
+ my_setopt(curl, CURLOPT_POSTREDIR, postRedir);
+
+ /* new in libcurl 7.21.6 */
+ if(config->encoding)
+ my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, "");
+
+ /* new in libcurl 7.21.6 */
+ if(config->tr_encoding)
+ my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L);
+
+ } /* (built_in_protos & CURLPROTO_HTTP) */
+
+ my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
+ my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
+ config->low_speed_limit);
+ my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
+ my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE,
+ config->sendpersecond);
+ my_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE,
+ config->recvpersecond);
+
+ if(config->use_resume)
+ my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from);
+ else
+ my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
+
+ my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
+ my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
+ my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
+ my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
+ my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
+
+ if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
+
+ /* SSH and SSL private key uses same command-line option */
+ /* new in libcurl 7.16.1 */
+ my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
+ /* new in libcurl 7.16.1 */
+ my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
+
+ /* new in libcurl 7.17.1: SSH host key md5 checking allows us
+ to fail if we are not talking to who we think we should */
+ my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
+ config->hostpubmd5);
+ }
+
+ if(config->cacert)
+ my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
+ if(config->capath)
+ my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
+ if(config->crlfile)
+ my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
+
+ if(curlinfo->features & CURL_VERSION_SSL) {
+ if(config->insecure_ok) {
+ my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ }
+ else {
+ my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
+ /* libcurl default is strict verifyhost -> 2L */
+ /* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
+ }
+ }
+
+ if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
+ if(!config->insecure_ok) {
+ char *home;
+ char *file;
+ res = CURLE_OUT_OF_MEMORY;
+ home = homedir();
+ if(home) {
+ file = aprintf("%s/%sssh/known_hosts", home, DOT_CHAR);
+ if(file) {
+ /* new in curl 7.19.6 */
+ res = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, file);
+ curl_free(file);
+ if(res == CURLE_UNKNOWN_OPTION)
+ /* libssh2 version older than 1.1.1 */
+ res = CURLE_OK;
+ }
+ Curl_safefree(home);
+ }
+ if(res)
+ goto show_error;
+ }
+ }
+
+ if(config->no_body || config->remote_time) {
+ /* no body or use remote time */
+ my_setopt(curl, CURLOPT_FILETIME, 1L);
+ }
+
+ my_setopt(curl, CURLOPT_CRLF, config->crlf?1L:0L);
+ my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
+ my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
+ my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+ if(config->cookie)
+ my_setopt_str(curl, CURLOPT_COOKIE, config->cookie);
+
+ if(config->cookiefile)
+ my_setopt_str(curl, CURLOPT_COOKIEFILE, config->cookiefile);
+
+ /* new in libcurl 7.9 */
+ if(config->cookiejar)
+ my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
+
+ /* new in libcurl 7.9.7 */
+ my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession?1L:0L);
+#else
+ if(config->cookie || config->cookiefile || config->cookiejar) {
+ warnf(config, "cookie option(s) used even though cookie support "
+ "is disabled!\n");
+ return CURLE_NOT_BUILT_IN;
+ }
+#endif
+
+ my_setopt_enum(curl, CURLOPT_SSLVERSION, config->ssl_version);
+ my_setopt_enum(curl, CURLOPT_TIMECONDITION, (long)config->timecond);
+ my_setopt(curl, CURLOPT_TIMEVALUE, (long)config->condtime);
+ my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
+ my_setopt(curl, CURLOPT_STDERR, global->errors);
+
+ /* three new ones in libcurl 7.3: */
+ my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
+ my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel);
+
+ progressbarinit(&progressbar, config);
+ if((global->progressmode == CURL_PROGRESS_BAR) &&
+ !global->noprogress && !global->mute) {
+ /* we want the alternative style, then we have to implement it
+ ourselves! */
+ my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
+ my_setopt(curl, CURLOPT_XFERINFODATA, &progressbar);
+ }
+
+ /* new in libcurl 7.24.0: */
+ if(config->dns_servers)
+ my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
+
+ /* new in libcurl 7.33.0: */
+ if(config->dns_interface)
+ my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
+ if(config->dns_ipv4_addr)
+ my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
+ if(config->dns_ipv6_addr)
+ my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
+
+ /* new in libcurl 7.6.2: */
+ my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
+
+ /* new in libcurl 7.7: */
+ my_setopt_str(curl, CURLOPT_RANDOM_FILE, config->random_file);
+ my_setopt_str(curl, CURLOPT_EGDSOCKET, config->egd_file);
+ my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS,
+ (long)(config->connecttimeout * 1000));
+
+ if(config->cipher_list)
+ my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
+
+ /* new in libcurl 7.9.2: */
+ if(config->disable_epsv)
+ /* disable it */
+ my_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
+
+ /* new in libcurl 7.10.5 */
+ if(config->disable_eprt)
+ /* disable it */
+ my_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L);
+
+ if(global->tracetype != TRACE_NONE) {
+ my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
+ my_setopt(curl, CURLOPT_DEBUGDATA, config);
+ my_setopt(curl, CURLOPT_VERBOSE, 1L);
+ }
+
+ /* new in curl 7.9.3 */
+ if(config->engine) {
+ res = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
+ if(res)
+ goto show_error;
+ my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
+ }
+
+ /* new in curl 7.10.7, extended in 7.19.4 but this only sets 0 or 1 */
+ my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
+ config->ftp_create_dirs?1L:0L);
+
+ /* new in curl 7.10.8 */
+ if(config->max_filesize)
+ my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE,
+ config->max_filesize);
+
+ if(4 == config->ip_version)
+ my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+ else if(6 == config->ip_version)
+ my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
+ else
+ my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
+
+ /* new in curl 7.15.5 */
+ if(config->ftp_ssl_reqd)
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
+
+ /* new in curl 7.11.0 */
+ else if(config->ftp_ssl)
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
+
+ /* new in curl 7.16.0 */
+ else if(config->ftp_ssl_control)
+ my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_CONTROL);
+
+ /* new in curl 7.16.1 */
+ if(config->ftp_ssl_ccc)
+ my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC,
+ (long)config->ftp_ssl_ccc_mode);
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ {
+ /* TODO: Make this a run-time check instead of compile-time one. */
+
+ /* new in curl 7.19.4 */
+ if(config->socks5_gssapi_service)
+ my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE,
+ config->socks5_gssapi_service);
+
+ /* new in curl 7.19.4 */
+ if(config->socks5_gssapi_nec)
+ my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
+ config->socks5_gssapi_nec);
+ }
+#endif
+ /* curl 7.13.0 */
+ my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
+
+ my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl?1L:0L);
+
+ /* curl 7.14.2 */
+ my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip?1L:0L);
+
+ /* curl 7.15.1 */
+ my_setopt(curl, CURLOPT_FTP_FILEMETHOD, (long)config->ftp_filemethod);
+
+ /* curl 7.15.2 */
+ if(config->localport) {
+ my_setopt(curl, CURLOPT_LOCALPORT, (long)config->localport);
+ my_setopt_str(curl, CURLOPT_LOCALPORTRANGE,
+ (long)config->localportrange);
+ }
+
+ /* curl 7.15.5 */
+ my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
+ config->ftp_alternative_to_user);
+
+ /* curl 7.16.0 */
+ if(config->disable_sessionid)
+ /* disable it */
+ my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
+
+ /* curl 7.16.2 */
+ if(config->raw) {
+ my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
+ my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L);
+ }
+
+ /* curl 7.17.1 */
+ if(!config->nokeepalive) {
+ my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
+ if(config->alivetime != 0) {
+#if !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL)
+ warnf(config, "Keep-alive functionality somewhat crippled due to "
+ "missing support in your operating system!\n");
+#endif
+ my_setopt(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime);
+ my_setopt(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime);
+ }
+ }
+ else
+ my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L);
+
+ /* curl 7.20.0 */
+ if(config->tftp_blksize)
+ my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
+
+ if(config->mail_from)
+ my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
+
+ if(config->mail_rcpt)
+ my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
+
+ /* curl 7.20.x */
+ if(config->ftp_pret)
+ my_setopt(curl, CURLOPT_FTP_USE_PRET, 1L);
+
+ if(config->proto_present)
+ my_setopt_flags(curl, CURLOPT_PROTOCOLS, config->proto);
+ if(config->proto_redir_present)
+ my_setopt_flags(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
+
+ if(config->content_disposition
+ && (urlnode->flags & GETOUT_USEREMOTE)
+ && (checkprefix("http://", this_url) ||
+ checkprefix("https://", this_url)))
+ hdrcbdata.honor_cd_filename = TRUE;
+ else
+ hdrcbdata.honor_cd_filename = FALSE;
+
+ hdrcbdata.outs = &outs;
+ hdrcbdata.heads = &heads;
+
+ my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
+ my_setopt(curl, CURLOPT_HEADERDATA, &hdrcbdata);
+
+ if(config->resolve)
+ /* new in 7.21.3 */
+ my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
+
+ /* new in 7.21.4 */
+ if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ if(config->tls_username)
+ my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
+ config->tls_username);
+ if(config->tls_password)
+ my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD,
+ config->tls_password);
+ if(config->tls_authtype)
+ my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
+ config->tls_authtype);
+ }
+
+ /* new in 7.22.0 */
+ if(config->gssapi_delegation)
+ my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
+ config->gssapi_delegation);
+
+ /* new in 7.25.0 */
+ if(config->ssl_allow_beast)
+ my_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST);
+
+ if(config->mail_auth)
+ my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
+
+ /* new in 7.31.0 */
+ if(config->sasl_ir)
+ my_setopt(curl, CURLOPT_SASL_IR, 1L);
+
+ if(config->nonpn) {
+ my_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 0L);
+ }
+
+ if(config->noalpn) {
+ my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
+ }
+
+ /* initialize retry vars for loop below */
+ retry_sleep_default = (config->retry_delay) ?
+ config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
+
+ retry_numretries = config->req_retry;
+ retry_sleep = retry_sleep_default; /* ms */
+ retrystart = tvnow();
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ res = easysrc_perform();
+ if(res) {
+ goto show_error;
+ }
+#endif
+
+ for(;;) {
+#ifdef USE_METALINK
+ if(!metalink && config->use_metalink) {
+ /* If outs.metalink_parser is non-NULL, delete it first. */
+ if(outs.metalink_parser)
+ metalink_parser_context_delete(outs.metalink_parser);
+ outs.metalink_parser = metalink_parser_context_new();
+ if(outs.metalink_parser == NULL) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+ fprintf(config->global->errors,
+ "Metalink: parsing (%s) metalink/XML...\n", this_url);
+ }
+ else if(metalink)
+ fprintf(config->global->errors,
+ "Metalink: fetching (%s) from (%s)...\n",
+ mlfile->filename, this_url);
+#endif /* USE_METALINK */
+
+#ifdef CURLDEBUG
+ if(config->test_event_based)
+ res = curl_easy_perform_ev(curl);
+ else
+#endif
+ res = curl_easy_perform(curl);
+
+ if(outs.is_cd_filename && outs.stream && !global->mute &&
+ outs.filename)
+ printf("curl: Saved to filename '%s'\n", outs.filename);
+
+ /* if retry-max-time is non-zero, make sure we haven't exceeded the
+ time */
+ if(retry_numretries &&
+ (!config->retry_maxtime ||
+ (tvdiff(tvnow(), retrystart) <
+ config->retry_maxtime*1000L)) ) {
+ enum {
+ RETRY_NO,
+ RETRY_TIMEOUT,
+ RETRY_HTTP,
+ RETRY_FTP,
+ RETRY_LAST /* not used */
+ } retry = RETRY_NO;
+ long response;
+ if((CURLE_OPERATION_TIMEDOUT == res) ||
+ (CURLE_COULDNT_RESOLVE_HOST == res) ||
+ (CURLE_COULDNT_RESOLVE_PROXY == res) ||
+ (CURLE_FTP_ACCEPT_TIMEOUT == res))
+ /* retry timeout always */
+ retry = RETRY_TIMEOUT;
+ else if((CURLE_OK == res) ||
+ (config->failonerror &&
+ (CURLE_HTTP_RETURNED_ERROR == res))) {
+ /* If it returned OK. _or_ failonerror was enabled and it
+ returned due to such an error, check for HTTP transient
+ errors to retry on. */
+ char *effective_url = NULL;
+ curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
+ if(effective_url &&
+ checkprefix("http", effective_url)) {
+ /* This was HTTP(S) */
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+
+ switch(response) {
+ case 500: /* Internal Server Error */
+ case 502: /* Bad Gateway */
+ case 503: /* Service Unavailable */
+ case 504: /* Gateway Timeout */
+ retry = RETRY_HTTP;
+ /*
+ * At this point, we have already written data to the output
+ * file (or terminal). If we write to a file, we must rewind
+ * or close/re-open the file so that the next attempt starts
+ * over from the beginning.
+ *
+ * TODO: similar action for the upload case. We might need
+ * to start over reading from a previous point if we have
+ * uploaded something when this was returned.
+ */
+ break;
+ }
+ }
+ } /* if CURLE_OK */
+ else if(res) {
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+
+ if(response/100 == 4)
+ /*
+ * This is typically when the FTP server only allows a certain
+ * amount of users and we are not one of them. All 4xx codes
+ * are transient.
+ */
+ retry = RETRY_FTP;
+ }
+
+ if(retry) {
+ static const char * const m[]={
+ NULL, "timeout", "HTTP error", "FTP error"
+ };
+ warnf(config, "Transient problem: %s "
+ "Will retry in %ld seconds. "
+ "%ld retries left.\n",
+ m[retry], retry_sleep/1000L, retry_numretries);
+
+ tool_go_sleep(retry_sleep);
+ retry_numretries--;
+ if(!config->retry_delay) {
+ retry_sleep *= 2;
+ if(retry_sleep > RETRY_SLEEP_MAX)
+ retry_sleep = RETRY_SLEEP_MAX;
+ }
+ if(outs.bytes && outs.filename) {
+ /* We have written data to a output file, we truncate file
+ */
+ if(!global->mute)
+ fprintf(global->errors, "Throwing away %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
+ outs.bytes);
+ fflush(outs.stream);
+ /* truncate file at the position where we started appending */
+#ifdef HAVE_FTRUNCATE
+ if(ftruncate( fileno(outs.stream), outs.init)) {
+ /* when truncate fails, we can't just append as then we'll
+ create something strange, bail out */
+ if(!global->mute)
+ fprintf(global->errors,
+ "failed to truncate, exiting\n");
+ res = CURLE_WRITE_ERROR;
+ goto quit_urls;
+ }
+ /* now seek to the end of the file, the position where we
+ just truncated the file in a large file-safe way */
+ fseek(outs.stream, 0, SEEK_END);
+#else
+ /* ftruncate is not available, so just reposition the file
+ to the location we would have truncated it. This won't
+ work properly with large files on 32-bit systems, but
+ most of those will have ftruncate. */
+ fseek(outs.stream, (long)outs.init, SEEK_SET);
+#endif
+ outs.bytes = 0; /* clear for next round */
+ }
+ continue; /* curl_easy_perform loop */
+ }
+ } /* if retry_numretries */
+ else if(metalink) {
+ /* Metalink: Decide to try the next resource or
+ not. Basically, we want to try the next resource if
+ download was not successful. */
+ long response;
+ if(CURLE_OK == res) {
+ /* TODO We want to try next resource when download was
+ not successful. How to know that? */
+ char *effective_url = NULL;
+ curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
+ if(effective_url &&
+ curlx_strnequal(effective_url, "http", 4)) {
+ /* This was HTTP(S) */
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
+ if(response != 200 && response != 206) {
+ metalink_next_res = 1;
+ fprintf(global->errors,
+ "Metalink: fetching (%s) from (%s) FAILED "
+ "(HTTP status code %d)\n",
+ mlfile->filename, this_url, response);
+ }
+ }
+ }
+ else {
+ metalink_next_res = 1;
+ fprintf(global->errors,
+ "Metalink: fetching (%s) from (%s) FAILED (%s)\n",
+ mlfile->filename, this_url,
+ (errorbuffer[0]) ?
+ errorbuffer : curl_easy_strerror((CURLcode)res));
+ }
+ }
+ if(metalink && !metalink_next_res)
+ fprintf(global->errors, "Metalink: fetching (%s) from (%s) OK\n",
+ mlfile->filename, this_url);
+
+ /* In all ordinary cases, just break out of loop here */
+ break; /* curl_easy_perform loop */
+
+ }
+
+ if((global->progressmode == CURL_PROGRESS_BAR) &&
+ progressbar.calls)
+ /* if the custom progress bar has been displayed, we output a
+ newline here */
+ fputs("\n", progressbar.out);
+
+ if(config->writeout)
+ ourWriteOut(curl, &outs, config->writeout);
+
+ if(config->writeenv)
+ ourWriteEnv(curl);
+
+ /*
+ ** Code within this loop may jump directly here to label 'show_error'
+ ** in order to display an error message for CURLcode stored in 'res'
+ ** variable and exit loop once that necessary writing and cleanup
+ ** in label 'quit_urls' has been done.
+ */
+
+ show_error:
+
+#ifdef __VMS
+ if(is_vms_shell()) {
+ /* VMS DCL shell behavior */
+ if(!global->showerror)
+ vms_show = VMSSTS_HIDE;
+ }
+ else
+#endif
+ if(res && global->showerror) {
+ fprintf(global->errors, "curl: (%d) %s\n", res, (errorbuffer[0]) ?
+ errorbuffer : curl_easy_strerror((CURLcode)res));
+ if(res == CURLE_SSL_CACERT)
+ fprintf(global->errors, "%s%s",
+ CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2);
+ }
+
+ /* Fall through comment to 'quit_urls' label */
+
+ /*
+ ** Upon error condition and always that a message has already been
+ ** displayed, code within this loop may jump directly here to label
+ ** 'quit_urls' otherwise it should jump to 'show_error' label above.
+ **
+ ** When 'res' variable is _not_ CURLE_OK loop will exit once that
+ ** all code following 'quit_urls' has been executed. Otherwise it
+ ** will loop to the beginning from where it may exit if there are
+ ** no more urls left.
+ */
+
+ quit_urls:
+
+ /* Set file extended attributes */
+ if(!res && config->xattr && outs.fopened && outs.stream) {
+ int rc = fwrite_xattr(curl, fileno(outs.stream));
+ if(rc)
+ warnf(config, "Error setting extended attributes: %s\n",
+ strerror(errno));
+ }
+
+ /* Close the file */
+ if(outs.fopened && outs.stream) {
+ int rc = fclose(outs.stream);
+ if(!res && rc) {
+ /* something went wrong in the writing process */
+ res = CURLE_WRITE_ERROR;
+ fprintf(global->errors, "(%d) Failed writing body\n", res);
+ }
+ }
+ else if(!outs.s_isreg && outs.stream) {
+ /* Dump standard stream buffered data */
+ int rc = fflush(outs.stream);
+ if(!res && rc) {
+ /* something went wrong in the writing process */
+ res = CURLE_WRITE_ERROR;
+ fprintf(global->errors, "(%d) Failed writing body\n", res);
+ }
+ }
+
+#ifdef __AMIGA__
+ if(!res && outs.s_isreg && outs.filename) {
+ /* Set the url (up to 80 chars) as comment for the file */
+ if(strlen(url) > 78)
+ url[79] = '\0';
+ SetComment(outs.filename, url);
+ }
+#endif
+
+#ifdef HAVE_UTIME
+ /* File time can only be set _after_ the file has been closed */
+ if(!res && config->remote_time && outs.s_isreg && outs.filename) {
+ /* Ask libcurl if we got a remote file time */
+ long filetime = -1;
+ curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
+ if(filetime >= 0) {
+ struct utimbuf times;
+ times.actime = (time_t)filetime;
+ times.modtime = (time_t)filetime;
+ utime(outs.filename, &times); /* set the time we got */
+ }
+ }
+#endif
+
+#ifdef USE_METALINK
+ if(!metalink && config->use_metalink && res == CURLE_OK) {
+ int rv = parse_metalink(config, &outs, this_url);
+ if(rv == 0)
+ fprintf(config->global->errors, "Metalink: parsing (%s) OK\n",
+ this_url);
+ else if(rv == -1)
+ fprintf(config->global->errors, "Metalink: parsing (%s) FAILED\n",
+ this_url);
+ }
+ else if(metalink && res == CURLE_OK && !metalink_next_res) {
+ int rv = metalink_check_hash(global, mlfile, outs.filename);
+ if(rv == 0) {
+ metalink_next_res = 1;
+ }
+ }
+#endif /* USE_METALINK */
+
+ /* No more business with this output struct */
+ if(outs.alloc_filename)
+ Curl_safefree(outs.filename);
+#ifdef USE_METALINK
+ if(outs.metalink_parser)
+ metalink_parser_context_delete(outs.metalink_parser);
+#endif /* USE_METALINK */
+ memset(&outs, 0, sizeof(struct OutStruct));
+ hdrcbdata.outs = NULL;
+
+ /* Free loop-local allocated memory and close loop-local opened fd */
+
+ Curl_safefree(outfile);
+ Curl_safefree(this_url);
+
+ if(infdopen)
+ close(infd);
+
+ if(metalink) {
+ /* Should exit if error is fatal. */
+ if(is_fatal_error(res)) {
+ break;
+ }
+ if(!metalink_next_res)
+ break;
+ mlres = mlres->next;
+ if(mlres == NULL)
+ /* TODO If metalink_next_res is 1 and mlres is NULL,
+ * set res to error code
+ */
+ break;
+ }
+ else
+ if(urlnum > 1) {
+ /* when url globbing, exit loop upon critical error */
+ if(is_fatal_error(res))
+ break;
+ }
+ else if(res)
+ /* when not url globbing, exit loop upon any error */
+ break;
+
+ } /* loop to the next URL */
+
+ /* Free loop-local allocated memory */
+
+ Curl_safefree(uploadfile);
+
+ if(urls) {
+ /* Free list of remaining URLs */
+ glob_cleanup(urls);
+ urls = NULL;
+ }
+
+ if(infilenum > 1) {
+ /* when file globbing, exit loop upon critical error */
+ if(is_fatal_error(res))
+ break;
+ }
+ else if(res)
+ /* when not file globbing, exit loop upon any error */
+ break;
+
+ } /* loop to the next globbed upload file */
+
+ /* Free loop-local allocated memory */
+
+ Curl_safefree(outfiles);
+
+ if(inglob) {
+ /* Free list of globbed upload files */
+ glob_cleanup(inglob);
+ inglob = NULL;
+ }
+
+ /* Free this URL node data without destroying the
+ the node itself nor modifying next pointer. */
+ Curl_safefree(urlnode->url);
+ Curl_safefree(urlnode->outfile);
+ Curl_safefree(urlnode->infile);
+ urlnode->flags = 0;
+
+ /*
+ ** Bail out upon critical errors
+ */
+ if(is_fatal_error(res))
+ goto quit_curl;
+
+ } /* for-loop through all URLs */
+
+ /*
+ ** Nested loops end here.
+ */
+
+ quit_curl:
+
+ /* Reset the global config variables */
+ global->noprogress = orig_noprogress;
+ global->isatty = orig_isatty;
+
+ /* Free function-local referenced allocated memory */
+ Curl_safefree(httpgetfields);
+
+ /* Free list of given URLs */
+ clean_getout(config);
+
+ hdrcbdata.heads = NULL;
+
+ /* Close function-local opened file descriptors */
+ if(heads.fopened && heads.stream)
+ fclose(heads.stream);
+
+ if(heads.alloc_filename)
+ Curl_safefree(heads.filename);
+
+ /* Release metalink related resources here */
+ clean_metalink(config);
+
+ return res;
+}
+
+CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[])
+{
+ CURLcode result = CURLE_OK;
+
+ /* Setup proper locale from environment */
+#ifdef HAVE_SETLOCALE
+ setlocale(LC_ALL, "");
+#endif
+
+ /* Parse .curlrc if necessary */
+ if((argc == 1) || (!curlx_strequal(argv[1], "-q"))) {
+ parseconfig(NULL, config); /* ignore possible failure */
+
+ /* If we had no arguments then make sure a url was specified in .curlrc */
+ if((argc < 2) && (!config->first->url_list)) {
+ helpf(config->errors, NULL);
+ result = CURLE_FAILED_INIT;
+ }
+ }
+
+ if(!result) {
+ /* Parse the command line arguments */
+ ParameterError res = parse_args(config, argc, argv);
+ if(res) {
+ result = CURLE_OK;
+
+ /* Check if we were asked for the help */
+ if(res == PARAM_HELP_REQUESTED)
+ tool_help();
+ /* Check if we were asked for the manual */
+ else if(res == PARAM_MANUAL_REQUESTED)
+ hugehelp();
+ /* Check if we were asked for the version information */
+ else if(res == PARAM_VERSION_INFO_REQUESTED)
+ tool_version_info();
+ /* Check if we were asked to list the SSL engines */
+ else if(res == PARAM_ENGINES_REQUESTED)
+ tool_list_engines(config->easy);
+ else
+ result = CURLE_FAILED_INIT;
+ }
+ else {
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ /* Initialise the libcurl source output */
+ result = easysrc_init();
+#endif
+
+ /* Perform the main operations */
+ if(!result) {
+ size_t count = 0;
+ struct OperationConfig *operation = config->first;
+
+ /* Get the required aguments for each operation */
+ while(!result && operation) {
+ result = get_args(operation, count++);
+
+ operation = operation->next;
+ }
+
+ /* Set the current operation pointer */
+ config->current = config->first;
+
+ /* Perform each operation */
+ while(!result && config->current) {
+ result = operate_do(config, config->current);
+
+ config->current = config->current->next;
+ }
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+ /* Cleanup the libcurl source output */
+ easysrc_cleanup();
+
+ /* Dump the libcurl code if previously enabled */
+ dumpeasysrc(config);
+#endif
+ }
+ else
+ helpf(config->errors, "out of memory\n");
+ }
+ }
+
+ return result;
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_operate.h b/external/libcurl_android/jni/libcurl/src/tool_operate.h
new file mode 100755
index 00000000..1d5c1a96
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_operate.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TOOL_OPERATE_H
+#define HEADER_CURL_TOOL_OPERATE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[]);
+
+#endif /* HEADER_CURL_TOOL_OPERATE_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_operhlp.c b/external/libcurl_android/jni/libcurl/src/tool_operhlp.c
new file mode 100755
index 00000000..15eefabe
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_operhlp.c
@@ -0,0 +1,171 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_convert.h"
+#include "tool_operhlp.h"
+#include "tool_metalink.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void clean_getout(struct OperationConfig *config)
+{
+ struct getout *next;
+ struct getout *node = config->url_list;
+
+ while(node) {
+ next = node->next;
+ Curl_safefree(node->url);
+ Curl_safefree(node->outfile);
+ Curl_safefree(node->infile);
+ Curl_safefree(node);
+ node = next;
+ }
+ config->url_list = NULL;
+}
+
+bool output_expected(const char *url, const char *uploadfile)
+{
+ if(!uploadfile)
+ return TRUE; /* download */
+ if(checkprefix("http://", url) || checkprefix("https://", url))
+ return TRUE; /* HTTP(S) upload */
+
+ return FALSE; /* non-HTTP upload, probably no output should be expected */
+}
+
+bool stdin_upload(const char *uploadfile)
+{
+ return (curlx_strequal(uploadfile, "-") ||
+ curlx_strequal(uploadfile, ".")) ? TRUE : FALSE;
+}
+
+/*
+ * Adds the file name to the URL if it doesn't already have one.
+ * url will be freed before return if the returned pointer is different
+ */
+char *add_file_name_to_url(CURL *curl, char *url, const char *filename)
+{
+ /* If no file name part is given in the URL, we add this file name */
+ char *ptr = strstr(url, "://");
+ if(ptr)
+ ptr += 3;
+ else
+ ptr = url;
+ ptr = strrchr(ptr, '/');
+ if(!ptr || !strlen(++ptr)) {
+ /* The URL has no file name part, add the local file name. In order
+ to be able to do so, we have to create a new URL in another
+ buffer.*/
+
+ /* We only want the part of the local path that is on the right
+ side of the rightmost slash and backslash. */
+ const char *filep = strrchr(filename, '/');
+ char *file2 = strrchr(filep?filep:filename, '\\');
+ char *encfile;
+
+ if(file2)
+ filep = file2 + 1;
+ else if(filep)
+ filep++;
+ else
+ filep = filename;
+
+ /* URL encode the file name */
+ encfile = curl_easy_escape(curl, filep, 0 /* use strlen */);
+ if(encfile) {
+ char *urlbuffer;
+ if(ptr)
+ /* there is a trailing slash on the URL */
+ urlbuffer = aprintf("%s%s", url, encfile);
+ else
+ /* there is no trailing slash on the URL */
+ urlbuffer = aprintf("%s/%s", url, encfile);
+
+ curl_free(encfile);
+ Curl_safefree(url);
+
+ if(!urlbuffer)
+ return NULL;
+
+ url = urlbuffer; /* use our new URL instead! */
+ }
+ else
+ Curl_safefree(url);
+ }
+ return url;
+}
+
+/* Extracts the name portion of the URL.
+ * Returns a pointer to a heap-allocated string or NULL if
+ * no name part, at location indicated by first argument.
+ */
+CURLcode get_url_file_name(char **filename, const char *url)
+{
+ const char *pc;
+
+ *filename = NULL;
+
+ /* Find and get the remote file name */
+ pc = strstr(url, "://");
+ if(pc)
+ pc += 3;
+ else
+ pc = url;
+ pc = strrchr(pc, '/');
+
+ if(pc) {
+ /* duplicate the string beyond the slash */
+ pc++;
+ if(*pc) {
+ *filename = strdup(pc);
+ if(!*filename)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ /* in case we built debug enabled, we allow an environment variable
+ * named CURL_TESTDIR to prefix the given file name to put it into a
+ * specific directory
+ */
+#ifdef DEBUGBUILD
+ {
+ char *tdir = curlx_getenv("CURL_TESTDIR");
+ if(tdir) {
+ char buffer[512]; /* suitably large */
+ snprintf(buffer, sizeof(buffer), "%s/%s", tdir, *filename);
+ Curl_safefree(*filename);
+ *filename = strdup(buffer); /* clone the buffer */
+ curl_free(tdir);
+ }
+ }
+#endif
+
+ return CURLE_OK;
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_operhlp.h b/external/libcurl_android/jni/libcurl/src/tool_operhlp.h
new file mode 100755
index 00000000..8fcaad69
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_operhlp.h
@@ -0,0 +1,39 @@
+#ifndef HEADER_CURL_TOOL_OPERHLP_H
+#define HEADER_CURL_TOOL_OPERHLP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+struct OperationConfig;
+
+void clean_getout(struct OperationConfig *config);
+
+bool output_expected(const char *url, const char *uploadfile);
+
+bool stdin_upload(const char *uploadfile);
+
+char *add_file_name_to_url(CURL *curl, char *url, const char *filename);
+
+CURLcode get_url_file_name(char **filename, const char *url);
+
+#endif /* HEADER_CURL_TOOL_OPERHLP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_panykey.c b/external/libcurl_android/jni/libcurl/src/tool_panykey.c
new file mode 100755
index 00000000..d8718e32
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_panykey.c
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(__SYMBIAN32__) || defined(NETWARE)
+
+#ifdef NETWARE
+# ifdef __NOVELL_LIBC__
+# include <screen.h>
+# else
+# include <nwconio.h>
+# endif
+#endif
+
+#include "tool_panykey.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void tool_pressanykey(void)
+{
+#if defined(__SYMBIAN32__)
+ getchar();
+#elif defined(NETWARE)
+ pressanykey();
+#endif
+}
+
+#endif /* __SYMBIAN32__ || NETWARE */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_panykey.h b/external/libcurl_android/jni/libcurl/src/tool_panykey.h
new file mode 100755
index 00000000..50b15d2d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_panykey.h
@@ -0,0 +1,37 @@
+#ifndef HEADER_CURL_TOOL_PANYKEY_H
+#define HEADER_CURL_TOOL_PANYKEY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#if defined(__SYMBIAN32__) || defined(NETWARE)
+
+void tool_pressanykey(void);
+
+#else
+
+#define tool_pressanykey() Curl_nop_stmt
+
+#endif
+
+#endif /* HEADER_CURL_TOOL_PANYKEY_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_paramhlp.c b/external/libcurl_android/jni/libcurl/src/tool_paramhlp.c
new file mode 100755
index 00000000..18da0265
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_paramhlp.c
@@ -0,0 +1,513 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "rawstr.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_getparam.h"
+#include "tool_getpass.h"
+#include "tool_homedir.h"
+#include "tool_msgs.h"
+#include "tool_paramhlp.h"
+#include "tool_version.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+struct getout *new_getout(struct OperationConfig *config)
+{
+ struct getout *node = calloc(1, sizeof(struct getout));
+ struct getout *last = config->url_last;
+ if(node) {
+ /* append this new node last in the list */
+ if(last)
+ last->next = node;
+ else
+ config->url_list = node; /* first node */
+
+ /* move the last pointer */
+ config->url_last = node;
+
+ node->flags = config->default_node_flags;
+ }
+ return node;
+}
+
+ParameterError file2string(char **bufp, FILE *file)
+{
+ char buffer[256];
+ char *ptr;
+ char *string = NULL;
+ size_t stringlen = 0;
+ size_t buflen;
+
+ if(file) {
+ while(fgets(buffer, sizeof(buffer), file)) {
+ if((ptr = strchr(buffer, '\r')) != NULL)
+ *ptr = '\0';
+ if((ptr = strchr(buffer, '\n')) != NULL)
+ *ptr = '\0';
+ buflen = strlen(buffer);
+ if((ptr = realloc(string, stringlen+buflen+1)) == NULL) {
+ Curl_safefree(string);
+ return PARAM_NO_MEM;
+ }
+ string = ptr;
+ strcpy(string+stringlen, buffer);
+ stringlen += buflen;
+ }
+ }
+ *bufp = string;
+ return PARAM_OK;
+}
+
+ParameterError file2memory(char **bufp, size_t *size, FILE *file)
+{
+ char *newbuf;
+ char *buffer = NULL;
+ size_t alloc = 512;
+ size_t nused = 0;
+ size_t nread;
+
+ if(file) {
+ do {
+ if(!buffer || (alloc == nused)) {
+ /* size_t overflow detection for huge files */
+ if(alloc+1 > ((size_t)-1)/2) {
+ Curl_safefree(buffer);
+ return PARAM_NO_MEM;
+ }
+ alloc *= 2;
+ /* allocate an extra char, reserved space, for null termination */
+ if((newbuf = realloc(buffer, alloc+1)) == NULL) {
+ Curl_safefree(buffer);
+ return PARAM_NO_MEM;
+ }
+ buffer = newbuf;
+ }
+ nread = fread(buffer+nused, 1, alloc-nused, file);
+ nused += nread;
+ } while(nread);
+ /* null terminate the buffer in case it's used as a string later */
+ buffer[nused] = '\0';
+ /* free trailing slack space, if possible */
+ if(alloc != nused) {
+ if((newbuf = realloc(buffer, nused+1)) == NULL) {
+ Curl_safefree(buffer);
+ return PARAM_NO_MEM;
+ }
+ buffer = newbuf;
+ }
+ /* discard buffer if nothing was read */
+ if(!nused) {
+ Curl_safefree(buffer); /* no string */
+ }
+ }
+ *size = nused;
+ *bufp = buffer;
+ return PARAM_OK;
+}
+
+void cleanarg(char *str)
+{
+#ifdef HAVE_WRITABLE_ARGV
+ /* now that GetStr has copied the contents of nextarg, wipe the next
+ * argument out so that the username:password isn't displayed in the
+ * system process list */
+ if(str) {
+ size_t len = strlen(str);
+ memset(str, ' ', len);
+ }
+#else
+ (void)str;
+#endif
+}
+
+/*
+ * Parse the string and write the long in the given address. Return PARAM_OK
+ * on success, otherwise a parameter specific error enum.
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError str2num(long *val, const char *str)
+{
+ if(str) {
+ char *endptr;
+ long num = strtol(str, &endptr, 10);
+ if((endptr != str) && (endptr == str + strlen(str))) {
+ *val = num;
+ return PARAM_OK; /* Ok */
+ }
+ }
+ return PARAM_BAD_NUMERIC; /* badness */
+}
+
+/*
+ * Parse the string and write the long in the given address. Return PARAM_OK
+ * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError str2unum(long *val, const char *str)
+{
+ ParameterError result = str2num(val, str);
+ if(result != PARAM_OK)
+ return result;
+ if(*val < 0)
+ return PARAM_NEGATIVE_NUMERIC;
+
+ return PARAM_OK;
+}
+
+/*
+ * Parse the string and write the double in the given address. Return PARAM_OK
+ * on success, otherwise a parameter specific error enum.
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError str2double(double *val, const char *str)
+{
+ if(str) {
+ char *endptr;
+ double num = strtod(str, &endptr);
+ if((endptr != str) && (endptr == str + strlen(str))) {
+ *val = num;
+ return PARAM_OK; /* Ok */
+ }
+ }
+ return PARAM_BAD_NUMERIC; /* badness */
+}
+
+/*
+ * Parse the string and write the double in the given address. Return PARAM_OK
+ * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+ParameterError str2udouble(double *val, const char *str)
+{
+ ParameterError result = str2double(val, str);
+ if(result != PARAM_OK)
+ return result;
+ if(*val < 0)
+ return PARAM_NEGATIVE_NUMERIC;
+
+ return PARAM_OK;
+}
+
+/*
+ * Parse the string and modify the long in the given address. Return
+ * non-zero on failure, zero on success.
+ *
+ * The string is a list of protocols
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+long proto2num(struct OperationConfig *config, long *val, const char *str)
+{
+ char *buffer;
+ const char *sep = ",";
+ char *token;
+
+ static struct sprotos {
+ const char *name;
+ long bit;
+ } const protos[] = {
+ { "all", CURLPROTO_ALL },
+ { "http", CURLPROTO_HTTP },
+ { "https", CURLPROTO_HTTPS },
+ { "ftp", CURLPROTO_FTP },
+ { "ftps", CURLPROTO_FTPS },
+ { "scp", CURLPROTO_SCP },
+ { "sftp", CURLPROTO_SFTP },
+ { "telnet", CURLPROTO_TELNET },
+ { "ldap", CURLPROTO_LDAP },
+ { "ldaps", CURLPROTO_LDAPS },
+ { "dict", CURLPROTO_DICT },
+ { "file", CURLPROTO_FILE },
+ { "tftp", CURLPROTO_TFTP },
+ { "imap", CURLPROTO_IMAP },
+ { "imaps", CURLPROTO_IMAPS },
+ { "pop3", CURLPROTO_POP3 },
+ { "pop3s", CURLPROTO_POP3S },
+ { "smtp", CURLPROTO_SMTP },
+ { "smtps", CURLPROTO_SMTPS },
+ { "rtsp", CURLPROTO_RTSP },
+ { "gopher", CURLPROTO_GOPHER },
+ { NULL, 0 }
+ };
+
+ if(!str)
+ return 1;
+
+ buffer = strdup(str); /* because strtok corrupts it */
+ if(!buffer)
+ return 1;
+
+ for(token = strtok(buffer, sep);
+ token;
+ token = strtok(NULL, sep)) {
+ enum e_action { allow, deny, set } action = allow;
+
+ struct sprotos const *pp;
+
+ /* Process token modifiers */
+ while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
+ switch (*token++) {
+ case '=':
+ action = set;
+ break;
+ case '-':
+ action = deny;
+ break;
+ case '+':
+ action = allow;
+ break;
+ default: /* Includes case of terminating NULL */
+ Curl_safefree(buffer);
+ return 1;
+ }
+ }
+
+ for(pp=protos; pp->name; pp++) {
+ if(curlx_raw_equal(token, pp->name)) {
+ switch (action) {
+ case deny:
+ *val &= ~(pp->bit);
+ break;
+ case allow:
+ *val |= pp->bit;
+ break;
+ case set:
+ *val = pp->bit;
+ break;
+ }
+ break;
+ }
+ }
+
+ if(!(pp->name)) { /* unknown protocol */
+ /* If they have specified only this protocol, we say treat it as
+ if no protocols are allowed */
+ if(action == set)
+ *val = 0;
+ warnf(config, "unrecognized protocol '%s'\n", token);
+ }
+ }
+ Curl_safefree(buffer);
+ return 0;
+}
+
+/**
+ * Parses the given string looking for an offset (which may be a
+ * larger-than-integer value). The offset CANNOT be negative!
+ *
+ * @param val the offset to populate
+ * @param str the buffer containing the offset
+ * @return PARAM_OK if successful, a parameter specific error enum if failure.
+ */
+ParameterError str2offset(curl_off_t *val, const char *str)
+{
+ char *endptr;
+ if(str[0] == '-')
+ /* offsets aren't negative, this indicates weird input */
+ return PARAM_NEGATIVE_NUMERIC;
+
+#if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+ *val = curlx_strtoofft(str, &endptr, 0);
+ if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (ERRNO == ERANGE))
+ return PARAM_BAD_NUMERIC;
+#else
+ *val = strtol(str, &endptr, 0);
+ if((*val == LONG_MIN || *val == LONG_MAX) && ERRNO == ERANGE)
+ return PARAM_BAD_NUMERIC;
+#endif
+ if((endptr != str) && (endptr == str + strlen(str)))
+ return PARAM_OK;
+
+ return PARAM_BAD_NUMERIC;
+}
+
+static CURLcode checkpasswd(const char *kind, /* for what purpose */
+ const size_t i, /* operation index */
+ const bool last, /* TRUE if last operation */
+ char **userpwd) /* pointer to allocated string */
+{
+ char *psep;
+ char *osep;
+
+ if(!*userpwd)
+ return CURLE_OK;
+
+ /* Attempt to find the password separator */
+ psep = strchr(*userpwd, ':');
+
+ /* Attempt to find the options separator */
+ osep = strchr(*userpwd, ';');
+
+ if(!psep && **userpwd != ';') {
+ /* no password present, prompt for one */
+ char passwd[256] = "";
+ char prompt[256];
+ size_t passwdlen;
+ size_t userlen = strlen(*userpwd);
+ char *passptr;
+
+ if(osep)
+ *osep = '\0';
+
+ /* build a nice-looking prompt */
+ if(!i && last)
+ curlx_msnprintf(prompt, sizeof(prompt),
+ "Enter %s password for user '%s':",
+ kind, *userpwd);
+ else
+ curlx_msnprintf(prompt, sizeof(prompt),
+ "Enter %s password for user '%s' on URL #%"
+ CURL_FORMAT_CURL_OFF_TU ":",
+ kind, *userpwd, i + 1);
+
+ /* get password */
+ getpass_r(prompt, passwd, sizeof(passwd));
+ passwdlen = strlen(passwd);
+
+ if(osep)
+ *osep = ';';
+
+ /* extend the allocated memory area to fit the password too */
+ passptr = realloc(*userpwd,
+ passwdlen + 1 + /* an extra for the colon */
+ userlen + 1); /* an extra for the zero */
+ if(!passptr)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* append the password separated with a colon */
+ passptr[userlen] = ':';
+ memcpy(&passptr[userlen+1], passwd, passwdlen+1);
+ *userpwd = passptr;
+ }
+
+ return CURLE_OK;
+}
+
+ParameterError add2list(struct curl_slist **list, const char *ptr)
+{
+ struct curl_slist *newlist = curl_slist_append(*list, ptr);
+ if(newlist)
+ *list = newlist;
+ else
+ return PARAM_NO_MEM;
+
+ return PARAM_OK;
+}
+
+int ftpfilemethod(struct OperationConfig *config, const char *str)
+{
+ if(curlx_raw_equal("singlecwd", str))
+ return CURLFTPMETHOD_SINGLECWD;
+ if(curlx_raw_equal("nocwd", str))
+ return CURLFTPMETHOD_NOCWD;
+ if(curlx_raw_equal("multicwd", str))
+ return CURLFTPMETHOD_MULTICWD;
+ warnf(config, "unrecognized ftp file method '%s', using default\n", str);
+ return CURLFTPMETHOD_MULTICWD;
+}
+
+int ftpcccmethod(struct OperationConfig *config, const char *str)
+{
+ if(curlx_raw_equal("passive", str))
+ return CURLFTPSSL_CCC_PASSIVE;
+ if(curlx_raw_equal("active", str))
+ return CURLFTPSSL_CCC_ACTIVE;
+ warnf(config, "unrecognized ftp CCC method '%s', using default\n", str);
+ return CURLFTPSSL_CCC_PASSIVE;
+}
+
+long delegation(struct OperationConfig *config, char *str)
+{
+ if(curlx_raw_equal("none", str))
+ return CURLGSSAPI_DELEGATION_NONE;
+ if(curlx_raw_equal("policy", str))
+ return CURLGSSAPI_DELEGATION_POLICY_FLAG;
+ if(curlx_raw_equal("always", str))
+ return CURLGSSAPI_DELEGATION_FLAG;
+ warnf(config, "unrecognized delegation method '%s', using none\n", str);
+ return CURLGSSAPI_DELEGATION_NONE;
+}
+
+/*
+ * my_useragent: returns allocated string with default user agent
+ */
+static char *my_useragent(void)
+{
+ return strdup(CURL_NAME "/" CURL_VERSION);
+}
+
+CURLcode get_args(struct OperationConfig *config, const size_t i)
+{
+ CURLcode result = CURLE_OK;
+ bool last = (config->next ? FALSE : TRUE);
+
+ /* Check we have a password for the given host user */
+ if(config->userpwd && !config->xoauth2_bearer) {
+ result = checkpasswd("host", i, last, &config->userpwd);
+ if(result)
+ return result;
+ }
+
+ /* Check we have a password for the given proxy user */
+ if(config->proxyuserpwd) {
+ result = checkpasswd("proxy", i, last, &config->proxyuserpwd);
+ if(result)
+ return result;
+ }
+
+ /* Check we have a user agent */
+ if(!config->useragent) {
+ config->useragent = my_useragent();
+ if(!config->useragent) {
+ helpf(config->global->errors, "out of memory\n");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ return result;
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_paramhlp.h b/external/libcurl_android/jni/libcurl/src/tool_paramhlp.h
new file mode 100755
index 00000000..69d7fd42
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_paramhlp.h
@@ -0,0 +1,54 @@
+#ifndef HEADER_CURL_TOOL_PARAMHLP_H
+#define HEADER_CURL_TOOL_PARAMHLP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+struct getout *new_getout(struct OperationConfig *config);
+
+ParameterError file2string(char **bufp, FILE *file);
+
+ParameterError file2memory(char **bufp, size_t *size, FILE *file);
+
+void cleanarg(char *str);
+
+ParameterError str2num(long *val, const char *str);
+ParameterError str2unum(long *val, const char *str);
+ParameterError str2double(double *val, const char *str);
+ParameterError str2udouble(double *val, const char *str);
+
+long proto2num(struct OperationConfig *config, long *val, const char *str);
+
+ParameterError str2offset(curl_off_t *val, const char *str);
+
+CURLcode get_args(struct OperationConfig *config, const size_t i);
+
+ParameterError add2list(struct curl_slist **list, const char *ptr);
+
+int ftpfilemethod(struct OperationConfig *config, const char *str);
+
+int ftpcccmethod(struct OperationConfig *config, const char *str);
+
+long delegation(struct OperationConfig *config, char *str);
+
+#endif /* HEADER_CURL_TOOL_PARAMHLP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_parsecfg.c b/external/libcurl_android/jni/libcurl/src/tool_parsecfg.c
new file mode 100755
index 00000000..7a161c3b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_parsecfg.c
@@ -0,0 +1,362 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_getparam.h"
+#include "tool_helpers.h"
+#include "tool_homedir.h"
+#include "tool_msgs.h"
+#include "tool_parsecfg.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#define CURLRC DOT_CHAR "curlrc"
+
+/* only acknowledge colon or equals as separators if the option was not
+ specified with an initial dash! */
+#define ISSEP(x,dash) (!dash && (((x) == '=') || ((x) == ':')))
+
+static const char *unslashquote(const char *line, char *param);
+static char *my_get_line(FILE *fp);
+
+/* return 0 on everything-is-fine, and non-zero otherwise */
+int parseconfig(const char *filename, struct GlobalConfig *global)
+{
+ int res;
+ FILE *file;
+ char filebuffer[512];
+ bool usedarg;
+ char *home;
+ int rc = 0;
+ struct OperationConfig *operation = global->first;
+
+ if(!filename || !*filename) {
+ /* NULL or no file name attempts to load .curlrc from the homedir! */
+
+#ifndef __AMIGA__
+ filename = CURLRC; /* sensible default */
+ home = homedir(); /* portable homedir finder */
+ if(home) {
+ if(strlen(home) < (sizeof(filebuffer) - strlen(CURLRC))) {
+ snprintf(filebuffer, sizeof(filebuffer),
+ "%s%s%s", home, DIR_CHAR, CURLRC);
+
+#ifdef WIN32
+ /* Check if the file exists - if not, try CURLRC in the same
+ * directory as our executable
+ */
+ file = fopen(filebuffer, "r");
+ if(file != NULL) {
+ fclose(file);
+ filename = filebuffer;
+ }
+ else {
+ /* Get the filename of our executable. GetModuleFileName is
+ * already declared via inclusions done in setup header file.
+ * We assume that we are using the ASCII version here.
+ */
+ int n = GetModuleFileName(0, filebuffer, sizeof(filebuffer));
+ if(n > 0 && n < (int)sizeof(filebuffer)) {
+ /* We got a valid filename - get the directory part */
+ char *lastdirchar = strrchr(filebuffer, '\\');
+ if(lastdirchar) {
+ size_t remaining;
+ *lastdirchar = 0;
+ /* If we have enough space, build the RC filename */
+ remaining = sizeof(filebuffer) - strlen(filebuffer);
+ if(strlen(CURLRC) < remaining - 1) {
+ snprintf(lastdirchar, remaining,
+ "%s%s", DIR_CHAR, CURLRC);
+ /* Don't bother checking if it exists - we do
+ * that later
+ */
+ filename = filebuffer;
+ }
+ }
+ }
+ }
+#else /* WIN32 */
+ filename = filebuffer;
+#endif /* WIN32 */
+ }
+ Curl_safefree(home); /* we've used it, now free it */
+ }
+
+# else /* __AMIGA__ */
+ /* On AmigaOS all the config files are into env:
+ */
+ filename = "ENV:" CURLRC;
+
+#endif
+ }
+
+ if(strcmp(filename,"-"))
+ file = fopen(filename, "r");
+ else
+ file = stdin;
+
+ if(file) {
+ char *line;
+ char *aline;
+ char *option;
+ char *param;
+ int lineno = 0;
+ bool alloced_param;
+ bool dashed_option;
+
+ while(NULL != (aline = my_get_line(file))) {
+ lineno++;
+ line = aline;
+ alloced_param=FALSE;
+
+ /* line with # in the first non-blank column is a comment! */
+ while(*line && ISSPACE(*line))
+ line++;
+
+ switch(*line) {
+ case '#':
+ case '/':
+ case '\r':
+ case '\n':
+ case '*':
+ case '\0':
+ Curl_safefree(aline);
+ continue;
+ }
+
+ /* the option keywords starts here */
+ option = line;
+
+ /* the option starts with a dash? */
+ dashed_option = option[0]=='-'?TRUE:FALSE;
+
+ while(*line && !ISSPACE(*line) && !ISSEP(*line, dashed_option))
+ line++;
+ /* ... and has ended here */
+
+ if(*line)
+ *line++ = '\0'; /* zero terminate, we have a local copy of the data */
+
+#ifdef DEBUG_CONFIG
+ fprintf(stderr, "GOT: %s\n", option);
+#endif
+
+ /* pass spaces and separator(s) */
+ while(*line && (ISSPACE(*line) || ISSEP(*line, dashed_option)))
+ line++;
+
+ /* the parameter starts here (unless quoted) */
+ if(*line == '\"') {
+ /* quoted parameter, do the quote dance */
+ line++;
+ param = malloc(strlen(line) + 1); /* parameter */
+ if(!param) {
+ /* out of memory */
+ Curl_safefree(aline);
+ rc = 1;
+ break;
+ }
+ alloced_param = TRUE;
+ (void)unslashquote(line, param);
+ }
+ else {
+ param = line; /* parameter starts here */
+ while(*line && !ISSPACE(*line))
+ line++;
+ *line = '\0'; /* zero terminate */
+
+ /* to detect mistakes better, see if there's data following */
+ line++;
+ /* pass all spaces */
+ while(*line && ISSPACE(*line))
+ line++;
+
+ switch(*line) {
+ case '\0':
+ case '\r':
+ case '\n':
+ case '#': /* comment */
+ break;
+ default:
+ warnf(operation, "%s:%d: warning: '%s' uses unquoted white space in"
+ " the line that may cause side-effects!\n",
+ filename, lineno, option);
+ }
+ }
+
+ if(param && !*param) {
+ /* do this so getparameter can check for required parameters.
+ Otherwise it always thinks there's a parameter. */
+ if(alloced_param)
+ Curl_safefree(param);
+ param = NULL;
+ }
+
+#ifdef DEBUG_CONFIG
+ fprintf(stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
+#endif
+ res = getparameter(option, param, &usedarg, global, operation);
+
+ if(param && *param && !usedarg)
+ /* we passed in a parameter that wasn't used! */
+ res = PARAM_GOT_EXTRA_PARAMETER;
+
+ if(res == PARAM_NEXT_OPERATION) {
+ if(operation->url_list && operation->url_list->url) {
+ /* Allocate the next config */
+ operation->next = malloc(sizeof(struct OperationConfig));
+ if(operation->next) {
+ /* Initialise the newly created config */
+ config_init(operation->next);
+
+ /* Copy the easy handle */
+ operation->next->easy = global->easy;
+
+ /* Set the global config pointer */
+ operation->next->global = global;
+
+ /* Update the last operation pointer */
+ global->last = operation->next;
+
+ /* Move onto the new config */
+ operation->next->prev = operation;
+ operation = operation->next;
+ }
+ else
+ res = PARAM_NO_MEM;
+ }
+ }
+
+ if(res != PARAM_OK && res != PARAM_NEXT_OPERATION) {
+ /* the help request isn't really an error */
+ if(!strcmp(filename, "-")) {
+ filename = (char *)"<stdin>";
+ }
+ if(res != PARAM_HELP_REQUESTED &&
+ res != PARAM_MANUAL_REQUESTED &&
+ res != PARAM_VERSION_INFO_REQUESTED &&
+ res != PARAM_ENGINES_REQUESTED) {
+ const char *reason = param2text(res);
+ warnf(operation, "%s:%d: warning: '%s' %s\n",
+ filename, lineno, option, reason);
+ }
+ }
+
+ if(alloced_param)
+ Curl_safefree(param);
+
+ Curl_safefree(aline);
+ }
+ if(file != stdin)
+ fclose(file);
+ }
+ else
+ rc = 1; /* couldn't open the file */
+
+ return rc;
+}
+
+/*
+ * Copies the string from line to the buffer at param, unquoting
+ * backslash-quoted characters and NUL-terminating the output string.
+ * Stops at the first non-backslash-quoted double quote character or the
+ * end of the input string. param must be at least as long as the input
+ * string. Returns the pointer after the last handled input character.
+ */
+static const char *unslashquote(const char *line, char *param)
+{
+ while(*line && (*line != '\"')) {
+ if(*line == '\\') {
+ char out;
+ line++;
+
+ /* default is to output the letter after the backslash */
+ switch(out = *line) {
+ case '\0':
+ continue; /* this'll break out of the loop */
+ case 't':
+ out = '\t';
+ break;
+ case 'n':
+ out = '\n';
+ break;
+ case 'r':
+ out = '\r';
+ break;
+ case 'v':
+ out = '\v';
+ break;
+ }
+ *param++ = out;
+ line++;
+ }
+ else
+ *param++ = *line++;
+ }
+ *param = '\0'; /* always zero terminate */
+ return line;
+}
+
+/*
+ * Reads a line from the given file, ensuring is NUL terminated.
+ * The pointer must be freed by the caller.
+ * NULL is returned on an out of memory condition.
+ */
+static char *my_get_line(FILE *fp)
+{
+ char buf[4096];
+ char *nl = NULL;
+ char *line = NULL;
+
+ do {
+ if(NULL == fgets(buf, sizeof(buf), fp))
+ break;
+ if(!line) {
+ line = strdup(buf);
+ if(!line)
+ return NULL;
+ }
+ else {
+ char *ptr;
+ size_t linelen = strlen(line);
+ ptr = realloc(line, linelen + strlen(buf) + 1);
+ if(!ptr) {
+ Curl_safefree(line);
+ return NULL;
+ }
+ line = ptr;
+ strcpy(&line[linelen], buf);
+ }
+ nl = strchr(line, '\n');
+ } while(!nl);
+
+ if(nl)
+ *nl = '\0';
+
+ return line;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_parsecfg.h b/external/libcurl_android/jni/libcurl/src/tool_parsecfg.h
new file mode 100755
index 00000000..c3b19d54
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_parsecfg.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TOOL_PARSECFG_H
+#define HEADER_CURL_TOOL_PARSECFG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+int parseconfig(const char *filename, struct GlobalConfig *config);
+
+#endif /* HEADER_CURL_TOOL_PARSECFG_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_sdecls.h b/external/libcurl_android/jni/libcurl/src/tool_sdecls.h
new file mode 100755
index 00000000..e74020f7
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_sdecls.h
@@ -0,0 +1,153 @@
+#ifndef HEADER_CURL_TOOL_SDECLS_H
+#define HEADER_CURL_TOOL_SDECLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+#ifdef USE_METALINK
+# include <metalink/metalink.h>
+#endif /* USE_METALINK */
+
+/*
+ * OutStruct variables keep track of information relative to curl's
+ * output writing, which may take place to a standard stream or a file.
+ *
+ * 'filename' member is either a pointer to a file name string or NULL
+ * when dealing with a standard stream.
+ *
+ * 'alloc_filename' member is TRUE when string pointed by 'filename' has been
+ * dynamically allocated and 'belongs' to this OutStruct, otherwise FALSE.
+ *
+ * 'is_cd_filename' member is TRUE when string pointed by 'filename' has been
+ * set using a server-specified Content-Disposition filename, otherwise FALSE.
+ *
+ * 's_isreg' member is TRUE when output goes to a regular file, this also
+ * implies that output is 'seekable' and 'appendable' and also that member
+ * 'filename' points to file name's string. For any standard stream member
+ * 's_isreg' will be FALSE.
+ *
+ * 'fopened' member is TRUE when output goes to a regular file and it
+ * has been fopen'ed, requiring it to be closed later on. In any other
+ * case this is FALSE.
+ *
+ * 'stream' member is a pointer to a stream controlling object as returned
+ * from a 'fopen' call or a standard stream.
+ *
+ * 'config' member is a pointer to associated 'OperationConfig' struct.
+ *
+ * 'bytes' member represents amount written so far.
+ *
+ * 'init' member holds original file size or offset at which truncation is
+ * taking place. Always zero unless appending to a non-empty regular file.
+ *
+ * 'metalink_parser' member is a pointer to Metalink XML parser
+ * context.
+ */
+
+struct OutStruct {
+ char *filename;
+ bool alloc_filename;
+ bool is_cd_filename;
+ bool s_isreg;
+ bool fopened;
+ FILE *stream;
+ struct OperationConfig *config;
+ curl_off_t bytes;
+ curl_off_t init;
+#ifdef USE_METALINK
+ metalink_parser_context_t *metalink_parser;
+#endif /* USE_METALINK */
+};
+
+
+/*
+ * InStruct variables keep track of information relative to curl's
+ * input reading, which may take place from stdin or from some file.
+ *
+ * 'fd' member is either 'stdin' file descriptor number STDIN_FILENO
+ * or a file descriptor as returned from an 'open' call for some file.
+ *
+ * 'config' member is a pointer to associated 'OperationConfig' struct.
+ */
+
+struct InStruct {
+ int fd;
+ struct OperationConfig *config;
+};
+
+
+/*
+ * A linked list of these 'getout' nodes contain URL's to fetch,
+ * as well as information relative to where URL contents should
+ * be stored or which file should be uploaded.
+ */
+
+struct getout {
+ struct getout *next; /* next one */
+ char *url; /* the URL we deal with */
+ char *outfile; /* where to store the output */
+ char *infile; /* file to upload, if GETOUT_UPLOAD is set */
+ int flags; /* options - composed of GETOUT_* bits */
+};
+
+#define GETOUT_OUTFILE (1<<0) /* set when outfile is deemed done */
+#define GETOUT_URL (1<<1) /* set when URL is deemed done */
+#define GETOUT_USEREMOTE (1<<2) /* use remote file name locally */
+#define GETOUT_UPLOAD (1<<3) /* if set, -T has been used */
+#define GETOUT_NOUPLOAD (1<<4) /* if set, -T "" has been used */
+#define GETOUT_METALINK (1<<5) /* set when Metalink download */
+
+/*
+ * 'trace' enumeration represents curl's output look'n feel possibilities.
+ */
+
+typedef enum {
+ TRACE_NONE, /* no trace/verbose output at all */
+ TRACE_BIN, /* tcpdump inspired look */
+ TRACE_ASCII, /* like *BIN but without the hex output */
+ TRACE_PLAIN /* -v/--verbose type */
+} trace;
+
+
+/*
+ * 'HttpReq' enumeration represents HTTP request types.
+ */
+
+typedef enum {
+ HTTPREQ_UNSPEC, /* first in list */
+ HTTPREQ_GET,
+ HTTPREQ_HEAD,
+ HTTPREQ_POST,
+ HTTPREQ_SIMPLEPOST,
+ HTTPREQ_CUSTOM,
+ HTTPREQ_LAST /* last in list */
+} HttpReq;
+
+
+/*
+ * Complete struct declarations which have OperationConfig struct members,
+ * just in case this header is directly included in some source file.
+ */
+
+#include "tool_cfgable.h"
+
+#endif /* HEADER_CURL_TOOL_SDECLS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_setopt.c b/external/libcurl_android/jni/libcurl/src/tool_setopt.c
new file mode 100755
index 00000000..62d94a65
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_setopt.c
@@ -0,0 +1,565 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+
+#include "tool_cfgable.h"
+#include "tool_easysrc.h"
+#include "tool_setopt.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* Lookup tables for converting setopt values back to symbols */
+/* For enums, values may be in any order. */
+/* For bit masks, put combinations first, then single bits, */
+/* and finally any "NONE" value. */
+
+#define NV(e) {#e, e}
+#define NV1(e, v) {#e, (v)}
+#define NVEND {NULL, 0} /* sentinel to mark end of list */
+
+const NameValue setopt_nv_CURLPROXY[] = {
+ NV(CURLPROXY_HTTP),
+ NV(CURLPROXY_HTTP_1_0),
+ NV(CURLPROXY_SOCKS4),
+ NV(CURLPROXY_SOCKS5),
+ NV(CURLPROXY_SOCKS4A),
+ NV(CURLPROXY_SOCKS5_HOSTNAME),
+ NVEND,
+};
+
+const NameValueUnsigned setopt_nv_CURLAUTH[] = {
+ NV(CURLAUTH_ANY), /* combination */
+ NV(CURLAUTH_ANYSAFE), /* combination */
+ NV(CURLAUTH_BASIC),
+ NV(CURLAUTH_DIGEST),
+ NV(CURLAUTH_GSSNEGOTIATE),
+ NV(CURLAUTH_NTLM),
+ NV(CURLAUTH_DIGEST_IE),
+ NV(CURLAUTH_NTLM_WB),
+ NV(CURLAUTH_ONLY),
+ NV(CURLAUTH_NONE),
+ NVEND,
+};
+
+const NameValue setopt_nv_CURL_HTTP_VERSION[] = {
+ NV(CURL_HTTP_VERSION_NONE),
+ NV(CURL_HTTP_VERSION_1_0),
+ NV(CURL_HTTP_VERSION_1_1),
+ NVEND,
+};
+
+const NameValue setopt_nv_CURL_SSLVERSION[] = {
+ NV(CURL_SSLVERSION_DEFAULT),
+ NV(CURL_SSLVERSION_TLSv1),
+ NV(CURL_SSLVERSION_SSLv2),
+ NV(CURL_SSLVERSION_SSLv3),
+ NV(CURL_SSLVERSION_TLSv1_0),
+ NV(CURL_SSLVERSION_TLSv1_1),
+ NV(CURL_SSLVERSION_TLSv1_2),
+ NVEND,
+};
+
+const NameValue setopt_nv_CURL_TIMECOND[] = {
+ NV(CURL_TIMECOND_IFMODSINCE),
+ NV(CURL_TIMECOND_IFUNMODSINCE),
+ NV(CURL_TIMECOND_LASTMOD),
+ NV(CURL_TIMECOND_NONE),
+ NVEND,
+};
+
+const NameValue setopt_nv_CURLFTPSSL_CCC[] = {
+ NV(CURLFTPSSL_CCC_NONE),
+ NV(CURLFTPSSL_CCC_PASSIVE),
+ NV(CURLFTPSSL_CCC_ACTIVE),
+ NVEND,
+};
+
+const NameValue setopt_nv_CURLUSESSL[] = {
+ NV(CURLUSESSL_NONE),
+ NV(CURLUSESSL_TRY),
+ NV(CURLUSESSL_CONTROL),
+ NV(CURLUSESSL_ALL),
+ NVEND,
+};
+
+const NameValue setopt_nv_CURL_NETRC[] = {
+ NV(CURL_NETRC_IGNORED),
+ NV(CURL_NETRC_OPTIONAL),
+ NV(CURL_NETRC_REQUIRED),
+ NVEND,
+};
+
+/* These mappings essentially triplicated - see
+ * tool_libinfo.c and tool_paramhlp.c */
+const NameValue setopt_nv_CURLPROTO[] = {
+ NV(CURLPROTO_ALL), /* combination */
+ NV(CURLPROTO_DICT),
+ NV(CURLPROTO_FILE),
+ NV(CURLPROTO_FTP),
+ NV(CURLPROTO_FTPS),
+ NV(CURLPROTO_GOPHER),
+ NV(CURLPROTO_HTTP),
+ NV(CURLPROTO_HTTPS),
+ NV(CURLPROTO_IMAP),
+ NV(CURLPROTO_IMAPS),
+ NV(CURLPROTO_LDAP),
+ NV(CURLPROTO_LDAPS),
+ NV(CURLPROTO_POP3),
+ NV(CURLPROTO_POP3S),
+ NV(CURLPROTO_RTSP),
+ NV(CURLPROTO_SCP),
+ NV(CURLPROTO_SFTP),
+ NV(CURLPROTO_SMTP),
+ NV(CURLPROTO_SMTPS),
+ NV(CURLPROTO_TELNET),
+ NV(CURLPROTO_TFTP),
+ NVEND,
+};
+
+/* These options have non-zero default values. */
+static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
+ NV1(CURLOPT_SSL_VERIFYPEER, 1),
+ NV1(CURLOPT_SSL_VERIFYHOST, 1),
+ NV1(CURLOPT_SSL_ENABLE_NPN, 1),
+ NV1(CURLOPT_SSL_ENABLE_ALPN, 1),
+ NVEND
+};
+
+/* Format and add code; jump to nomem on malloc error */
+#define ADD(args) do { \
+ ret = easysrc_add args; \
+ if(ret) \
+ goto nomem; \
+} WHILE_FALSE
+#define ADDF(args) do { \
+ ret = easysrc_addf args; \
+ if(ret) \
+ goto nomem; \
+} WHILE_FALSE
+
+#define DECL0(s) ADD((&easysrc_decl, s))
+#define DECL1(f,a) ADDF((&easysrc_decl, f,a))
+
+#define DATA0(s) ADD((&easysrc_data, s))
+#define DATA1(f,a) ADDF((&easysrc_data, f,a))
+#define DATA2(f,a,b) ADDF((&easysrc_data, f,a,b))
+#define DATA3(f,a,b,c) ADDF((&easysrc_data, f,a,b,c))
+
+#define CODE0(s) ADD((&easysrc_code, s))
+#define CODE1(f,a) ADDF((&easysrc_code, f,a))
+#define CODE2(f,a,b) ADDF((&easysrc_code, f,a,b))
+#define CODE3(f,a,b,c) ADDF((&easysrc_code, f,a,b,c))
+
+#define CLEAN0(s) ADD((&easysrc_clean, s))
+#define CLEAN1(f,a) ADDF((&easysrc_clean, f,a))
+
+#define REM0(s) ADD((&easysrc_toohard, s))
+#define REM1(f,a) ADDF((&easysrc_toohard, f,a))
+#define REM2(f,a,b) ADDF((&easysrc_toohard, f,a,b))
+
+/* Escape string to C string syntax. Return NULL if out of memory.
+ * Is this correct for those wacky EBCDIC guys? */
+static char *c_escape(const char *str)
+{
+ size_t len = 0;
+ const char *s;
+ unsigned char c;
+ char *escaped, *e;
+ /* Allocate space based on worst-case */
+ len = strlen(str);
+ escaped = malloc(4 * len + 1);
+ if(!escaped)
+ return NULL;
+
+ e = escaped;
+ for(s=str; (c=*s) != '\0'; s++) {
+ if(c=='\n') {
+ strcpy(e, "\\n");
+ e += 2;
+ }
+ else if(c=='\r') {
+ strcpy(e, "\\r");
+ e += 2;
+ }
+ else if(c=='\t') {
+ strcpy(e, "\\t");
+ e += 2;
+ }
+ else if(c=='\\') {
+ strcpy(e, "\\\\");
+ e += 2;
+ }
+ else if(c=='"') {
+ strcpy(e, "\\\"");
+ e += 2;
+ }
+ else if(! isprint(c)) {
+ snprintf(e, 4, "\\%03o", c);
+ e += 4;
+ }
+ else
+ *e++ = c;
+ }
+ *e = '\0';
+ return escaped;
+}
+
+/* setopt wrapper for enum types */
+CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const NameValue *nvlist, long lval)
+{
+ CURLcode ret = CURLE_OK;
+ bool skip = FALSE;
+
+ ret = curl_easy_setopt(curl, tag, lval);
+ if(!lval)
+ skip = TRUE;
+
+ if(config->libcurl && !skip && !ret) {
+ /* we only use this for real if --libcurl was used */
+ const NameValue *nv = NULL;
+ for(nv=nvlist; nv->name; nv++) {
+ if(nv->value == lval) break; /* found it */
+ }
+ if(! nv->name) {
+ /* If no definition was found, output an explicit value.
+ * This could happen if new values are defined and used
+ * but the NameValue list is not updated. */
+ CODE2("curl_easy_setopt(hnd, %s, %ldL);", name, lval);
+ }
+ else {
+ CODE2("curl_easy_setopt(hnd, %s, (long)%s);", name, nv->name);
+ }
+ }
+
+ nomem:
+ return ret;
+}
+
+/* setopt wrapper for flags */
+CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const NameValue *nvlist, long lval)
+{
+ CURLcode ret = CURLE_OK;
+ bool skip = FALSE;
+
+ ret = curl_easy_setopt(curl, tag, lval);
+ if(!lval)
+ skip = TRUE;
+
+ if(config->libcurl && !skip && !ret) {
+ /* we only use this for real if --libcurl was used */
+ char preamble[80]; /* should accommodate any symbol name */
+ long rest = lval; /* bits not handled yet */
+ const NameValue *nv = NULL;
+ snprintf(preamble, sizeof(preamble),
+ "curl_easy_setopt(hnd, %s, ", name);
+ for(nv=nvlist; nv->name; nv++) {
+ if((nv->value & ~ rest) == 0) {
+ /* all value flags contained in rest */
+ rest &= ~ nv->value; /* remove bits handled here */
+ CODE3("%s(long)%s%s",
+ preamble, nv->name, rest ? " |" : ");");
+ if(!rest)
+ break; /* handled them all */
+ /* replace with all spaces for continuation line */
+ snprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
+ }
+ }
+ /* If any bits have no definition, output an explicit value.
+ * This could happen if new bits are defined and used
+ * but the NameValue list is not updated. */
+ if(rest)
+ CODE2("%s%ldL);", preamble, rest);
+ }
+
+ nomem:
+ return ret;
+}
+
+/* setopt wrapper for bitmasks */
+CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const NameValueUnsigned *nvlist,
+ long lval)
+{
+ CURLcode ret = CURLE_OK;
+ bool skip = FALSE;
+
+ ret = curl_easy_setopt(curl, tag, lval);
+ if(!lval)
+ skip = TRUE;
+
+ if(config->libcurl && !skip && !ret) {
+ /* we only use this for real if --libcurl was used */
+ char preamble[80];
+ unsigned long rest = (unsigned long)lval;
+ const NameValueUnsigned *nv = NULL;
+ snprintf(preamble, sizeof(preamble),
+ "curl_easy_setopt(hnd, %s, ", name);
+ for(nv=nvlist; nv->name; nv++) {
+ if((nv->value & ~ rest) == 0) {
+ /* all value flags contained in rest */
+ rest &= ~ nv->value; /* remove bits handled here */
+ CODE3("%s(long)%s%s",
+ preamble, nv->name, rest ? " |" : ");");
+ if(!rest)
+ break; /* handled them all */
+ /* replace with all spaces for continuation line */
+ snprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
+ }
+ }
+ /* If any bits have no definition, output an explicit value.
+ * This could happen if new bits are defined and used
+ * but the NameValue list is not updated. */
+ if(rest)
+ CODE2("%s%luUL);", preamble, rest);
+ }
+
+ nomem:
+ return ret;
+}
+
+/* setopt wrapper for CURLOPT_HTTPPOST */
+CURLcode tool_setopt_httppost(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ struct curl_httppost *post)
+{
+ CURLcode ret = CURLE_OK;
+ char *escaped = NULL;
+ bool skip = FALSE;
+
+ ret = curl_easy_setopt(curl, tag, post);
+ if(!post)
+ skip = TRUE;
+
+ if(config->libcurl && !skip && !ret) {
+ struct curl_httppost *pp, *p;
+ int i;
+ /* May use several httppost lists, if multiple POST actions */
+ i = ++ easysrc_form_count;
+ DECL1("struct curl_httppost *post%d;", i);
+ DATA1("post%d = NULL;", i);
+ CLEAN1("curl_formfree(post%d);", i);
+ CLEAN1("post%d = NULL;", i);
+ if(i == 1)
+ DECL0("struct curl_httppost *postend;");
+ DATA0("postend = NULL;");
+ for(p=post; p; p=p->next) {
+ DATA1("curl_formadd(&post%d, &postend,", i);
+ DATA1(" CURLFORM_COPYNAME, \"%s\",", p->name);
+ for(pp=p; pp; pp=pp->more) {
+ /* May be several files uploaded for one name;
+ * these are linked through the 'more' pointer */
+ Curl_safefree(escaped);
+ escaped = c_escape(pp->contents);
+ if(!escaped) {
+ ret = CURLE_OUT_OF_MEMORY;
+ goto nomem;
+ }
+ if(pp->flags & HTTPPOST_FILENAME) {
+ /* file upload as for -F @filename */
+ DATA1(" CURLFORM_FILE, \"%s\",", escaped);
+ }
+ else if(pp->flags & HTTPPOST_READFILE) {
+ /* content from file as for -F <filename */
+ DATA1(" CURLFORM_FILECONTENT, \"%s\",", escaped);
+ }
+ else
+ DATA1(" CURLFORM_COPYCONTENTS, \"%s\",", escaped);
+ if(pp->showfilename) {
+ Curl_safefree(escaped);
+ escaped = c_escape(pp->showfilename);
+ if(!escaped) {
+ ret = CURLE_OUT_OF_MEMORY;
+ goto nomem;
+ }
+ DATA1(" CURLFORM_FILENAME, \"%s\",", escaped);
+ }
+ if(pp->contenttype) {
+ Curl_safefree(escaped);
+ escaped = c_escape(pp->contenttype);
+ if(!escaped) {
+ ret = CURLE_OUT_OF_MEMORY;
+ goto nomem;
+ }
+ DATA1(" CURLFORM_CONTENTTYPE, \"%s\",", escaped);
+ }
+ }
+ DATA0(" CURLFORM_END);");
+ }
+ CODE2("curl_easy_setopt(hnd, %s, post%d);", name, i);
+ }
+
+ nomem:
+ Curl_safefree(escaped);
+ return ret;
+}
+
+/* setopt wrapper for curl_slist options */
+CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ struct curl_slist *list)
+{
+ CURLcode ret = CURLE_OK;
+ char *escaped = NULL;
+ bool skip = FALSE;
+
+ ret = curl_easy_setopt(curl, tag, list);
+ if(!list)
+ skip = TRUE;
+
+ if(config->libcurl && !skip && !ret) {
+ struct curl_slist *s;
+ int i;
+ /* May need several slist variables, so invent name */
+ i = ++ easysrc_slist_count;
+ DECL1("struct curl_slist *slist%d;", i);
+ DATA1("slist%d = NULL;", i);
+ CLEAN1("curl_slist_free_all(slist%d);", i);
+ CLEAN1("slist%d = NULL;", i);
+ for(s=list; s; s=s->next) {
+ Curl_safefree(escaped);
+ escaped = c_escape(s->data);
+ if(!escaped) {
+ ret = CURLE_OUT_OF_MEMORY;
+ goto nomem;
+ }
+ DATA3("slist%d = curl_slist_append(slist%d, \"%s\");", i, i, escaped);
+ }
+ CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i);
+ }
+
+ nomem:
+ Curl_safefree(escaped);
+ return ret;
+}
+
+/* generic setopt wrapper for all other options.
+ * Some type information is encoded in the tag value. */
+CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
+ const char *name, CURLoption tag, ...)
+{
+ va_list arg;
+ char buf[256];
+ const char *value = NULL;
+ bool remark = FALSE;
+ bool skip = FALSE;
+ bool escape = FALSE;
+ char *escaped = NULL;
+ CURLcode ret = CURLE_OK;
+
+ va_start(arg, tag);
+
+ if(tag < CURLOPTTYPE_OBJECTPOINT) {
+ /* Value is expected to be a long */
+ long lval = va_arg(arg, long);
+ long defval = 0L;
+ const NameValue *nv = NULL;
+ for(nv=setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
+ if(!strcmp(name, nv->name)) {
+ defval = nv->value;
+ break; /* found it */
+ }
+ }
+
+ snprintf(buf, sizeof(buf), "%ldL", lval);
+ value = buf;
+ ret = curl_easy_setopt(curl, tag, lval);
+ if(lval == defval)
+ skip = TRUE;
+ }
+ else if(tag < CURLOPTTYPE_OFF_T) {
+ /* Value is some sort of object pointer */
+ void *pval = va_arg(arg, void *);
+
+ /* function pointers are never printable */
+ if(tag >= CURLOPTTYPE_FUNCTIONPOINT) {
+ if(pval) {
+ value = "functionpointer";
+ remark = TRUE;
+ }
+ else
+ skip = TRUE;
+ }
+
+ else if(pval && str) {
+ value = (char *)pval;
+ escape = TRUE;
+ }
+ else if(pval) {
+ value = "objectpointer";
+ remark = TRUE;
+ }
+ else
+ skip = TRUE;
+
+ ret = curl_easy_setopt(curl, tag, pval);
+
+ }
+ else {
+ /* Value is expected to be curl_off_t */
+ curl_off_t oval = va_arg(arg, curl_off_t);
+ snprintf(buf, sizeof(buf),
+ "(curl_off_t)%" CURL_FORMAT_CURL_OFF_T, oval);
+ value = buf;
+ ret = curl_easy_setopt(curl, tag, oval);
+
+ if(!oval)
+ skip = TRUE;
+ }
+
+ va_end(arg);
+
+ if(config->libcurl && !skip && !ret) {
+ /* we only use this for real if --libcurl was used */
+
+ if(remark)
+ REM2("%s set to a %s", name, value);
+ else {
+ if(escape) {
+ escaped = c_escape(value);
+ if(!escaped) {
+ ret = CURLE_OUT_OF_MEMORY;
+ goto nomem;
+ }
+ CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
+ }
+ else
+ CODE2("curl_easy_setopt(hnd, %s, %s);", name, value);
+ }
+ }
+
+ nomem:
+ Curl_safefree(escaped);
+ return ret;
+}
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_setopt.h b/external/libcurl_android/jni/libcurl/src/tool_setopt.h
new file mode 100755
index 00000000..cd144bc0
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_setopt.h
@@ -0,0 +1,148 @@
+#ifndef HEADER_CURL_TOOL_SETOPT_H
+#define HEADER_CURL_TOOL_SETOPT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+/*
+ * Macros used in operate()
+ */
+
+#define SETOPT_CHECK(v) do { \
+ res = (v); \
+ if(res) \
+ goto show_error; \
+} WHILE_FALSE
+
+#ifndef CURL_DISABLE_LIBCURL_OPTION
+
+/* Associate symbolic names with option values */
+typedef struct {
+ const char *name;
+ long value;
+} NameValue;
+
+typedef struct {
+ const char *name;
+ unsigned long value;
+} NameValueUnsigned;
+
+extern const NameValue setopt_nv_CURLPROXY[];
+extern const NameValue setopt_nv_CURL_HTTP_VERSION[];
+extern const NameValue setopt_nv_CURL_SSLVERSION[];
+extern const NameValue setopt_nv_CURL_TIMECOND[];
+extern const NameValue setopt_nv_CURLFTPSSL_CCC[];
+extern const NameValue setopt_nv_CURLUSESSL[];
+extern const NameValue setopt_nv_CURL_NETRC[];
+extern const NameValue setopt_nv_CURLPROTO[];
+extern const NameValueUnsigned setopt_nv_CURLAUTH[];
+
+/* Map options to NameValue sets */
+#define setopt_nv_CURLOPT_HTTP_VERSION setopt_nv_CURL_HTTP_VERSION
+#define setopt_nv_CURLOPT_HTTPAUTH setopt_nv_CURLAUTH
+#define setopt_nv_CURLOPT_SSLVERSION setopt_nv_CURL_SSLVERSION
+#define setopt_nv_CURLOPT_TIMECONDITION setopt_nv_CURL_TIMECOND
+#define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC
+#define setopt_nv_CURLOPT_USE_SSL setopt_nv_CURLUSESSL
+#define setopt_nv_CURLOPT_NETRC setopt_nv_CURL_NETRC
+#define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO
+#define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO
+#define setopt_nv_CURLOPT_PROXYTYPE setopt_nv_CURLPROXY
+#define setopt_nv_CURLOPT_PROXYAUTH setopt_nv_CURLAUTH
+
+/* Intercept setopt calls for --libcurl */
+
+CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const NameValue *nv, long lval);
+CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const NameValue *nv, long lval);
+CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ const NameValueUnsigned *nv, long lval);
+CURLcode tool_setopt_httppost(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ struct curl_httppost *httppost);
+CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ struct curl_slist *list);
+CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
+ const char *name, CURLoption tag, ...);
+
+#define my_setopt(x,y,z) \
+ SETOPT_CHECK(tool_setopt(x, FALSE, global, #y, y, z))
+
+#define my_setopt_str(x,y,z) \
+ SETOPT_CHECK(tool_setopt(x, TRUE, global, #y, y, z))
+
+#define my_setopt_enum(x,y,z) \
+ SETOPT_CHECK(tool_setopt_enum(x, global, #y, y, setopt_nv_ ## y, z))
+
+#define my_setopt_flags(x,y,z) \
+ SETOPT_CHECK(tool_setopt_flags(x, global, #y, y, setopt_nv_ ## y, z))
+
+#define my_setopt_bitmask(x,y,z) \
+ SETOPT_CHECK(tool_setopt_bitmask(x, global, #y, y, setopt_nv_ ## y, z))
+
+#define my_setopt_httppost(x,y,z) \
+ SETOPT_CHECK(tool_setopt_httppost(x, global, #y, y, z))
+
+#define my_setopt_slist(x,y,z) \
+ SETOPT_CHECK(tool_setopt_slist(x, global, #y, y, z))
+
+#define res_setopt(x,y,z) tool_setopt(x, FALSE, global, #y, y, z)
+
+#define res_setopt_str(x,y,z) tool_setopt(x, TRUE, global, #y, y, z)
+
+#else /* CURL_DISABLE_LIBCURL_OPTION */
+
+/* No --libcurl, so pass options directly to library */
+
+#define my_setopt(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z))
+
+#define my_setopt_str(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z))
+
+#define my_setopt_enum(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z))
+
+#define my_setopt_flags(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z))
+
+#define my_setopt_bitmask(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z))
+
+#define my_setopt_httppost(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z))
+
+#define my_setopt_slist(x,y,z) \
+ SETOPT_CHECK(curl_easy_setopt(x, y, z))
+
+#define res_setopt(x,y,z) curl_easy_setopt(x,y,z)
+
+#define res_setopt_str(x,y,z) curl_easy_setopt(x,y,z)
+
+#endif /* CURL_DISABLE_LIBCURL_OPTION */
+
+#endif /* HEADER_CURL_TOOL_SETOPT_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_setup.h b/external/libcurl_android/jni/libcurl/src/tool_setup.h
new file mode 100755
index 00000000..c94686f9
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_setup.h
@@ -0,0 +1,75 @@
+#ifndef HEADER_CURL_TOOL_SETUP_H
+#define HEADER_CURL_TOOL_SETUP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#define CURL_NO_OLDIES
+
+/*
+ * curl_setup.h may define preprocessor macros such as _FILE_OFFSET_BITS and
+ * _LARGE_FILES in order to support files larger than 2 GB. On platforms
+ * where this happens it is mandatory that these macros are defined before
+ * any system header file is included, otherwise file handling function
+ * prototypes will be misdeclared and curl tool may not build properly;
+ * therefore we must include curl_setup.h before curl.h when building curl.
+ */
+
+#include "curl_setup.h" /* from the lib directory */
+
+/*
+ * curl tool certainly uses libcurl's external interface.
+ */
+
+#include <curl/curl.h> /* external interface */
+
+/*
+ * Platform specific stuff.
+ */
+
+#if defined(macintosh) && defined(__MRC__)
+# define main(x,y) curl_main(x,y)
+#endif
+
+#ifdef TPF
+# undef select
+ /* change which select is used for the curl command line tool */
+# define select(a,b,c,d,e) tpf_select_bsd(a,b,c,d,e)
+ /* and turn off the progress meter */
+# define CONF_DEFAULT (0|CONF_NOPROGRESS)
+#endif
+
+#ifndef OS
+# define OS "unknown"
+#endif
+
+#ifndef UNPRINTABLE_CHAR
+ /* define what to use for unprintable characters */
+# define UNPRINTABLE_CHAR '.'
+#endif
+
+#ifndef HAVE_STRDUP
+# include "strdup.h"
+# define strdup(ptr) curlx_strdup(ptr)
+#endif
+
+#endif /* HEADER_CURL_TOOL_SETUP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_sleep.c b/external/libcurl_android/jni/libcurl/src/tool_sleep.c
new file mode 100755
index 00000000..49cdc71b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_sleep.c
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#elif defined(HAVE_POLL_H)
+# include <poll.h>
+#endif
+
+#ifdef MSDOS
+# include <dos.h>
+#endif
+
+#include "tool_sleep.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void tool_go_sleep(long ms)
+{
+#if defined(MSDOS)
+ delay(ms);
+#elif defined(WIN32)
+ Sleep(ms);
+#elif defined(HAVE_POLL_FINE)
+ poll((void *)0, 0, (int)ms);
+#else
+ struct timeval timeout;
+ timeout.tv_sec = ms / 1000L;
+ ms = ms % 1000L;
+ timeout.tv_usec = ms * 1000L;
+ select(0, NULL, NULL, NULL, &timeout);
+#endif
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_sleep.h b/external/libcurl_android/jni/libcurl/src/tool_sleep.h
new file mode 100755
index 00000000..115a4e40
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_sleep.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_TOOL_SLEEP_H
+#define HEADER_CURL_TOOL_SLEEP_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void tool_go_sleep(long ms);
+
+#endif /* HEADER_CURL_TOOL_SLEEP_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_urlglob.c b/external/libcurl_android/jni/libcurl/src/tool_urlglob.c
new file mode 100755
index 00000000..36e83c33
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_urlglob.c
@@ -0,0 +1,674 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
+#include <curl/mprintf.h>
+
+#include "tool_urlglob.h"
+#include "tool_vms.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+typedef enum {
+ GLOB_OK,
+ GLOB_NO_MEM = CURLE_OUT_OF_MEMORY,
+ GLOB_ERROR = CURLE_URL_MALFORMAT
+} GlobCode;
+
+#define GLOBERROR(string, column, code) \
+ glob->error = string, glob->pos = column, code
+
+void glob_cleanup(URLGlob* glob);
+
+static GlobCode glob_fixed(URLGlob *glob, char *fixed, size_t len)
+{
+ URLPattern *pat = &glob->pattern[glob->size];
+ pat->type = UPTSet;
+ pat->content.Set.size = 1;
+ pat->content.Set.ptr_s = 0;
+ pat->globindex = -1;
+
+ pat->content.Set.elements = malloc(sizeof(char*));
+
+ if(!pat->content.Set.elements)
+ return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
+
+ pat->content.Set.elements[0] = malloc(len+1);
+ if(!pat->content.Set.elements[0])
+ return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
+
+ memcpy(pat->content.Set.elements[0], fixed, len);
+ pat->content.Set.elements[0][len] = 0;
+
+ return GLOB_OK;
+}
+
+/* multiply
+ *
+ * Multiplies and checks for overflow.
+ */
+static int multiply(unsigned long *amount, long with)
+{
+ unsigned long sum = *amount * with;
+ if(sum/with != *amount)
+ return 1; /* didn't fit, bail out */
+ *amount = sum;
+ return 0;
+}
+
+static GlobCode glob_set(URLGlob *glob, char **patternp,
+ size_t *posp, unsigned long *amount,
+ int globindex)
+{
+ /* processes a set expression with the point behind the opening '{'
+ ','-separated elements are collected until the next closing '}'
+ */
+ URLPattern *pat;
+ bool done = FALSE;
+ char *buf = glob->glob_buffer;
+ char *pattern = *patternp;
+ char *opattern = pattern;
+ size_t opos = *posp-1;
+
+ pat = &glob->pattern[glob->size];
+ /* patterns 0,1,2,... correspond to size=1,3,5,... */
+ pat->type = UPTSet;
+ pat->content.Set.size = 0;
+ pat->content.Set.ptr_s = 0;
+ pat->content.Set.elements = NULL;
+ pat->globindex = globindex;
+
+ while(!done) {
+ switch (*pattern) {
+ case '\0': /* URL ended while set was still open */
+ return GLOBERROR("unmatched brace", opos, GLOB_ERROR);
+
+ case '{':
+ case '[': /* no nested expressions at this time */
+ return GLOBERROR("nested brace", *posp, GLOB_ERROR);
+
+ case '}': /* set element completed */
+ if(opattern == pattern)
+ return GLOBERROR("empty string within braces", *posp, GLOB_ERROR);
+
+ /* add 1 to size since it'll be incremented below */
+ if(multiply(amount, pat->content.Set.size+1))
+ return GLOBERROR("range overflow", 0, GLOB_ERROR);
+
+ /* fall-through */
+ case ',':
+
+ *buf = '\0';
+ if(pat->content.Set.elements) {
+ char **new_arr = realloc(pat->content.Set.elements,
+ (pat->content.Set.size + 1) * sizeof(char*));
+ if(!new_arr)
+ return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
+
+ pat->content.Set.elements = new_arr;
+ }
+ else
+ pat->content.Set.elements = malloc(sizeof(char*));
+
+ if(!pat->content.Set.elements)
+ return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
+
+ pat->content.Set.elements[pat->content.Set.size] =
+ strdup(glob->glob_buffer);
+ if(!pat->content.Set.elements[pat->content.Set.size])
+ return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
+ ++pat->content.Set.size;
+
+ if(*pattern == '}') {
+ pattern++; /* pass the closing brace */
+ done = TRUE;
+ continue;
+ }
+
+ buf = glob->glob_buffer;
+ ++pattern;
+ ++(*posp);
+ break;
+
+ case ']': /* illegal closing bracket */
+ return GLOBERROR("unexpected close bracket", *posp, GLOB_ERROR);
+
+ case '\\': /* escaped character, skip '\' */
+ if(pattern[1]) {
+ ++pattern;
+ ++(*posp);
+ }
+ /* intentional fallthrough */
+ default:
+ *buf++ = *pattern++; /* copy character to set element */
+ ++(*posp);
+ }
+ }
+
+ *patternp = pattern; /* return with the new position */
+ return GLOB_OK;
+}
+
+static GlobCode glob_range(URLGlob *glob, char **patternp,
+ size_t *posp, unsigned long *amount,
+ int globindex)
+{
+ /* processes a range expression with the point behind the opening '['
+ - char range: e.g. "a-z]", "B-Q]"
+ - num range: e.g. "0-9]", "17-2000]"
+ - num range with leading zeros: e.g. "001-999]"
+ expression is checked for well-formedness and collected until the next ']'
+ */
+ URLPattern *pat;
+ int rc;
+ char *pattern = *patternp;
+ char *c;
+
+ pat = &glob->pattern[glob->size];
+ pat->globindex = globindex;
+
+ if(ISALPHA(*pattern)) {
+ /* character range detected */
+ char min_c;
+ char max_c;
+ int step=1;
+
+ pat->type = UPTCharRange;
+
+ rc = sscanf(pattern, "%c-%c", &min_c, &max_c);
+
+ if((rc == 2) && (pattern[3] == ':')) {
+ char *endp;
+ unsigned long lstep;
+ errno = 0;
+ lstep = strtoul(&pattern[3], &endp, 10);
+ if(errno || (*endp != ']'))
+ step = -1;
+ else {
+ pattern = endp+1;
+ step = (int)lstep;
+ if(step > (max_c - min_c))
+ step = -1;
+ }
+ }
+ else
+ pattern += 4;
+
+ *posp += (pattern - *patternp);
+
+ if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
+ (step < 0) )
+ /* the pattern is not well-formed */
+ return GLOBERROR("bad range", *posp, GLOB_ERROR);
+
+ /* if there was a ":[num]" thing, use that as step or else use 1 */
+ pat->content.CharRange.step = step;
+ pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c;
+ pat->content.CharRange.max_c = max_c;
+
+ if(multiply(amount, (pat->content.CharRange.max_c -
+ pat->content.CharRange.min_c + 1)))
+ return GLOBERROR("range overflow", *posp, GLOB_ERROR);
+ }
+ else if(ISDIGIT(*pattern)) {
+ /* numeric range detected */
+ unsigned long min_n;
+ unsigned long max_n = 0;
+ unsigned long step_n = 0;
+ char *endp;
+
+ pat->type = UPTNumRange;
+ pat->content.NumRange.padlength = 0;
+
+ if(*pattern == '0') {
+ /* leading zero specified, count them! */
+ c = pattern;
+ while(ISDIGIT(*c)) {
+ c++;
+ ++pat->content.NumRange.padlength; /* padding length is set for all
+ instances of this pattern */
+ }
+ }
+
+ errno = 0;
+ min_n = strtoul(pattern, &endp, 10);
+ if(errno || (endp == pattern))
+ endp=NULL;
+ else {
+ if(*endp != '-')
+ endp = NULL;
+ else {
+ pattern = endp+1;
+ errno = 0;
+ max_n = strtoul(pattern, &endp, 10);
+ if(errno || (*endp == ':')) {
+ pattern = endp+1;
+ errno = 0;
+ step_n = strtoul(pattern, &endp, 10);
+ if(errno)
+ /* over/underflow situation */
+ endp = NULL;
+ }
+ else
+ step_n = 1;
+ if(endp && (*endp == ']')) {
+ pattern= endp+1;
+ }
+ else
+ endp = NULL;
+ }
+ }
+
+ *posp += (pattern - *patternp);
+
+ if(!endp || (min_n > max_n) || (step_n > (max_n - min_n)))
+ /* the pattern is not well-formed */
+ return GLOBERROR("bad range", *posp, GLOB_ERROR);
+
+ /* typecasting to ints are fine here since we make sure above that we
+ are within 31 bits */
+ pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
+ pat->content.NumRange.max_n = max_n;
+ pat->content.NumRange.step = step_n;
+
+ if(multiply(amount, (pat->content.NumRange.max_n -
+ pat->content.NumRange.min_n + 1)))
+ return GLOBERROR("range overflow", *posp, GLOB_ERROR);
+ }
+ else
+ return GLOBERROR("bad range specification", *posp, GLOB_ERROR);
+
+ *patternp = pattern;
+ return GLOB_OK;
+}
+
+static bool peek_ipv6(const char *str, size_t *skip)
+{
+ /*
+ * Scan for a potential IPv6 literal.
+ * - Valid globs contain a hyphen and <= 1 colon.
+ * - IPv6 literals contain no hyphens and >= 2 colons.
+ */
+ size_t i = 0;
+ size_t colons = 0;
+ if(str[i++] != '[') {
+ return FALSE;
+ }
+ for(;;) {
+ const char c = str[i++];
+ if(ISALNUM(c) || c == '.' || c == '%') {
+ /* ok */
+ }
+ else if(c == ':') {
+ colons++;
+ }
+ else if(c == ']') {
+ *skip = i;
+ return colons >= 2 ? TRUE : FALSE;
+ }
+ else {
+ return FALSE;
+ }
+ }
+}
+
+static GlobCode glob_parse(URLGlob *glob, char *pattern,
+ size_t pos, unsigned long *amount)
+{
+ /* processes a literal string component of a URL
+ special characters '{' and '[' branch to set/range processing functions
+ */
+ GlobCode res = GLOB_OK;
+ int globindex = 0; /* count "actual" globs */
+
+ *amount = 1;
+
+ while(*pattern && !res) {
+ char *buf = glob->glob_buffer;
+ size_t sublen = 0;
+ while(*pattern && *pattern != '{') {
+ if(*pattern == '[') {
+ /* Skip over potential IPv6 literals. */
+ size_t skip;
+ if(peek_ipv6(pattern, &skip)) {
+ memcpy(buf, pattern, skip);
+ buf += skip;
+ pattern += skip;
+ sublen += skip;
+ continue;
+ }
+ break;
+ }
+ if(*pattern == '}' || *pattern == ']')
+ return GLOBERROR("unmatched close brace/bracket", pos, GLOB_ERROR);
+
+ /* only allow \ to escape known "special letters" */
+ if(*pattern == '\\' &&
+ (*(pattern+1) == '{' || *(pattern+1) == '[' ||
+ *(pattern+1) == '}' || *(pattern+1) == ']') ) {
+
+ /* escape character, skip '\' */
+ ++pattern;
+ ++pos;
+ }
+ *buf++ = *pattern++; /* copy character to literal */
+ ++pos;
+ sublen++;
+ }
+ if(sublen) {
+ /* we got a literal string, add it as a single-item list */
+ *buf = '\0';
+ res = glob_fixed(glob, glob->glob_buffer, sublen);
+ }
+ else {
+ switch (*pattern) {
+ case '\0': /* done */
+ break;
+
+ case '{':
+ /* process set pattern */
+ pattern++;
+ pos++;
+ res = glob_set(glob, &pattern, &pos, amount, globindex++);
+ break;
+
+ case '[':
+ /* process range pattern */
+ pattern++;
+ pos++;
+ res = glob_range(glob, &pattern, &pos, amount, globindex++);
+ break;
+ }
+ }
+
+ if(++glob->size > GLOB_PATTERN_NUM)
+ return GLOBERROR("too many globs", pos, GLOB_ERROR);
+ }
+ return res;
+}
+
+int glob_url(URLGlob** glob, char* url, unsigned long *urlnum, FILE *error)
+{
+ /*
+ * We can deal with any-size, just make a buffer with the same length
+ * as the specified URL!
+ */
+ URLGlob *glob_expand;
+ unsigned long amount = 0;
+ char *glob_buffer;
+ GlobCode res;
+
+ *glob = NULL;
+
+ glob_buffer = malloc(strlen(url) + 1);
+ if(!glob_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ glob_expand = calloc(1, sizeof(URLGlob));
+ if(!glob_expand) {
+ Curl_safefree(glob_buffer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ glob_expand->urllen = strlen(url);
+ glob_expand->glob_buffer = glob_buffer;
+
+ res = glob_parse(glob_expand, url, 1, &amount);
+ if(!res)
+ *urlnum = amount;
+ else {
+ if(error && glob_expand->error) {
+ char text[128];
+ const char *t;
+ if(glob_expand->pos) {
+ snprintf(text, sizeof(text), "%s in column %zu", glob_expand->error,
+ glob_expand->pos);
+ t = text;
+ }
+ else
+ t = glob_expand->error;
+
+ /* send error description to the error-stream */
+ fprintf(error, "curl: (%d) [globbing] %s\n", res, t);
+ }
+ /* it failed, we cleanup */
+ glob_cleanup(glob_expand);
+ *urlnum = 1;
+ return res;
+ }
+
+ *glob = glob_expand;
+ return CURLE_OK;
+}
+
+void glob_cleanup(URLGlob* glob)
+{
+ size_t i;
+ int elem;
+
+ /* the < condition is required since i underflows! */
+ for(i = glob->size - 1; i < glob->size; --i) {
+ if((glob->pattern[i].type == UPTSet) &&
+ (glob->pattern[i].content.Set.elements)) {
+ for(elem = glob->pattern[i].content.Set.size - 1;
+ elem >= 0;
+ --elem) {
+ Curl_safefree(glob->pattern[i].content.Set.elements[elem]);
+ }
+ Curl_safefree(glob->pattern[i].content.Set.elements);
+ }
+ }
+ Curl_safefree(glob->glob_buffer);
+ Curl_safefree(glob);
+}
+
+int glob_next_url(char **globbed, URLGlob *glob)
+{
+ URLPattern *pat;
+ size_t i;
+ size_t j;
+ size_t len;
+ size_t buflen = glob->urllen + 1;
+ char *buf = glob->glob_buffer;
+
+ *globbed = NULL;
+
+ if(!glob->beenhere)
+ glob->beenhere = 1;
+ else {
+ bool carry = TRUE;
+
+ /* implement a counter over the index ranges of all patterns,
+ starting with the rightmost pattern */
+ /* the < condition is required since i underflows! */
+ for(i = glob->size - 1; carry && (i < glob->size); --i) {
+ carry = FALSE;
+ pat = &glob->pattern[i];
+ switch (pat->type) {
+ case UPTSet:
+ if((pat->content.Set.elements) &&
+ (++pat->content.Set.ptr_s == pat->content.Set.size)) {
+ pat->content.Set.ptr_s = 0;
+ carry = TRUE;
+ }
+ break;
+ case UPTCharRange:
+ pat->content.CharRange.ptr_c = (char)(pat->content.CharRange.step +
+ (int)((unsigned char)pat->content.CharRange.ptr_c));
+ if(pat->content.CharRange.ptr_c > pat->content.CharRange.max_c) {
+ pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
+ carry = TRUE;
+ }
+ break;
+ case UPTNumRange:
+ pat->content.NumRange.ptr_n += pat->content.NumRange.step;
+ if(pat->content.NumRange.ptr_n > pat->content.NumRange.max_n) {
+ pat->content.NumRange.ptr_n = pat->content.NumRange.min_n;
+ carry = TRUE;
+ }
+ break;
+ default:
+ printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
+ return CURLE_FAILED_INIT;
+ }
+ }
+ if(carry) { /* first pattern ptr has run into overflow, done! */
+ /* TODO: verify if this should actally return CURLE_OK. */
+ return CURLE_OK; /* CURLE_OK to match previous behavior */
+ }
+ }
+
+ for(j = 0; j < glob->size; ++j) {
+ pat = &glob->pattern[j];
+ switch(pat->type) {
+ case UPTSet:
+ if(pat->content.Set.elements) {
+ len = strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
+ snprintf(buf, buflen, "%s",
+ pat->content.Set.elements[pat->content.Set.ptr_s]);
+ buf += len;
+ buflen -= len;
+ }
+ break;
+ case UPTCharRange:
+ *buf++ = pat->content.CharRange.ptr_c;
+ break;
+ case UPTNumRange:
+ len = snprintf(buf, buflen, "%0*ld",
+ pat->content.NumRange.padlength,
+ pat->content.NumRange.ptr_n);
+ buf += len;
+ buflen -= len;
+ break;
+ default:
+ printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
+ return CURLE_FAILED_INIT;
+ }
+ }
+ *buf = '\0';
+
+ *globbed = strdup(glob->glob_buffer);
+ if(!*globbed)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
+int glob_match_url(char **result, char *filename, URLGlob *glob)
+{
+ char *target;
+ size_t allocsize;
+ char numbuf[18];
+ char *appendthis = NULL;
+ size_t appendlen = 0;
+ size_t stringlen = 0;
+
+ *result = NULL;
+
+ /* We cannot use the glob_buffer for storage here since the filename may
+ * be longer than the URL we use. We allocate a good start size, then
+ * we need to realloc in case of need.
+ */
+ allocsize = strlen(filename) + 1; /* make it at least one byte to store the
+ trailing zero */
+ target = malloc(allocsize);
+ if(!target)
+ return CURLE_OUT_OF_MEMORY;
+
+ while(*filename) {
+ if(*filename == '#' && ISDIGIT(filename[1])) {
+ unsigned long i;
+ char *ptr = filename;
+ unsigned long num = strtoul(&filename[1], &filename, 10);
+ URLPattern *pat =NULL;
+
+ if(num < glob->size) {
+ num--; /* make it zero based */
+ /* find the correct glob entry */
+ for(i=0; i<glob->size; i++) {
+ if(glob->pattern[i].globindex == (int)num) {
+ pat = &glob->pattern[i];
+ break;
+ }
+ }
+ }
+
+ if(pat) {
+ switch (pat->type) {
+ case UPTSet:
+ if(pat->content.Set.elements) {
+ appendthis = pat->content.Set.elements[pat->content.Set.ptr_s];
+ appendlen =
+ strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
+ }
+ break;
+ case UPTCharRange:
+ numbuf[0] = pat->content.CharRange.ptr_c;
+ numbuf[1] = 0;
+ appendthis = numbuf;
+ appendlen = 1;
+ break;
+ case UPTNumRange:
+ snprintf(numbuf, sizeof(numbuf), "%0*d",
+ pat->content.NumRange.padlength,
+ pat->content.NumRange.ptr_n);
+ appendthis = numbuf;
+ appendlen = strlen(numbuf);
+ break;
+ default:
+ fprintf(stderr, "internal error: invalid pattern type (%d)\n",
+ (int)pat->type);
+ Curl_safefree(target);
+ return CURLE_FAILED_INIT;
+ }
+ }
+ else {
+ /* #[num] out of range, use the #[num] in the output */
+ filename = ptr;
+ appendthis = filename++;
+ appendlen = 1;
+ }
+ }
+ else {
+ appendthis = filename++;
+ appendlen = 1;
+ }
+ if(appendlen + stringlen >= allocsize) {
+ char *newstr;
+ /* we append a single byte to allow for the trailing byte to be appended
+ at the end of this function outside the while() loop */
+ allocsize = (appendlen + stringlen) * 2;
+ newstr = realloc(target, allocsize + 1);
+ if(!newstr) {
+ Curl_safefree(target);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ target = newstr;
+ }
+ memcpy(&target[stringlen], appendthis, appendlen);
+ stringlen += appendlen;
+ }
+ target[stringlen]= '\0';
+ *result = target;
+ return CURLE_OK;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_urlglob.h b/external/libcurl_android/jni/libcurl/src/tool_urlglob.h
new file mode 100755
index 00000000..9fa6f83b
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_urlglob.h
@@ -0,0 +1,77 @@
+#ifndef HEADER_CURL_TOOL_URLGLOB_H
+#define HEADER_CURL_TOOL_URLGLOB_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+typedef enum {
+ UPTSet = 1,
+ UPTCharRange,
+ UPTNumRange
+} URLPatternType;
+
+typedef struct {
+ URLPatternType type;
+ int globindex; /* the number of this particular glob or -1 if not used
+ within {} or [] */
+ union {
+ struct {
+ char **elements;
+ int size;
+ int ptr_s;
+ } Set;
+ struct {
+ char min_c;
+ char max_c;
+ char ptr_c;
+ int step;
+ } CharRange;
+ struct {
+ unsigned long min_n;
+ unsigned long max_n;
+ int padlength;
+ unsigned long ptr_n;
+ unsigned long step;
+ } NumRange ;
+ } content;
+} URLPattern;
+
+/* the total number of globs supported */
+#define GLOB_PATTERN_NUM 100
+
+typedef struct {
+ URLPattern pattern[GLOB_PATTERN_NUM];
+ size_t size;
+ size_t urllen;
+ char *glob_buffer;
+ char beenhere;
+ const char *error; /* error message */
+ size_t pos; /* column position of error or 0 */
+} URLGlob;
+
+int glob_url(URLGlob**, char*, unsigned long *, FILE *);
+int glob_next_url(char **, URLGlob *);
+int glob_match_url(char **, char*, URLGlob *);
+void glob_cleanup(URLGlob* glob);
+
+#endif /* HEADER_CURL_TOOL_URLGLOB_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_util.c b/external/libcurl_android/jni/libcurl/src/tool_util.c
new file mode 100755
index 00000000..00d205eb
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_util.c
@@ -0,0 +1,138 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#include "tool_util.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#if defined(WIN32) && !defined(MSDOS)
+
+struct timeval tool_tvnow(void)
+{
+ /*
+ ** GetTickCount() is available on _all_ Windows versions from W95 up
+ ** to nowadays. Returns milliseconds elapsed since last system boot,
+ ** increases monotonically and wraps once 49.7 days have elapsed.
+ */
+ struct timeval now;
+ DWORD milliseconds = GetTickCount();
+ now.tv_sec = milliseconds / 1000;
+ now.tv_usec = (milliseconds % 1000) * 1000;
+ return now;
+}
+
+#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
+
+struct timeval tool_tvnow(void)
+{
+ /*
+ ** clock_gettime() is granted to be increased monotonically when the
+ ** monotonic clock is queried. Time starting point is unspecified, it
+ ** could be the system start-up time, the Epoch, or something else,
+ ** in any case the time starting point does not change once that the
+ ** system has started up.
+ */
+ struct timeval now;
+ struct timespec tsnow;
+ if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
+ now.tv_sec = tsnow.tv_sec;
+ now.tv_usec = tsnow.tv_nsec / 1000;
+ }
+ /*
+ ** Even when the configure process has truly detected monotonic clock
+ ** availability, it might happen that it is not actually available at
+ ** run-time. When this occurs simply fallback to other time source.
+ */
+#ifdef HAVE_GETTIMEOFDAY
+ else
+ (void)gettimeofday(&now, NULL);
+#else
+ else {
+ now.tv_sec = (long)time(NULL);
+ now.tv_usec = 0;
+ }
+#endif
+ return now;
+}
+
+#elif defined(HAVE_GETTIMEOFDAY)
+
+struct timeval tool_tvnow(void)
+{
+ /*
+ ** gettimeofday() is not granted to be increased monotonically, due to
+ ** clock drifting and external source time synchronization it can jump
+ ** forward or backward in time.
+ */
+ struct timeval now;
+ (void)gettimeofday(&now, NULL);
+ return now;
+}
+
+#else
+
+struct timeval tool_tvnow(void)
+{
+ /*
+ ** time() returns the value of time in seconds since the Epoch.
+ */
+ struct timeval now;
+ now.tv_sec = (long)time(NULL);
+ now.tv_usec = 0;
+ return now;
+}
+
+#endif
+
+/*
+ * Make sure that the first argument is the more recent time, as otherwise
+ * we'll get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+long tool_tvdiff(struct timeval newer, struct timeval older)
+{
+ return (newer.tv_sec-older.tv_sec)*1000+
+ (newer.tv_usec-older.tv_usec)/1000;
+}
+
+/*
+ * Same as tool_tvdiff but with full usec resolution.
+ *
+ * Returns: the time difference in seconds with subsecond resolution.
+ */
+double tool_tvdiff_secs(struct timeval newer, struct timeval older)
+{
+ if(newer.tv_sec != older.tv_sec)
+ return (double)(newer.tv_sec-older.tv_sec)+
+ (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+ else
+ return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+}
+
+/* return the number of seconds in the given input timeval struct */
+long tool_tvlong(struct timeval t1)
+{
+ return t1.tv_sec;
+}
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_util.h b/external/libcurl_android/jni/libcurl/src/tool_util.h
new file mode 100755
index 00000000..d8bb0366
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_util.h
@@ -0,0 +1,56 @@
+#ifndef HEADER_CURL_TOOL_UTIL_H
+#define HEADER_CURL_TOOL_UTIL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+struct timeval tool_tvnow(void);
+
+/*
+ * Make sure that the first argument (t1) is the more recent time and t2 is
+ * the older time, as otherwise you get a weird negative time-diff back...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+long tool_tvdiff(struct timeval t1, struct timeval t2);
+
+/*
+ * Same as tool_tvdiff but with full usec resolution.
+ *
+ * Returns: the time difference in seconds with subsecond resolution.
+ */
+double tool_tvdiff_secs(struct timeval t1, struct timeval t2);
+
+long tool_tvlong(struct timeval t1);
+
+#undef tvnow
+#undef tvdiff
+#undef tvdiff_secs
+#undef tvlong
+
+#define tvnow() tool_tvnow()
+#define tvdiff(a,b) tool_tvdiff((a), (b))
+#define tvdiff_secs(a,b) tool_tvdiff_secs((a), (b))
+#define tvlong(a) tool_tvlong((a))
+
+#endif /* HEADER_CURL_TOOL_UTIL_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_version.h b/external/libcurl_android/jni/libcurl/src/tool_version.h
new file mode 100755
index 00000000..0c09149e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_version.h
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_TOOL_VERSION_H
+#define HEADER_CURL_TOOL_VERSION_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include <curl/curlver.h>
+
+#define CURL_NAME "curl"
+#define CURL_COPYRIGHT LIBCURL_COPYRIGHT
+#define CURL_VERSION "7.38.0"
+#define CURL_VERSION_MAJOR LIBCURL_VERSION_MAJOR
+#define CURL_VERSION_MINOR LIBCURL_VERSION_MINOR
+#define CURL_VERSION_PATCH LIBCURL_VERSION_PATCH
+#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
+
+#endif /* HEADER_CURL_TOOL_VERSION_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_vms.c b/external/libcurl_android/jni/libcurl/src/tool_vms.c
new file mode 100755
index 00000000..4a6a6f58
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_vms.c
@@ -0,0 +1,219 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef __VMS
+
+#if defined(__DECC) && !defined(__VAX) && \
+ defined(__CRTL_VER) && (__CRTL_VER >= 70301000)
+#include <unixlib.h>
+#endif
+
+#define ENABLE_CURLX_PRINTF
+#include "curlx.h"
+
+#include "curlmsg_vms.h"
+#include "tool_vms.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+void decc$__posix_exit(int __status);
+void decc$exit(int __status);
+
+static int vms_shell = -1;
+
+/* VMS has a DCL shell and and also has Unix shells ported to it.
+ * When curl is running under a Unix shell, we want it to be as much
+ * like Unix as possible.
+ */
+int is_vms_shell(void)
+{
+ char *shell;
+
+ /* Have we checked the shell yet? */
+ if(vms_shell >= 0)
+ return vms_shell;
+
+ shell = getenv("SHELL");
+
+ /* No shell, means DCL */
+ if(shell == NULL) {
+ vms_shell = 1;
+ return 1;
+ }
+
+ /* Have to make sure some one did not set shell to DCL */
+ if(strcmp(shell, "DCL") == 0) {
+ vms_shell = 1;
+ return 1;
+ }
+
+ vms_shell = 0;
+ return 0;
+}
+
+/*
+ * VMS has two exit() routines. When running under a Unix style shell, then
+ * Unix style and the __posix_exit() routine is used.
+ *
+ * When running under the DCL shell, then the VMS encoded codes and decc$exit()
+ * is used.
+ *
+ * We can not use exit() or return a code from main() because the actual
+ * routine called depends on both the compiler version, compile options, and
+ * feature macro settings, and one of the exit routines is hidden at compile
+ * time.
+ *
+ * Since we want Curl to work properly under the VMS DCL shell and Unix
+ * shells under VMS, this routine should compile correctly regardless of
+ * the settings.
+ */
+
+void vms_special_exit(int code, int vms_show)
+{
+ int vms_code;
+
+ /* The Posix exit mode is only available after VMS 7.0 */
+#if __CRTL_VER >= 70000000
+ if(is_vms_shell() == 0) {
+ decc$__posix_exit(code);
+ }
+#endif
+
+ if(code > CURL_LAST) { /* If CURL_LAST exceeded then */
+ vms_code = CURL_LAST; /* curlmsg.h is out of sync. */
+ }
+ else {
+ vms_code = vms_cond[code] | vms_show;
+ }
+ decc$exit(vms_code);
+}
+
+#if defined(__DECC) && !defined(__VAX) && \
+ defined(__CRTL_VER) && (__CRTL_VER >= 70301000)
+
+/*
+ * 2004-09-19 SMS.
+ *
+ * decc_init()
+ *
+ * On non-VAX systems, use LIB$INITIALIZE to set a collection of C
+ * RTL features without using the DECC$* logical name method, nor
+ * requiring the user to define the corresponding logical names.
+ */
+
+/* Structure to hold a DECC$* feature name and its desired value. */
+typedef struct {
+ char *name;
+ int value;
+} decc_feat_t;
+
+/* Array of DECC$* feature names and their desired values. */
+static decc_feat_t decc_feat_array[] = {
+ /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
+ { "DECC$ARGV_PARSE_STYLE", 1 },
+ /* Preserve case for file names on ODS5 disks. */
+ { "DECC$EFS_CASE_PRESERVE", 1 },
+ /* Enable multiple dots (and most characters) in ODS5 file names,
+ while preserving VMS-ness of ";version". */
+ { "DECC$EFS_CHARSET", 1 },
+ /* List terminator. */
+ { (char *)NULL, 0 }
+};
+
+/* Flag to sense if decc_init() was called. */
+static int decc_init_done = -1;
+
+/* LIB$INITIALIZE initialization function. */
+static void decc_init(void)
+{
+ int feat_index;
+ int feat_value;
+ int feat_value_max;
+ int feat_value_min;
+ int i;
+ int sts;
+
+ /* Set the global flag to indicate that LIB$INITIALIZE worked. */
+ decc_init_done = 1;
+
+ /* Loop through all items in the decc_feat_array[]. */
+ for(i = 0; decc_feat_array[i].name != NULL; i++) {
+
+ /* Get the feature index. */
+ feat_index = decc$feature_get_index( decc_feat_array[i].name);
+
+ if(feat_index >= 0) {
+ /* Valid item. Collect its properties. */
+ feat_value = decc$feature_get_value( feat_index, 1);
+ feat_value_min = decc$feature_get_value( feat_index, 2);
+ feat_value_max = decc$feature_get_value( feat_index, 3);
+
+ if((decc_feat_array[i].value >= feat_value_min) &&
+ (decc_feat_array[i].value <= feat_value_max)) {
+ /* Valid value. Set it if necessary. */
+ if(feat_value != decc_feat_array[i].value) {
+ sts = decc$feature_set_value( feat_index, 1,
+ decc_feat_array[i].value);
+ }
+ }
+ else {
+ /* Invalid DECC feature value. */
+ printf(" INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\n",
+ feat_value,
+ feat_value_min, decc_feat_array[i].name, feat_value_max);
+ }
+ }
+ else {
+ /* Invalid DECC feature name. */
+ printf(" UNKNOWN DECC FEATURE: %s.\n", decc_feat_array[i].name);
+ }
+
+ }
+}
+
+/* Get "decc_init()" into a valid, loaded LIB$INITIALIZE PSECT. */
+
+#pragma nostandard
+
+/* Establish the LIB$INITIALIZE PSECTs, with proper alignment and
+ other attributes. Note that "nopic" is significant only on VAX. */
+#pragma extern_model save
+#pragma extern_model strict_refdef "LIB$INITIALIZ" 2, nopic, nowrt
+const int spare[8] = {0};
+#pragma extern_model strict_refdef "LIB$INITIALIZE" 2, nopic, nowrt
+void (*const x_decc_init)() = decc_init;
+#pragma extern_model restore
+
+/* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */
+#pragma extern_model save
+int LIB$INITIALIZE(void);
+#pragma extern_model strict_refdef
+int dmy_lib$initialize = (int) LIB$INITIALIZE;
+#pragma extern_model restore
+
+#pragma standard
+
+#endif /* __DECC && !__VAX && __CRTL_VER && __CRTL_VER >= 70301000 */
+
+#endif /* __VMS */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_vms.h b/external/libcurl_android/jni/libcurl/src/tool_vms.h
new file mode 100755
index 00000000..1afd75ec
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_vms.h
@@ -0,0 +1,47 @@
+#ifndef HEADER_CURL_TOOL_VMS_H
+#define HEADER_CURL_TOOL_VMS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef __VMS
+
+/*
+ * Forward-declaration of global variable vms_show defined
+ * in tool_main.c, used in main() as parameter for function
+ * vms_special_exit() to allow proper curl tool exiting.
+ */
+extern int vms_show;
+
+int is_vms_shell(void);
+void vms_special_exit(int code, int vms_show);
+
+#undef exit
+#define exit(__code) vms_special_exit((__code), (0))
+
+#define VMS_STS(c,f,e,s) (((c&0xF)<<28)|((f&0xFFF)<<16)|((e&0x1FFF)<3)|(s&7))
+#define VMSSTS_HIDE VMS_STS(1,0,0,0)
+
+#endif /* __VMS */
+
+#endif /* HEADER_CURL_TOOL_VMS_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_writeenv.c b/external/libcurl_android/jni/libcurl/src/tool_writeenv.c
new file mode 100755
index 00000000..a9462d00
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_writeenv.c
@@ -0,0 +1,116 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef USE_ENVIRONMENT
+
+#ifdef __riscos__
+# include <kernel.h>
+#endif
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "tool_writeenv.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+static const struct
+{
+ const char * name;
+ CURLINFO id;
+ enum {
+ writeenv_NONE,
+ writeenv_DOUBLE,
+ writeenv_LONG,
+ writeenv_STRING
+ } type;
+} variables[14] =
+{
+ {"curl_url_effective", CURLINFO_EFFECTIVE_URL, writeenv_STRING},
+ {"curl_http_code", CURLINFO_RESPONSE_CODE, writeenv_LONG},
+ {"curl_time_total", CURLINFO_TOTAL_TIME, writeenv_DOUBLE},
+ {"curl_time_namelookup", CURLINFO_NAMELOOKUP_TIME, writeenv_DOUBLE},
+ {"curl_time_connect", CURLINFO_CONNECT_TIME, writeenv_DOUBLE},
+ {"curl_time_pretransfer", CURLINFO_PRETRANSFER_TIME, writeenv_DOUBLE},
+ {"curl_time_starttransfer", CURLINFO_STARTTRANSFER_TIME, writeenv_DOUBLE},
+ {"curl_size_header", CURLINFO_HEADER_SIZE, writeenv_LONG},
+ {"curl_size_request", CURLINFO_REQUEST_SIZE, writeenv_LONG},
+ {"curl_size_download", CURLINFO_SIZE_DOWNLOAD, writeenv_DOUBLE},
+ {"curl_size_upload", CURLINFO_SIZE_UPLOAD, writeenv_DOUBLE},
+ {"curl_speed_download", CURLINFO_SPEED_DOWNLOAD, writeenv_DOUBLE},
+ {"curl_speed_upload", CURLINFO_SPEED_UPLOAD, writeenv_DOUBLE},
+ {NULL, 0, writeenv_NONE}
+ };
+
+static void internalSetEnv(const char * name, char * value)
+{
+ /* Add your OS-specific code here. */
+#ifdef __riscos__
+ _kernel_setenv(name, value);
+#elif defined (CURLDEBUG)
+ curl_memlog("ENV %s = %s\n", name, value);
+#endif
+ return;
+}
+
+void ourWriteEnv(CURL *curl)
+{
+ unsigned int i;
+ char *string, numtext[10];
+ long longinfo;
+ double doubleinfo;
+
+ for(i=0; variables[i].name; i++) {
+ switch (variables[i].type) {
+ case writeenv_STRING:
+ if(curl_easy_getinfo(curl, variables[i].id, &string) == CURLE_OK)
+ internalSetEnv(variables[i].name, string);
+ else
+ internalSetEnv(variables[i].name, NULL);
+ break;
+
+ case writeenv_LONG:
+ if(curl_easy_getinfo(curl, variables[i].id, &longinfo) == CURLE_OK) {
+ curl_msprintf(numtext, "%5ld", longinfo);
+ internalSetEnv(variables[i].name, numtext);
+ }
+ else
+ internalSetEnv(variables[i].name, NULL);
+ break;
+ case writeenv_DOUBLE:
+ if(curl_easy_getinfo(curl, variables[i].id, &doubleinfo) == CURLE_OK) {
+ curl_msprintf(numtext, "%6.2f", doubleinfo);
+ internalSetEnv(variables[i].name, numtext);
+ }
+ else
+ internalSetEnv(variables[i].name, NULL);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return;
+}
+
+#endif
diff --git a/external/libcurl_android/jni/libcurl/src/tool_writeenv.h b/external/libcurl_android/jni/libcurl/src/tool_writeenv.h
new file mode 100755
index 00000000..c0a952fe
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_writeenv.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_TOOL_WRITEENV_H
+#define HEADER_CURL_TOOL_WRITEENV_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef USE_ENVIRONMENT
+
+void ourWriteEnv(CURL *curl);
+
+#else
+# define ourWriteEnv(x) Curl_nop_stmt
+#endif
+
+#endif /* HEADER_CURL_TOOL_WRITEENV_H */
+
diff --git a/external/libcurl_android/jni/libcurl/src/tool_writeout.c b/external/libcurl_android/jni/libcurl/src/tool_writeout.c
new file mode 100755
index 00000000..f29d1ac3
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_writeout.c
@@ -0,0 +1,327 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
+#include <curl/mprintf.h>
+
+#include "tool_cfgable.h"
+#include "tool_writeout.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+typedef enum {
+ VAR_NONE, /* must be the first */
+ VAR_TOTAL_TIME,
+ VAR_NAMELOOKUP_TIME,
+ VAR_CONNECT_TIME,
+ VAR_APPCONNECT_TIME,
+ VAR_PRETRANSFER_TIME,
+ VAR_STARTTRANSFER_TIME,
+ VAR_SIZE_DOWNLOAD,
+ VAR_SIZE_UPLOAD,
+ VAR_SPEED_DOWNLOAD,
+ VAR_SPEED_UPLOAD,
+ VAR_HTTP_CODE,
+ VAR_HTTP_CODE_PROXY,
+ VAR_HEADER_SIZE,
+ VAR_REQUEST_SIZE,
+ VAR_EFFECTIVE_URL,
+ VAR_CONTENT_TYPE,
+ VAR_NUM_CONNECTS,
+ VAR_REDIRECT_TIME,
+ VAR_REDIRECT_COUNT,
+ VAR_FTP_ENTRY_PATH,
+ VAR_REDIRECT_URL,
+ VAR_SSL_VERIFY_RESULT,
+ VAR_EFFECTIVE_FILENAME,
+ VAR_PRIMARY_IP,
+ VAR_PRIMARY_PORT,
+ VAR_LOCAL_IP,
+ VAR_LOCAL_PORT,
+ VAR_NUM_OF_VARS /* must be the last */
+} replaceid;
+
+struct variable {
+ const char *name;
+ replaceid id;
+};
+
+
+static const struct variable replacements[]={
+ {"url_effective", VAR_EFFECTIVE_URL},
+ {"http_code", VAR_HTTP_CODE},
+ {"response_code", VAR_HTTP_CODE},
+ {"http_connect", VAR_HTTP_CODE_PROXY},
+ {"time_total", VAR_TOTAL_TIME},
+ {"time_namelookup", VAR_NAMELOOKUP_TIME},
+ {"time_connect", VAR_CONNECT_TIME},
+ {"time_appconnect", VAR_APPCONNECT_TIME},
+ {"time_pretransfer", VAR_PRETRANSFER_TIME},
+ {"time_starttransfer", VAR_STARTTRANSFER_TIME},
+ {"size_header", VAR_HEADER_SIZE},
+ {"size_request", VAR_REQUEST_SIZE},
+ {"size_download", VAR_SIZE_DOWNLOAD},
+ {"size_upload", VAR_SIZE_UPLOAD},
+ {"speed_download", VAR_SPEED_DOWNLOAD},
+ {"speed_upload", VAR_SPEED_UPLOAD},
+ {"content_type", VAR_CONTENT_TYPE},
+ {"num_connects", VAR_NUM_CONNECTS},
+ {"time_redirect", VAR_REDIRECT_TIME},
+ {"num_redirects", VAR_REDIRECT_COUNT},
+ {"ftp_entry_path", VAR_FTP_ENTRY_PATH},
+ {"redirect_url", VAR_REDIRECT_URL},
+ {"ssl_verify_result", VAR_SSL_VERIFY_RESULT},
+ {"filename_effective", VAR_EFFECTIVE_FILENAME},
+ {"remote_ip", VAR_PRIMARY_IP},
+ {"remote_port", VAR_PRIMARY_PORT},
+ {"local_ip", VAR_LOCAL_IP},
+ {"local_port", VAR_LOCAL_PORT},
+ {NULL, VAR_NONE}
+};
+
+void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo)
+{
+ FILE *stream = stdout;
+ const char *ptr = writeinfo;
+ char *stringp = NULL;
+ long longinfo;
+ double doubleinfo;
+
+ while(ptr && *ptr) {
+ if('%' == *ptr) {
+ if('%' == ptr[1]) {
+ /* an escaped %-letter */
+ fputc('%', stream);
+ ptr += 2;
+ }
+ else {
+ /* this is meant as a variable to output */
+ char *end;
+ char keepit;
+ int i;
+ if(('{' == ptr[1]) && ((end = strchr(ptr, '}')) != NULL)) {
+ bool match = FALSE;
+ ptr += 2; /* pass the % and the { */
+ keepit = *end;
+ *end = 0; /* zero terminate */
+ for(i = 0; replacements[i].name; i++) {
+ if(curl_strequal(ptr, replacements[i].name)) {
+ match = TRUE;
+ switch(replacements[i].id) {
+ case VAR_EFFECTIVE_URL:
+ if((CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &stringp))
+ && stringp)
+ fputs(stringp, stream);
+ break;
+ case VAR_HTTP_CODE:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &longinfo))
+ fprintf(stream, "%03ld", longinfo);
+ break;
+ case VAR_HTTP_CODE_PROXY:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE,
+ &longinfo))
+ fprintf(stream, "%03ld", longinfo);
+ break;
+ case VAR_HEADER_SIZE:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &longinfo))
+ fprintf(stream, "%ld", longinfo);
+ break;
+ case VAR_REQUEST_SIZE:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &longinfo))
+ fprintf(stream, "%ld", longinfo);
+ break;
+ case VAR_NUM_CONNECTS:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &longinfo))
+ fprintf(stream, "%ld", longinfo);
+ break;
+ case VAR_REDIRECT_COUNT:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &longinfo))
+ fprintf(stream, "%ld", longinfo);
+ break;
+ case VAR_REDIRECT_TIME:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME,
+ &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_TOTAL_TIME:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_NAMELOOKUP_TIME:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME,
+ &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_CONNECT_TIME:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_APPCONNECT_TIME:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME,
+ &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_PRETRANSFER_TIME:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME,
+ &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_STARTTRANSFER_TIME:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME,
+ &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_SIZE_UPLOAD:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &doubleinfo))
+ fprintf(stream, "%.0f", doubleinfo);
+ break;
+ case VAR_SIZE_DOWNLOAD:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD,
+ &doubleinfo))
+ fprintf(stream, "%.0f", doubleinfo);
+ break;
+ case VAR_SPEED_DOWNLOAD:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD,
+ &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_SPEED_UPLOAD:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &doubleinfo))
+ fprintf(stream, "%.3f", doubleinfo);
+ break;
+ case VAR_CONTENT_TYPE:
+ if((CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &stringp))
+ && stringp)
+ fputs(stringp, stream);
+ break;
+ case VAR_FTP_ENTRY_PATH:
+ if((CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &stringp))
+ && stringp)
+ fputs(stringp, stream);
+ break;
+ case VAR_REDIRECT_URL:
+ if((CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &stringp))
+ && stringp)
+ fputs(stringp, stream);
+ break;
+ case VAR_SSL_VERIFY_RESULT:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT,
+ &longinfo))
+ fprintf(stream, "%ld", longinfo);
+ break;
+ case VAR_EFFECTIVE_FILENAME:
+ if(outs->filename)
+ fprintf(stream, "%s", outs->filename);
+ break;
+ case VAR_PRIMARY_IP:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP,
+ &stringp))
+ fprintf(stream, "%s", stringp);
+ break;
+ case VAR_PRIMARY_PORT:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_PRIMARY_PORT,
+ &longinfo))
+ fprintf(stream, "%ld", longinfo);
+ break;
+ case VAR_LOCAL_IP:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_LOCAL_IP,
+ &stringp))
+ fprintf(stream, "%s", stringp);
+ break;
+ case VAR_LOCAL_PORT:
+ if(CURLE_OK ==
+ curl_easy_getinfo(curl, CURLINFO_LOCAL_PORT,
+ &longinfo))
+ fprintf(stream, "%ld", longinfo);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ if(!match) {
+ fprintf(stderr, "curl: unknown --write-out variable: '%s'\n", ptr);
+ }
+ ptr = end + 1; /* pass the end */
+ *end = keepit;
+ }
+ else {
+ /* illegal syntax, then just output the characters that are used */
+ fputc('%', stream);
+ fputc(ptr[1], stream);
+ ptr += 2;
+ }
+ }
+ }
+ else if('\\' == *ptr) {
+ switch(ptr[1]) {
+ case 'r':
+ fputc('\r', stream);
+ break;
+ case 'n':
+ fputc('\n', stream);
+ break;
+ case 't':
+ fputc('\t', stream);
+ break;
+ default:
+ /* unknown, just output this */
+ fputc(*ptr, stream);
+ fputc(ptr[1], stream);
+ break;
+ }
+ ptr += 2;
+ }
+ else {
+ fputc(*ptr, stream);
+ ptr++;
+ }
+ }
+
+}
diff --git a/external/libcurl_android/jni/libcurl/src/tool_writeout.h b/external/libcurl_android/jni/libcurl/src/tool_writeout.h
new file mode 100755
index 00000000..4dd3a75a
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_writeout.h
@@ -0,0 +1,28 @@
+#ifndef HEADER_CURL_TOOL_WRITEOUT_H
+#define HEADER_CURL_TOOL_WRITEOUT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo);
+
+#endif /* HEADER_CURL_TOOL_WRITEOUT_H */
diff --git a/external/libcurl_android/jni/libcurl/src/tool_xattr.c b/external/libcurl_android/jni/libcurl/src/tool_xattr.c
new file mode 100755
index 00000000..b2666d97
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_xattr.c
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_FSETXATTR
+# include <sys/xattr.h> /* header from libc, not from libattr */
+# define USE_XATTR
+#elif defined(__FreeBSD_version) && (__FreeBSD_version > 500000)
+# include <sys/types.h>
+# include <sys/extattr.h>
+# define USE_XATTR
+#endif
+
+#include "tool_xattr.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+#ifdef USE_XATTR
+
+/* mapping table of curl metadata to extended attribute names */
+static const struct xattr_mapping {
+ const char *attr; /* name of the xattr */
+ CURLINFO info;
+} mappings[] = {
+ /* mappings proposed by
+ * http://freedesktop.org/wiki/CommonExtendedAttributes
+ */
+ { "user.xdg.origin.url", CURLINFO_EFFECTIVE_URL },
+ { "user.mime_type", CURLINFO_CONTENT_TYPE },
+ { NULL, CURLINFO_NONE } /* last element, abort loop here */
+};
+
+/* store metadata from the curl request alongside the downloaded
+ * file using extended attributes
+ */
+int fwrite_xattr(CURL *curl, int fd)
+{
+ int i = 0;
+ int err = 0;
+ /* loop through all xattr-curlinfo pairs and abort on a set error */
+ while(err == 0 && mappings[i].attr != NULL) {
+ char *value = NULL;
+ CURLcode rc = curl_easy_getinfo(curl, mappings[i].info, &value);
+ if(rc == CURLE_OK && value) {
+#ifdef HAVE_FSETXATTR_6
+ err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0);
+#elif defined(HAVE_FSETXATTR_5)
+ err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0);
+#elif defined(__FreeBSD_version)
+ err = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, mappings[i].attr, value,
+ strlen(value));
+ /* FreeBSD's extattr_set_fd returns the length of the extended attribute
+ */
+ err = err < 0 ? err : 0;
+#endif
+ }
+ i++;
+ }
+ return err;
+}
+#else
+int fwrite_xattr(CURL *curl, int fd)
+{
+ (void)curl;
+ (void)fd;
+ return 0;
+}
+#endif
diff --git a/external/libcurl_android/jni/libcurl/src/tool_xattr.h b/external/libcurl_android/jni/libcurl/src/tool_xattr.h
new file mode 100755
index 00000000..3f8f585e
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/tool_xattr.h
@@ -0,0 +1,28 @@
+#ifndef HEADER_CURL_TOOL_XATTR_H
+#define HEADER_CURL_TOOL_XATTR_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+int fwrite_xattr(CURL *curl, int fd);
+
+#endif /* HEADER_CURL_TOOL_XATTR_H */
diff --git a/external/libcurl_android/jni/libcurl/src/version.h b/external/libcurl_android/jni/libcurl/src/version.h
new file mode 100755
index 00000000..9260aa5d
--- /dev/null
+++ b/external/libcurl_android/jni/libcurl/src/version.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_VERSION_H
+#define HEADER_CURL_VERSION_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <curl/curlver.h>
+
+#define CURL_NAME "curl"
+#define CURL_COPYRIGHT LIBCURL_COPYRIGHT
+#define CURL_VERSION "7.22.0"
+#define CURL_VERSION_MAJOR LIBCURL_VERSION_MAJOR
+#define CURL_VERSION_MINOR LIBCURL_VERSION_MINOR
+#define CURL_VERSION_PATCH LIBCURL_VERSION_PATCH
+#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
+
+#endif /* HEADER_CURL_VERSION_H */
diff --git a/scripts/compile_androidviper.sh b/scripts/compile_androidviper.sh
index 215fecee..518580bd 100755
--- a/scripts/compile_androidviper.sh
+++ b/scripts/compile_androidviper.sh
@@ -14,7 +14,7 @@
##############################################################################
#!/bin/bash
-
+set -e
export ANDROID_HOME=${SDK}
export ANDROID_NDK_HOST=${OS}-${ARCH}
export ANDROID_NDK_PLATFORM=android-23
diff --git a/scripts/init.sh b/scripts/init.sh
index 7e3d8ccb..6324c6b0 100755
--- a/scripts/init.sh
+++ b/scripts/init.sh
@@ -158,24 +158,11 @@ fi
echo "Create libdash dependencies"
if [ ! -d ${INSTALLATION_DIR}/include/curl ]; then
- if [ ! -d curl ]; then
- git clone https://github.com/curl/curl.git
- cd curl
- export SYSROOT=$NDK/platforms/android-23/arch-arm
- export CC="$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/${OS}-${ARCH}/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT"
- ./buildconf
- ./configure --with-sysroot=$SYSROOT --host=arm
- mv src/tool_hugehelp.c.cvs src/tool_hugehelp.c
- cd ..
- fi
- cp -r curl/lib libcurl_android/jni/libcurl/
- cp -r curl/src libcurl_android/jni/libcurl/
- cp -r curl/include libcurl_android/jni/libcurl/
cd libcurl_android
${NDK}/ndk-build
echo "Copy libcurl in workspace"
cp -rf jni/libcurl/include/curl ${INSTALLATION_DIR}/include/
- cp -f obj/local/${ABI}/libcurl.a ${INSTALLATION_DIR}/lib/
+ cp -f obj/local/${ABI}/libcurl*.a ${INSTALLATION_DIR}/lib/
cd ..
fi
diff --git a/scripts/init_qt.sh b/scripts/init_qt.sh
index 93cefd3a..065bffa6 100755
--- a/scripts/init_qt.sh
+++ b/scripts/init_qt.sh
@@ -42,11 +42,18 @@ if [ ! -d ${QT_HOME} ]; then
fi
fi
-cp -f $DISTILLERY_INSTALL_DIR/lib/lib* ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/
+cp -f $DISTILLERY_INSTALL_DIR/lib/libicnet.so ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/
+cp -f $DISTILLERY_INSTALL_DIR/lib/libcrystax.so ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/
+cp -f $DISTILLERY_INSTALL_DIR/lib/libdash.so ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/
+cp -f $DISTILLERY_INSTALL_DIR/lib/libboost_system.so ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/
+
if [ ! -d ${QT_HOME}/5.7/android_${ANDROID_ARCH}/include/boost ]; then
- for folder in $(ls -d $DISTILLERY_INSTALL_DIR/include/*/); do
- ln -s $folder ${QT_HOME}/5.7/android_${ANDROID_ARCH}/include/
- done
+ ln -s $DISTILLERY_INSTALL_DIR/include/ccnx ${QT_HOME}/5.7/android_${ANDROID_ARCH}/include/
+ ln -s $DISTILLERY_INSTALL_DIR/include/boost ${QT_HOME}/5.7/android_${ANDROID_ARCH}/include/
+ ln -s $DISTILLERY_INSTALL_DIR/include/parc ${QT_HOME}/5.7/android_${ANDROID_ARCH}/include/
+ ln -s $DISTILLERY_INSTALL_DIR/include/LongBow ${QT_HOME}/5.7/android_${ANDROID_ARCH}/include/
+ ln -s $DISTILLERY_INSTALL_DIR/include/icnet ${QT_HOME}/5.7/android_${ANDROID_ARCH}/include/
+ ln -s $DISTILLERY_INSTALL_DIR/include/libdash ${QT_HOME}/5.7/android_${ANDROID_ARCH}/include/
fi
if [ ! -f ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/libavcodec.so -o ! -f ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/libavfilter.so -o ! -f ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/libavformat.so -o ! -f ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/libavutil.so -o ! -f ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/libswresample.so -o ! -f ${QT_HOME}/5.7/android_${ANDROID_ARCH}/lib/libswscale.so ]; then
diff --git a/scripts/update.sh b/scripts/update.sh
index e34a6261..e169cd2f 100755
--- a/scripts/update.sh
+++ b/scripts/update.sh
@@ -28,7 +28,5 @@ git pull
cd ../..
cd src/libicnet
git pull
-cd ../..
-cd src/viper
-git pull
-cd ../.. \ No newline at end of file
+cd ../..
+
diff --git a/src/libdash/CMakeLists.txt b/src/libdash/CMakeLists.txt
index a873e998..6c2c232e 100644
--- a/src/libdash/CMakeLists.txt
+++ b/src/libdash/CMakeLists.txt
@@ -9,8 +9,9 @@ if(ANDROID_API)
set(LIBXML2_INCLUDE_DIR "$ENV{DISTILLERY_ROOT_DIR}/external/libxml2_android/jni/libxml2/include")
set(LIBXML2_LIBRARIES "$ENV{DISTILLERY_ROOT_DIR}/usr/lib/libxml2.a")
set(CURL_INCLUDE_DIRS "$ENV{DISTILLERY_ROOT_DIR}/external/libcurl_android/jni/libcurl/include")
- set(CURL_LIBRARIES "$ENV{DISTILLERY_ROOT_DIR}/usr/lib/libcurl.a")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} ${ANDROID_C_FLAGS} -std=c++11 -Wall -fpermissive -O3")
+ set(CURL_LIBRARIES "$ENV{DISTILLERY_ROOT_DIR}/usr/lib/libcurl.a" "$ENV{DISTILLERY_ROOT_DIR}/usr/lib/libcurl-library.a")
+ set(ANDROID_LIBRARIES "${ANDROID_NDK}/platforms/android-23/arch-arm/usr/lib/libz.a" "$ENV{NDK}/sources/cxx-stl/gnu-libstdc++/4.9/libs/$ENV{ABI}/libgnustl_shared.so" "${ANDROID_NDK}/platforms/android-23/arch-arm/usr/lib/liblog.so")
+ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${ANDROID_C_FLAGS} -std=c++0x -g -DLOG_BUILD")
else ()
set(CMAKE_CXX_FLAGS "-std=c++0x -g -DLOG_BUILD")
find_package(LibXml2 REQUIRED)
@@ -180,7 +181,7 @@ include_directories(include)
add_library(dash SHARED ${SOURCE_FILES})
set_target_properties(dash PROPERTIES LINKER_LANGUAGE CXX)
-target_link_libraries(dash ${CURL_LIBRARIES} ${ZLIB_LIBRARIES} ${LIBXML2_LIBRARIES})
+target_link_libraries(dash ${CURL_LIBRARIES} ${ZLIB_LIBRARIES} ${LIBXML2_LIBRARIES} ${ANDROID_LIBRARIES})
message("libxml ${LIBXML2_LIBRARIES} ${LIBXML2_INCLUDE_DIR}")
install(TARGETS dash DESTINATION ${CMAKE_INSTALL_PREFIX}/lib PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
install(FILES ${HEADER_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/libdash)