summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorng0 <ng0@infotropique.org>2017-10-06 14:15:34 +0000
committerng0 <ng0@infotropique.org>2017-10-06 14:15:34 +0000
commit64d20516fc61405cf0de4db0b0b8c52b3cafe917 (patch)
tree804233b6e02880b5774b9cc3a015ddaeb036717a
parentdc3acc1603d57da12f54d5e360e40eda12b1066c (diff)
parent3ea76790571c1f7cf1bed34fabffd3cc20ad3dd3 (diff)
downloadgnurl-64d20516fc61405cf0de4db0b0b8c52b3cafe917.tar.gz
gnurl-64d20516fc61405cf0de4db0b0b8c52b3cafe917.tar.bz2
gnurl-64d20516fc61405cf0de4db0b0b8c52b3cafe917.zip
Merge tag 'curl-7_56_0'
curl 7.56.0
-rw-r--r--.gitignore5
-rw-r--r--.mailmap26
-rw-r--r--.travis.yml48
-rw-r--r--CMake/Macros.cmake29
-rw-r--r--CMakeLists.txt114
-rw-r--r--Makefile.am3
-rw-r--r--RELEASE-NOTES245
-rwxr-xr-x[-rw-r--r--]acinclude.m4325
-rwxr-xr-x[-rw-r--r--]configure.ac218
-rw-r--r--docs/CODE_OF_CONDUCT.md4
-rw-r--r--docs/HELP-US.md70
-rw-r--r--docs/HISTORY.md18
-rw-r--r--docs/INSTALL.md3
-rw-r--r--docs/KNOWN_BUGS16
-rw-r--r--docs/MAIL-ETIQUETTE31
-rw-r--r--docs/Makefile.am2
-rw-r--r--docs/THANKS30
-rw-r--r--docs/TODO49
-rw-r--r--docs/cmdline-opts/Makefile.inc3
-rw-r--r--docs/cmdline-opts/cacert.d2
-rw-r--r--docs/cmdline-opts/compressed-ssh.d7
-rw-r--r--docs/cmdline-opts/form-string.d4
-rw-r--r--docs/cmdline-opts/form.d80
-rwxr-xr-xdocs/cmdline-opts/gen.pl2
-rw-r--r--docs/cmdline-opts/request-target.d1
-rw-r--r--docs/examples/.gitignore1
-rw-r--r--docs/examples/10-at-a-time.c8
-rw-r--r--docs/examples/Makefile.inc9
-rw-r--r--docs/examples/anyauthput.c4
-rw-r--r--docs/examples/cacertinmem.c44
-rw-r--r--docs/examples/chkspeed.c4
-rw-r--r--docs/examples/curlx.c71
-rw-r--r--docs/examples/debug.c24
-rw-r--r--docs/examples/evhiperfifo.c24
-rw-r--r--docs/examples/fopen.c81
-rw-r--r--docs/examples/ftpget.c8
-rw-r--r--docs/examples/ftpsget.c8
-rw-r--r--docs/examples/ftpupload.c4
-rw-r--r--docs/examples/ftpuploadresume.c36
-rw-r--r--docs/examples/ghiper.c44
-rw-r--r--docs/examples/hiperfifo.c22
-rw-r--r--docs/examples/htmltidy.c6
-rw-r--r--docs/examples/http2-download.c30
-rw-r--r--docs/examples/http2-serverpush.c28
-rw-r--r--docs/examples/http2-upload.c30
-rw-r--r--docs/examples/httpput.c4
-rw-r--r--docs/examples/imap-multi.c4
-rw-r--r--docs/examples/multi-app.c12
-rw-r--r--docs/examples/multi-debugcallback.c26
-rw-r--r--docs/examples/multi-double.c4
-rw-r--r--docs/examples/multi-formadd.c171
-rw-r--r--docs/examples/multi-post.c62
-rw-r--r--docs/examples/multithread.c4
-rw-r--r--docs/examples/opensslthreadlock.c4
-rw-r--r--docs/examples/pop3-multi.c4
-rw-r--r--docs/examples/post-callback.c55
-rw-r--r--docs/examples/postinmemory.c4
-rw-r--r--docs/examples/postit2-formadd.c107
-rw-r--r--docs/examples/postit2.c56
-rw-r--r--docs/examples/sendrecv.c4
-rw-r--r--docs/examples/sftpget.c8
-rw-r--r--docs/examples/simplepost.c4
-rw-r--r--docs/examples/simplessl.c4
-rw-r--r--docs/examples/smooth-gtk-thread.c6
-rw-r--r--docs/examples/smtp-mail.c4
-rw-r--r--docs/examples/smtp-mime.c162
-rw-r--r--docs/examples/smtp-multi.c8
-rw-r--r--docs/examples/smtp-ssl.c4
-rw-r--r--docs/examples/smtp-tls.c4
-rw-r--r--docs/examples/sslbackend.c77
-rw-r--r--docs/examples/synctime.c10
-rw-r--r--docs/examples/threaded-ssl.c18
-rw-r--r--docs/examples/usercertinmem.c4
-rw-r--r--docs/libcurl/Makefile.inc6
-rw-r--r--docs/libcurl/gnurl_easy_setopt.34
-rw-r--r--docs/libcurl/gnurl_formadd.323
-rw-r--r--docs/libcurl/gnurl_formfree.38
-rw-r--r--docs/libcurl/gnurl_formget.37
-rw-r--r--docs/libcurl/gnurl_global_init.33
-rw-r--r--docs/libcurl/gnurl_global_sslset.397
-rw-r--r--docs/libcurl/gnurl_mime_addpart.366
-rw-r--r--docs/libcurl/gnurl_mime_data.369
-rw-r--r--docs/libcurl/gnurl_mime_data_cb.3160
-rw-r--r--docs/libcurl/gnurl_mime_encoder.397
-rw-r--r--docs/libcurl/gnurl_mime_filedata.377
-rw-r--r--docs/libcurl/gnurl_mime_filename.372
-rw-r--r--docs/libcurl/gnurl_mime_free.348
-rw-r--r--docs/libcurl/gnurl_mime_headers.365
-rw-r--r--docs/libcurl/gnurl_mime_init.369
-rw-r--r--docs/libcurl/gnurl_mime_name.363
-rw-r--r--docs/libcurl/gnurl_mime_subparts.353
-rw-r--r--docs/libcurl/gnurl_mime_type.383
-rw-r--r--docs/libcurl/gnurl_version_info.36
-rw-r--r--docs/libcurl/libgnurl-tutorial.3266
-rw-r--r--docs/libcurl/libgnurl.34
-rw-r--r--docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_PROTOCOL.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_SCHEME.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_CAPATH.35
-rw-r--r--docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.34
-rw-r--r--docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.34
-rw-r--r--docs/libcurl/opts/GNURLOPT_HTTPPOST.311
-rw-r--r--docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.37
-rw-r--r--docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.38
-rw-r--r--docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_MIMEPOST.352
-rw-r--r--docs/libcurl/opts/GNURLOPT_NOPROXY.37
-rw-r--r--docs/libcurl/opts/GNURLOPT_PRE_PROXY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY.33
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.37
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSH_COMPRESSION.358
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.34
-rw-r--r--docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_USERPWD.31
-rw-r--r--docs/libcurl/opts/Makefile.inc32
-rw-r--r--docs/libcurl/symbols-in-versions64
-rw-r--r--include/README2
-rw-r--r--include/gnurl/curl.h230
-rw-r--r--include/gnurl/curlver.h8
-rw-r--r--include/gnurl/multi.h2
-rw-r--r--include/gnurl/system.h112
-rw-r--r--include/gnurl/typecheck-gcc.h6
-rw-r--r--lib/Makefile.am20
-rw-r--r--lib/Makefile.inc5
-rw-r--r--lib/Makefile.m3232
-rw-r--r--lib/asyn-ares.c4
-rw-r--r--lib/asyn-thread.c21
-rwxr-xr-xlib/checksrc.pl55
-rw-r--r--lib/config-dos.h6
-rw-r--r--lib/config-tpf.h3
-rw-r--r--lib/config-win32.h6
-rw-r--r--lib/config-win32ce.h3
-rwxr-xr-x[-rw-r--r--]lib/connect.c41
-rw-r--r--lib/content_encoding.c6
-rw-r--r--lib/cookie.c142
-rw-r--r--lib/cookie.h11
-rw-r--r--lib/curl_addrinfo.c6
-rw-r--r--lib/curl_config.h.cmake9
-rw-r--r--lib/curl_fnmatch.c12
-rw-r--r--lib/curl_ntlm_core.c92
-rw-r--r--lib/curl_ntlm_core.h14
-rw-r--r--lib/curl_ntlm_wb.c7
-rw-r--r--lib/curl_sasl.c6
-rw-r--r--lib/curl_setup.h17
-rw-r--r--lib/dict.c14
-rw-r--r--lib/dotdot.c30
-rw-r--r--lib/easy.c16
-rw-r--r--lib/escape.c26
-rw-r--r--lib/file.c39
-rw-r--r--lib/formdata.c888
-rw-r--r--lib/formdata.h54
-rw-r--r--lib/ftp.c167
-rw-r--r--lib/ftp.h1
-rw-r--r--lib/ftplistparser.c38
-rw-r--r--lib/getinfo.c65
-rw-r--r--lib/gopher.c10
-rw-r--r--lib/hash.c4
-rw-r--r--lib/hostcheck.c14
-rw-r--r--lib/hostip.c12
-rw-r--r--lib/hostip4.c4
-rw-r--r--lib/hostip6.c4
-rw-r--r--lib/http.c425
-rw-r--r--lib/http.h6
-rw-r--r--lib/http2.c11
-rw-r--r--lib/http_chunks.c26
-rw-r--r--lib/http_ntlm.c13
-rw-r--r--lib/http_proxy.c30
-rw-r--r--lib/if2ip.c6
-rw-r--r--lib/imap.c118
-rw-r--r--lib/imap.h3
-rw-r--r--lib/inet_ntop.c2
-rw-r--r--lib/ldap.c4
-rw-r--r--lib/memdebug.c18
-rw-r--r--lib/mime.c1860
-rw-r--r--lib/mime.h135
-rw-r--r--lib/mprintf.c38
-rw-r--r--lib/multi.c62
-rw-r--r--lib/netrc.c39
-rw-r--r--lib/non-ascii.c83
-rw-r--r--lib/non-ascii.h4
-rw-r--r--lib/openldap.c12
-rw-r--r--lib/parsedate.c64
-rw-r--r--lib/pingpong.c28
-rw-r--r--lib/progress.c56
-rw-r--r--lib/progress.h2
-rw-r--r--lib/rtsp.c20
-rw-r--r--lib/security.c4
-rw-r--r--lib/sendf.c20
-rw-r--r--lib/smtp.c40
-rw-r--r--lib/socks.c22
-rw-r--r--lib/socks_gssapi.c59
-rw-r--r--lib/socks_sspi.c24
-rw-r--r--lib/splay.c2
-rw-r--r--lib/splay.h4
-rw-r--r--lib/ssh.c54
-rw-r--r--lib/strcase.c11
-rw-r--r--lib/strdup.c6
-rw-r--r--lib/strtoofft.c63
-rw-r--r--lib/strtoofft.h37
-rw-r--r--lib/telnet.c30
-rw-r--r--lib/tftp.c59
-rw-r--r--lib/transfer.c140
-rw-r--r--lib/transfer.h5
-rw-r--r--lib/url.c254
-rw-r--r--lib/urldata.h196
-rw-r--r--lib/vauth/digest_sspi.c4
-rw-r--r--lib/vauth/ntlm.c16
-rw-r--r--lib/vauth/ntlm_sspi.c9
-rw-r--r--lib/vauth/vauth.h5
-rw-r--r--lib/version.c8
-rw-r--r--lib/vtls/axtls.c190
-rw-r--r--lib/vtls/axtls.h39
-rw-r--r--lib/vtls/cyassl.c223
-rw-r--r--lib/vtls/cyassl.h63
-rw-r--r--lib/vtls/darwinssl.c450
-rw-r--r--lib/vtls/darwinssl.h71
-rw-r--r--lib/vtls/gskit.c191
-rw-r--r--lib/vtls/gskit.h38
-rw-r--r--lib/vtls/gtls.c210
-rw-r--r--lib/vtls/gtls.h64
-rw-r--r--lib/vtls/mbedtls.c237
-rw-r--r--lib/vtls/mbedtls.h52
-rw-r--r--lib/vtls/nss.c217
-rw-r--r--lib/vtls/nssg.h71
-rw-r--r--lib/vtls/openssl.c574
-rw-r--r--lib/vtls/openssl.h91
-rw-r--r--lib/vtls/polarssl.c198
-rw-r--r--lib/vtls/polarssl.h52
-rw-r--r--lib/vtls/polarssl_threadlock.c4
-rw-r--r--lib/vtls/schannel.c532
-rw-r--r--lib/vtls/schannel.h89
-rw-r--r--lib/vtls/vtls.c499
-rw-r--r--lib/vtls/vtls.h82
-rw-r--r--lib/warnless.c32
-rw-r--r--lib/wildcard.h2
-rw-r--r--m4/curl-compilers.m49
-rw-r--r--m4/curl-confopts.m48
-rw-r--r--packages/OS400/curl.inc.in4
-rw-r--r--projects/build-openssl.bat11
-rwxr-xr-xscripts/contributors.sh2
-rwxr-xr-xscripts/contrithanks.sh2
-rwxr-xr-xscripts/updatemanpages.pl2
-rwxr-xr-xscripts/zsh.pl5
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile.inc2
-rw-r--r--src/Makefile.m3232
-rw-r--r--src/tool_cb_dbg.c29
-rw-r--r--src/tool_cb_hdr.c2
-rw-r--r--src/tool_cb_prg.c4
-rw-r--r--src/tool_cfgable.c8
-rw-r--r--src/tool_cfgable.h5
-rw-r--r--src/tool_easysrc.c20
-rw-r--r--src/tool_easysrc.h4
-rw-r--r--src/tool_formparse.c713
-rw-r--r--src/tool_formparse.h6
-rw-r--r--src/tool_getparam.c39
-rw-r--r--src/tool_help.c11
-rw-r--r--src/tool_main.c9
-rw-r--r--src/tool_metalink.c19
-rw-r--r--src/tool_mfiles.c127
-rw-r--r--src/tool_msgs.c4
-rw-r--r--src/tool_operate.c110
-rw-r--r--src/tool_paramhlp.c36
-rw-r--r--src/tool_parsecfg.c4
-rw-r--r--src/tool_sdecls.h4
-rw-r--r--src/tool_setopt.c303
-rw-r--r--src/tool_setopt.h12
-rw-r--r--src/tool_strdup.c6
-rw-r--r--src/tool_urlglob.c24
-rw-r--r--tests/FILEFORMAT3
-rwxr-xr-xtests/curl_test_data.py21
-rw-r--r--tests/data/Makefile.inc23
-rw-r--r--tests/data/test10532
-rw-r--r--tests/data/test11334
-rw-r--r--tests/data/test113517
-rw-r--r--tests/data/test113927
-rw-r--r--tests/data/test114964
-rw-r--r--tests/data/test115055
-rw-r--r--tests/data/test115166
-rw-r--r--tests/data/test115261
-rw-r--r--tests/data/test115361
-rw-r--r--tests/data/test116049
-rw-r--r--tests/data/test116154
-rw-r--r--tests/data/test13154
-rw-r--r--tests/data/test14014
-rw-r--r--tests/data/test140467
-rw-r--r--tests/data/test144938
-rw-r--r--tests/data/test145338
-rw-r--r--tests/data/test1581
-rw-r--r--tests/data/test1631
-rw-r--r--tests/data/test1661
-rw-r--r--tests/data/test1736
-rw-r--r--tests/data/test1865
-rw-r--r--tests/data/test190479
-rw-r--r--tests/data/test205687
-rw-r--r--tests/data/test2057108
-rw-r--r--tests/data/test2596
-rw-r--r--tests/data/test2775
-rw-r--r--tests/data/test410
-rw-r--r--tests/data/test464
-rw-r--r--tests/data/test50616
-rw-r--r--tests/data/test5542
-rw-r--r--tests/data/test5642
-rw-r--r--tests/data/test5871
-rw-r--r--tests/data/test58955
-rw-r--r--tests/data/test64242
-rw-r--r--tests/data/test643131
-rw-r--r--tests/data/test64458
-rw-r--r--tests/data/test645141
-rw-r--r--tests/data/test64698
-rw-r--r--tests/data/test64779
-rw-r--r--tests/data/test64875
-rw-r--r--tests/data/test64972
-rw-r--r--tests/data/test650122
-rw-r--r--tests/data/test711
-rw-r--r--tests/data/test8004
-rw-r--r--tests/data/test84650
-rw-r--r--tests/data/test8563
-rw-r--r--tests/data/test91
-rwxr-xr-xtests/ftpserver.pl15
-rw-r--r--tests/fuzz/Makefile.am19
-rw-r--r--tests/fuzz/Makefile.inc26
-rw-r--r--tests/fuzz/README13
-rw-r--r--tests/fuzz/corpus.py96
-rw-r--r--tests/fuzz/curl_fuzz_data/oss-fuzz-3327bin0 -> 27 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test1bin0 -> 289 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test10bin0 -> 226 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test100bin0 -> 675 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test12bin0 -> 464 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test13bin0 -> 179 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test1326bin0 -> 62 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test1450bin0 -> 98 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test2bin0 -> 182 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test271bin0 -> 74 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test3bin0 -> 242 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test4bin0 -> 336 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test5bin0 -> 185 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test6bin0 -> 223 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test800bin0 -> 137 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test850bin0 -> 130 bytes
-rw-r--r--tests/fuzz/curl_fuzz_data/test900bin0 -> 129 bytes
-rw-r--r--tests/fuzz/curl_fuzzer.cc447
-rw-r--r--tests/fuzz/curl_fuzzer.h186
-rwxr-xr-xtests/fuzz/generate_corpus.py132
-rwxr-xr-xtests/fuzz/read_corpus.py69
-rw-r--r--tests/fuzz/standalone_fuzz_target_runner.cc89
-rw-r--r--tests/fuzz/testinput.h (renamed from src/tool_mfiles.h)27
-rw-r--r--tests/libtest/.gitignore3
-rw-r--r--tests/libtest/Makefile.am15
-rw-r--r--tests/libtest/Makefile.inc18
-rw-r--r--tests/libtest/first.c14
-rw-r--r--tests/libtest/lib1501.c4
-rw-r--r--tests/libtest/lib1502.c4
-rw-r--r--tests/libtest/lib1506.c12
-rw-r--r--tests/libtest/lib1507.c4
-rw-r--r--tests/libtest/lib1510.c6
-rw-r--r--tests/libtest/lib1512.c6
-rw-r--r--tests/libtest/lib1513.c4
-rw-r--r--tests/libtest/lib1515.c5
-rw-r--r--tests/libtest/lib1517.c4
-rw-r--r--tests/libtest/lib1531.c8
-rw-r--r--tests/libtest/lib1538.c7
-rw-r--r--tests/libtest/lib1550.c13
-rw-r--r--tests/libtest/lib1551.c2
-rw-r--r--tests/libtest/lib1900.c14
-rw-r--r--tests/libtest/lib500.c4
-rw-r--r--tests/libtest/lib502.c4
-rw-r--r--tests/libtest/lib503.c4
-rw-r--r--tests/libtest/lib504.c4
-rw-r--r--tests/libtest/lib505.c4
-rw-r--r--tests/libtest/lib506.c8
-rw-r--r--tests/libtest/lib507.c4
-rw-r--r--tests/libtest/lib508.c4
-rw-r--r--tests/libtest/lib510.c4
-rw-r--r--tests/libtest/lib513.c4
-rw-r--r--tests/libtest/lib514.c4
-rw-r--r--tests/libtest/lib515.c4
-rw-r--r--tests/libtest/lib516.c4
-rw-r--r--tests/libtest/lib517.c4
-rw-r--r--tests/libtest/lib525.c4
-rw-r--r--tests/libtest/lib526.c12
-rw-r--r--tests/libtest/lib530.c10
-rw-r--r--tests/libtest/lib533.c6
-rw-r--r--tests/libtest/lib536.c4
-rw-r--r--tests/libtest/lib540.c10
-rw-r--r--tests/libtest/lib543.c12
-rw-r--r--tests/libtest/lib544.c4
-rw-r--r--tests/libtest/lib547.c4
-rw-r--r--tests/libtest/lib552.c36
-rw-r--r--tests/libtest/lib553.c8
-rw-r--r--tests/libtest/lib554.c8
-rw-r--r--tests/libtest/lib555.c8
-rw-r--r--tests/libtest/lib557.c93
-rw-r--r--tests/libtest/lib560.c4
-rw-r--r--tests/libtest/lib564.c4
-rw-r--r--tests/libtest/lib567.c4
-rw-r--r--tests/libtest/lib568.c6
-rw-r--r--tests/libtest/lib569.c4
-rw-r--r--tests/libtest/lib570.c4
-rw-r--r--tests/libtest/lib571.c6
-rw-r--r--tests/libtest/lib572.c6
-rw-r--r--tests/libtest/lib573.c4
-rw-r--r--tests/libtest/lib575.c4
-rw-r--r--tests/libtest/lib578.c4
-rw-r--r--tests/libtest/lib579.c4
-rw-r--r--tests/libtest/lib586.c10
-rw-r--r--tests/libtest/lib589.c59
-rw-r--r--tests/libtest/lib591.c4
-rw-r--r--tests/libtest/lib597.c11
-rw-r--r--tests/libtest/lib599.c4
-rw-r--r--tests/libtest/lib643.c270
-rw-r--r--tests/libtest/lib650.c189
-rw-r--r--tests/libtest/libntlmconnect.c4
-rw-r--r--tests/libtest/mk-lib1521.pl12
-rw-r--r--tests/libtest/stub_gssapi.c397
-rw-r--r--tests/libtest/stub_gssapi.h183
-rw-r--r--tests/libtest/testtrace.c22
-rwxr-xr-xtests/runtests.pl69
-rw-r--r--tests/server/fake_ntlm.c13
-rw-r--r--tests/server/getpart.c42
-rw-r--r--tests/server/resolve.c6
-rw-r--r--tests/server/rtspd.c42
-rw-r--r--tests/server/sockfilt.c16
-rw-r--r--tests/server/sws.c67
-rw-r--r--tests/server/tftpd.c14
-rw-r--r--tests/server/util.c8
-rw-r--r--tests/unit/unit1300.c2
-rw-r--r--tests/unit/unit1301.c4
-rw-r--r--tests/unit/unit1302.c6
-rw-r--r--tests/unit/unit1303.c8
-rw-r--r--tests/unit/unit1305.c4
-rw-r--r--tests/unit/unit1308.c6
-rw-r--r--tests/unit/unit1309.c18
-rw-r--r--tests/unit/unit1323.c2
-rw-r--r--tests/unit/unit1395.c4
-rw-r--r--tests/unit/unit1396.c12
-rw-r--r--tests/unit/unit1398.c4
-rw-r--r--tests/unit/unit1399.c95
-rw-r--r--tests/unit/unit1600.c8
-rw-r--r--tests/unit/unit1605.c15
-rw-r--r--tests/unit/unit1606.c36
-rw-r--r--winbuild/MakefileBuild.vc2
467 files changed, 15365 insertions, 6403 deletions
diff --git a/.gitignore b/.gitignore
index 13d10a67f..8d6042fd0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,4 +53,7 @@ mkinstalldirs
tags
test-driver
scripts/_gnurl
-\#*\# \ No newline at end of file
+\#*\#
+curl_fuzzer
+curl_fuzzer_seed_corpus.zip
+libstandaloneengine.a
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 000000000..18cf8a6d8
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,26 @@
+Guenter Knauf <lists@gknw.net> <gk@gknw.de>
+Gisle Vanem <gisle.vanem@gmail.com> <gvanem@yahoo.no>
+Gisle Vanem <gisle.vanem@gmail.com> <gvanem@broadpark.no>
+Alessandro Ghedini <alessandro@ghedini.me> <alessandro@cloudflare.com>
+Alessandro Ghedini <alessandro@ghedini.me> <al3xbio@gmail.com>
+Björn Stenberg <bjorn@haxx.se>
+Björn Stenberg <bjorn@haxx.se> <bjst@bjorn>
+Viktor Szakáts <vszakats@users.noreply.github.com>
+Daniel Gustafsson <daniel@yesql.se> <dgustafsson@pivotal.io>
+Daniel Gustafsson <daniel@yesql.se> <daniel@hobbit.se>
+Linus Nielsen <linus@haxx.se>
+Yamada Yasuharu <yasuharu.yamada@access-company.com>
+Ulion <ulion2002@gmail.com>
+Tim Rühsen <tim.ruehsen@gmx.de>
+Steve Holme <steve_holme@hotmail.com> <steven.holme@cubic.com>
+Claes Jakobsson <claes@surfar.nu> <claes@versed.se>
+Sergei Nikulov <sergey.nikulov@gmail.com> <snikulov@users.noreply.github.com>
+Patrick Monnerat <patrick@monnerat.net> <Patrick.Monnerat@datasphere.ch>
+Patrick Monnerat <patrick@monnerat.net> <patrick.monnerat@dh.com>
+Patrick Monnerat <patrick@monnerat.net> <pm@datasphere.ch>
+Nick Zitzmann <nickzman@gmail.com><nick@chronosnet.com>
+Peter Wu <peter@lekensteyn.nl> <peter_at_lekensteyn.nl>
+David Woodhouse <David.Woodhouse@intel.com> <dwmw2@infradead.org>
+Marcel Raad <Marcel.Raad@teamviewer.com> <raad@teamviewer.com>
+Marcel Raad <Marcel.Raad@teamviewer.com> <MarcelRaad@users.noreply.github.com>
+Marcel Raad <Marcel.Raad@teamviewer.com> <marcelraad@users.sf.net>
diff --git a/.travis.yml b/.travis.yml
index 64aecd890..541628d99 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,13 +18,22 @@ addons:
- stunnel4
- libidn2-0-dev
- libssh2-1-dev
+ - krb5-user
matrix:
include:
- os: linux
compiler: gcc
dist: trusty
- env: T=normal
+ env: T=normal C=--with-gssapi
+ - os: linux
+ compiler: gcc
+ dist: trusty
+ env: T=normal C="--disable-http --disable-smtp --disable-imap"
+ - os: linux
+ compiler: gcc
+ dist: trusty
+ env: T=normal C=--enable-ares
- os: linux
compiler: clang
dist: trusty
@@ -34,13 +43,16 @@ matrix:
env: T=debug
- os: osx
compiler: gcc
- env: T=debug C=--with-ssl=/usr/local/opt/openssl
+ env: T=debug C=--enable-ares
+ - os: osx
+ compiler: gcc
+ env: T=debug C="--with-ssl=/usr/local/opt/openssl --with-libmetalink"
- os: osx
compiler: gcc
- env: T=debug C=--with-ssl=/usr/local/opt/libressl
+ env: T=debug C="--with-ssl=/usr/local/opt/libressl --with-libmetalink"
- os: osx
compiler: clang
- env: T=debug C="--without-ssl --with-darwinssl"
+ env: T=debug C="--without-ssl --with-darwinssl --with-libmetalink"
- os: osx
compiler: clang
env: T=normal
@@ -60,12 +72,16 @@ matrix:
compiler: gcc
dist: trusty
env: T=distcheck
+ - os: linux
+ compiler: clang
+ dist: trusty
+ env: T=fuzzer
install:
- pip install --user cpp-coveralls
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update > /dev/null; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew reinstall libtool > /dev/null; fi
- - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install openssl libidn rtmpdump libssh2 c-ares libmetalink libressl nghttp2; fi
+ - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install rtmpdump libssh2 c-ares libmetalink libressl nghttp2 libmetalink; fi
- if [ $TRAVIS_OS_NAME = linux ]; then
curl -L https://github.com/nghttp2/nghttp2/releases/download/v1.24.0/nghttp2-1.24.0.tar.gz |
tar xzf - &&
@@ -85,18 +101,19 @@ script:
tests="1 2 3 4 5 6 7 8 9 10 200 201 202 300 301 302 500 501 502 503 504 506 507 508 509 510 511 512 513 514 515 516 517 518 519 600 601 800 801 802 803 900 901 902 903 1000 1001 1002 1004 1302 1303 1304 1305 1306 1308 1400 1401 1402 1404 1450 1451 1452 1502 1507 1508 1600 1602 1603 1605"
make "TFLAGS=-n -e $tests" test-nonflaky
make "TFLAGS=-n -t $tests" test-nonflaky
- coveralls --gcov /usr/bin/gcov-4.8 --gcov-options '\-lp' -i src -i lib -i lib/vtls -i lib/vauth -e tests -e docs
+ coveralls --gcov /usr/bin/gcov-4.8 --gcov-options '\-lp' -i src -e lib -e tests -e docs -b $PWD/src
+ coveralls --gcov /usr/bin/gcov-4.8 --gcov-options '\-lp' -e src -i lib -e tests -e docs -b $PWD/lib
fi
- |
if [ "$T" = "debug" ]; then
./configure --enable-debug --enable-werror $C
- make
+ make && make examples
make TFLAGS=-n test-nonflaky
fi
- |
if [ "$T" = "normal" ]; then
./configure --enable-warnings --enable-werror $C
- make
+ make && make examples
make test-nonflaky
fi
- |
@@ -137,6 +154,21 @@ script:
cmake .. && \
make)
fi
+ - |
+ if [ "$T" = "fuzzer" ]; then
+ export CC=clang
+ export CXX=clang++
+ export CFLAGS="-fsanitize=address"
+
+ # Specifically use libstdc++ for travis as libc++ is not installed.
+ # This is ok because we're not compiling against libFuzzer.
+ export CXXFLAGS="-fsanitize=address -stdlib=libstdc++"
+ ./configure --disable-shared --enable-debug --enable-maintainer-mode
+ make
+ cd tests/fuzz
+ make clean
+ make check
+ fi
# whitelist branches to avoid testing feature branches twice (as branch and as pull request)
branches:
diff --git a/CMake/Macros.cmake b/CMake/Macros.cmake
index dab005f73..82aadca9d 100644
--- a/CMake/Macros.cmake
+++ b/CMake/Macros.cmake
@@ -93,3 +93,32 @@ macro(CURL_INTERNAL_TEST_RUN CURL_TEST)
endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
endif()
endmacro(CURL_INTERNAL_TEST_RUN)
+
+macro(CURL_NROFF_CHECK)
+ find_program(NROFF NAMES gnroff nroff)
+ if(NROFF)
+ # Need a way to write to stdin, this will do
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" "test")
+ # Tests for a valid nroff option to generate a manpage
+ foreach(_MANOPT "-man" "-mandoc")
+ execute_process(COMMAND "${NROFF}" ${_MANOPT}
+ OUTPUT_VARIABLE NROFF_MANOPT_OUTPUT
+ INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt"
+ ERROR_QUIET)
+ # Save the option if it was valid
+ if(NROFF_MANOPT_OUTPUT)
+ message("Found *nroff option: -- ${_MANOPT}")
+ set(NROFF_MANOPT ${_MANOPT})
+ set(NROFF_USEFUL ON)
+ break()
+ endif()
+ endforeach()
+ # No need for the temporary file
+ file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt")
+ if(NOT NROFF_USEFUL)
+ message(WARNING "Found no *nroff option to get plaintext from man pages")
+ endif()
+ else()
+ message(WARNING "Found no *nroff program")
+ endif()
+endmacro(CURL_NROFF_CHECK)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index be3fb4b3c..c816467b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,6 +43,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
include(Macros)
include(CMakeDependentOption)
+include(CheckCCompilerFlag)
project( CURL C )
@@ -73,6 +74,7 @@ include_directories(${PROJECT_BINARY_DIR}/include/gnurl)
include_directories( ${CURL_SOURCE_DIR}/include )
option(CURL_WERROR "Turn compiler warnings into errors" OFF)
+option(PICKY_COMPILER "Enable picky compiler options" ON)
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
@@ -88,6 +90,19 @@ CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DN
option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+ if (PICKY_COMPILER)
+ foreach (_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers)
+ # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
+ # test result in.
+ CHECK_C_COMPILER_FLAG(${_CCOPT} OPT${_CCOPT})
+ if(OPT${_CCOPT})
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
+ endif()
+ endforeach()
+ endif(PICKY_COMPILER)
+endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+
if (ENABLE_DEBUG)
# DEBUGBUILD will be defined only for Debug builds
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
@@ -172,8 +187,6 @@ option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF)
mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF)
mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS)
-option(DISABLED_THREADSAFE "Set to explicitly specify we don't want to use thread-safe functions" OFF)
-mark_as_advanced(DISABLED_THREADSAFE)
option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON)
mark_as_advanced(ENABLE_IPV6)
if(ENABLE_IPV6 AND NOT WIN32)
@@ -190,35 +203,19 @@ if(ENABLE_IPV6 AND NOT WIN32)
endif()
endif()
-option(ENABLE_MANUAL "to provide the built-in manual" ON)
-unset(USE_MANUAL CACHE) # TODO: cache NROFF/NROFF_MANOPT/USE_MANUAL vars?
+CURL_NROFF_CHECK()
+find_package(Perl)
+
+CMAKE_DEPENDENT_OPTION(ENABLE_MANUAL "to provide the built-in manual"
+ ON "NROFF_USEFUL;PERL_FOUND"
+ OFF)
+
+if(NOT PERL_FOUND)
+ message(STATUS "Perl not found, testing disabled.")
+ set(BUILD_TESTING OFF)
+endif()
if(ENABLE_MANUAL)
- find_program(NROFF NAMES gnroff nroff)
- if(NROFF)
- # Need a way to write to stdin, this will do
- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" "test")
- # Tests for a valid nroff option to generate a manpage
- foreach(_MANOPT "-man" "-mandoc")
- execute_process(COMMAND "${NROFF}" ${_MANOPT}
- OUTPUT_VARIABLE NROFF_MANOPT_OUTPUT
- INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt"
- ERROR_QUIET)
- # Save the option if it was valid
- if(NROFF_MANOPT_OUTPUT)
- message("Found *nroff option: -- ${_MANOPT}")
- set(NROFF_MANOPT ${_MANOPT})
- set(USE_MANUAL 1)
- break()
- endif()
- endforeach()
- # No need for the temporary file
- file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt")
- if(NOT USE_MANUAL)
- message(WARNING "Found no *nroff option to get plaintext from man pages")
- endif()
- else()
- message(WARNING "Found no *nroff program")
- endif()
+ set(USE_MANUAL ON)
endif()
# Required for building manual, docs, tests
find_package(Perl REQUIRED)
@@ -801,50 +798,6 @@ if(NOT HAVE_SIZEOF_SSIZE_T)
endif(NOT HAVE_SIZEOF_SSIZE_T)
# off_t is sized later, after the HAVE_FILE_OFFSET_BITS test
-# Different sizeofs, etc.
-
-# define CURL_SIZEOF_LONG 4
-# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_FORMAT_OFF_T "%lld"
-# define CURL_SIZEOF_CURL_OFF_T 8
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-
-set(CURL_SIZEOF_LONG ${SIZEOF_LONG})
-
-if(SIZEOF_LONG EQUAL 8)
- set(CURL_TYPEOF_CURL_OFF_T long)
- set(CURL_SIZEOF_CURL_OFF_T 8)
- set(CURL_FORMAT_CURL_OFF_T "ld")
- set(CURL_FORMAT_CURL_OFF_TU "lu")
- set(CURL_FORMAT_OFF_T "%ld")
- set(CURL_SUFFIX_CURL_OFF_T L)
- set(CURL_SUFFIX_CURL_OFF_TU UL)
-endif(SIZEOF_LONG EQUAL 8)
-
-if(SIZEOF_LONG_LONG EQUAL 8)
- set(CURL_TYPEOF_CURL_OFF_T "long long")
- set(CURL_SIZEOF_CURL_OFF_T 8)
- set(CURL_FORMAT_CURL_OFF_T "lld")
- set(CURL_FORMAT_CURL_OFF_TU "llu")
- set(CURL_FORMAT_OFF_T "%lld")
- set(CURL_SUFFIX_CURL_OFF_T LL)
- set(CURL_SUFFIX_CURL_OFF_TU ULL)
-endif(SIZEOF_LONG_LONG EQUAL 8)
-
-if(NOT CURL_TYPEOF_CURL_OFF_T)
- set(CURL_TYPEOF_CURL_OFF_T ${ssize_t})
- set(CURL_SIZEOF_CURL_OFF_T ${SIZEOF_SSIZE_T})
- # TODO: need adjustment here.
- set(CURL_FORMAT_CURL_OFF_T "ld")
- set(CURL_FORMAT_CURL_OFF_TU "lu")
- set(CURL_FORMAT_OFF_T "%ld")
- set(CURL_SUFFIX_CURL_OFF_T L)
- set(CURL_SUFFIX_CURL_OFF_TU LU)
-endif(NOT CURL_TYPEOF_CURL_OFF_T)
-
if(HAVE_SIZEOF_LONG_LONG)
set(HAVE_LONGLONG 1)
set(HAVE_LL 1)
@@ -1013,6 +966,13 @@ if(HAVE_FILE_OFFSET_BITS)
set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
endif(HAVE_FILE_OFFSET_BITS)
check_type_size("off_t" SIZEOF_OFF_T)
+
+# include this header to get the type
+set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCE_DIR}/include")
+set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h")
+check_type_size("curl_off_t" SIZEOF_CURL_OFF_T)
+set(CMAKE_EXTRA_INCLUDE_FILES "")
+
set(CMAKE_REQUIRED_FLAGS)
foreach(CURL_TEST
@@ -1173,8 +1133,12 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
endfunction()
-add_subdirectory(docs)
+if(USE_MANUAL)
+ add_subdirectory(docs)
+endif()
+
add_subdirectory(lib)
+
if(BUILD_CURL_EXE)
add_subdirectory(src)
endif()
diff --git a/Makefile.am b/Makefile.am
index d668ead22..2b5fcaea7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -210,6 +210,9 @@ test-am:
endif
+fuzzer:
+ @(cd tests/fuzz; $(MAKE) all)
+
examples:
@(cd docs/examples; $(MAKE) check)
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index a735262d0..971336faf 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,40 +1,110 @@
-Curl and libcurl 7.55.1
+Curl and libcurl 7.56.0
- Public curl releases: 168
- Command line options: 210
- curl_easy_setopt() options: 247
- Public functions in libcurl: 61
- Contributors: 1592
+ Public curl releases: 169
+ Command line options: 211
+ curl_easy_setopt() options: 249
+ Public functions in libcurl: 74
+ Contributors: 1618
+
+This release includes the following changes:
+
+ o curl: enable compression for SCP/SFTP with --compressed-ssh [11]
+ o libcurl: enable compression for SCP/SFTP with CURLOPT_SSH_COMPRESSION [11]
+ o vtls: added dynamic changing SSL backend with curl_global_sslset() [28]
+ o new MIME API, curl_mime_init() and friends [32]
+ o openssl: initial SSLKEYLOGFILE implementation [36]
This release includes the following bugfixes:
- o build: fix 'make install' with configure, install docs/libcurl/* too
- o make install: add 8 missing man pages to the installation
- o curl: do bounds check using a double comparison [1]
- o dist: Add dictserver.py/negtelnetserver.py to release [2]
- o digest_sspi: Don't reuse context if the user/passwd has changed [3]
- o gitignore: ignore top-level .vs folder [4]
- o build: check out *.sln files with Windows line endings [5]
- o travis: verify "make install" [6]
- o dist: fix the cmake build by shipping cmake_uninstall.cmake.in too [7]
- o metalink: fix error: ‘*’ in boolean context, suggest ‘&&’ instead
- o configure: use the threaded resolver backend by default if possible [8]
- o mkhelp.pl: allow executing this script directly [9]
- o maketgz: remove old *.dist files before making the tarball [10]
- o openssl: remove CONST_ASN1_BIT_STRING [11]
- o openssl: fix "error: this statement may fall through"
- o proxy: fix memory leak in case of invalid proxy server name [12]
- o curl/system.h: support more architectures (OpenRISC, ARC) [13]
- o docs: fix typos [14]
- o curl/system.h: add Oracle Solaris Studio [15]
- o CURLINFO_TOTAL_TIME: could wrongly return 4200 seconds [16]
- o docs: --connect-to clarified
- o cmake: allow user to override CMAKE_DEBUG_POSTFIX [17]
- o travis: test cmake build on tarball too
- o redirect: make it handle absolute redirects to IDN names [18]
- o curl/system.h: fix for gcc on PowerPC [19]
- o curl --interface: fixed for IPV6 unique local addresses [20]
- o cmake: threads detection improvements [21]
+ o FTP: zero terminate the entry path even on bad input [67]
+ o examples/ftpuploadresume.c: use portable code
+ o runtests: match keywords case insensitively
+ o travis: build the examples too [1]
+ o strtoofft: reduce integer overflow risks globally [2]
+ o zsh.pl: produce a working completion script again [3]
+ o cmake: remove dead code for CURL_DISABLE_RTMP [4]
+ o progress: Track total times following redirects [5]
+ o configure: fix --disable-threaded-resolver [6]
+ o cmake: remove dead code for DISABLED_THREADSAFE [7]
+ o configure: fix clang version detection
+ o darwinssi: fix error: variable length array used
+ o travis: add metalink to some osx builds [8]
+ o configure: check for __builtin_available() availability [9]
+ o http_proxy: fix build error for CURL_DOES_CONVERSIONS [10]
+ o examples/ftpuploadresume: checksrc compliance
+ o ftp: fix CWD when doing multicwd then nocwd on same connection [12]
+ o system.h: remove all CURL_SIZEOF_* defines [13]
+ o http: Don't wait on CONNECT when there is no proxy [14]
+ o system.h: check for __ppc__ as well [15]
+ o http2_recv: return error better on fatal h2 errors [16]
+ o scripts/contri*sh: use "git log --use-mailmap"
+ o tftp: fix memory leak on too long filename [17]
+ o system.h: fix build for hppa [18]
+ o cmake: enable picky compiler options with clang and gcc [19]
+ o makefile.m32: add support for libidn2 [20]
+ o curl: turn off MinGW CRT's globbing [21]
+ o request-target.d: mention added in 7.55.0
+ o curl: shorten and clean up CA cert verification error message [22]
+ o imap: support PREAUTH [23]
+ o CURLOPT_USERPWD.3: see also CURLOPT_PROXYUSERPWD
+ o examples/threaded-ssl: mention that this is for openssl before 1.1
+ o winbuild: fix embedded manifest option [24]
+ o tests: Make sure libtests & unittests call curl_global_cleanup()
+ o system.h: include sys/poll.h for AIX [25]
+ o darwinssl: handle long strings in TLS certs [26]
+ o strtooff: fix build for systems with long long but no strtoll [27]
+ o asyn-thread: Improved cleanup after OOM situations
+ o HELP-US.md: "How to get started helping out in the curl project" [29]
+ o curl.h: CURLSSLBACKEND_WOLFSSL used wrong value [30]
+ o unit1301: fix error message on first test
+ o ossfuzz: moving towards the ideal integration [31]
+ o http: fix a memory leakage in checkrtspprefix()
+ o examples/post-callback: stop returning one byte at a time
+ o schannel: return CURLE_SSL_CACERT on failed verification [33]
+ o MAIL-ETIQUETTE: added "1.9 Your emails are public"
+ o http-proxy: treat all 2xx as CONNECT success [34]
+ o openssl: use OpenSSL's default ciphers by default [35]
+ o runtests.pl: support attribute "nonewline" in part verify/upload
+ o configure: remove --enable-soname-bump and SONAME_BUMP [37]
+ o travis: add c-ares enabled builds linux + osx [38]
+ o vtls: fix WolfSSL 3.12 build problems [39]
+ o http-proxy: when not doing CONNECT, that phase is done immediately [40]
+ o configure: fix curl_off_t check's include order [41]
+ o configure: use -Wno-varargs on clang 3.9[.X] debug builds
+ o rtsp: do not call fwrite() with NULL pointer FILE * [42]
+ o mbedtls: enable CA path processing [43]
+ o travis: add build without HTTP/SMTP/IMAP
+ o checksrc: verify more code style rules [44]
+ o HTTP proxy: on connection re-use, still use the new remote port [45]
+ o tests: add initial gssapi test using stub implementation [46]
+ o rtsp: Segfault when using WRITEDATA [47]
+ o docs: clarify the CURLOPT_INTERLEAVE* options behavior
+ o non-ascii: use iconv() with 'char **' argument [48]
+ o server/getpart: provide dummy function to build conversion enabled
+ o conversions: fix several compiler warnings
+ o openssl: add missing includes [49]
+ o schannel: Support partial send for when data is too large [50]
+ o socks: fix incorrect port number in SOCKS4 error message [51]
+ o curl: fix integer overflow in timeout options [52]
+ o travis: on mac, don't install openssl or libidn [53]
+ o cookies: reject oversized cookies instead of truncating [54]
+ o cookies: use lock when using CURLINFO_COOKIELIST [55]
+ o curl: check fseek() return code and bail on error
+ o examples/post-callback: use long for CURLOPT_POSTFIELDSIZE
+ o openssl: only verify RSA private key if supported [56]
+ o tests: make the imap server not verify user+password [57]
+ o imap: quote atoms properly when escaping characters [58]
+ o tests: fix a compiler warning in test 643
+ o file_range: avoid integer overflow when figuring out byte range [59]
+ o curl.h: include <sys/select.h> on cygwin too [60]
+ o reuse_conn: don't copy flags that are known to be equal [61]
+ o http: fix adding custom empty headers to repeated requests [62]
+ o docs: clarify the use of environment variables for proxy [63]
+ o docs: link CURLOPT_CONNECTTIMEOUT and CURLOPT_CONNECTTIMEOUT_MS [64]
+ o connect: fix race condition with happy eyeballs timeout [65]
+ o cookie: fix memory leak if path was set twice in header [66]
+ o vtls: compare and clone ssl configs properly [68]
+ o proxy: read the "no_proxy" variable only if necessary [69]
This release includes the following known bugs:
@@ -43,36 +113,89 @@ This release includes the following known bugs:
This release would not have looked like this without help, code, reports and
advice from friends like these:
- Adam Sampson, Alessandro Ghedini, Alex Potapenko, Bernard Spil,
- Christian Weisgerber, Dagobert Michelsen, Dan Fandrich, Daniel Krügler,
- Daniel Stenberg, David Benjamin, David Lord, Even Rouault, Han Qiao,
- Isaac Boukris, James Slaughter, Marcel Raad, paulharris on github,
- Ray Satiro, Salah-Eddin Shaban, Sergei Nikulov, Simon Warta,
- Thomas Petazzoni,
- (22 contributors)
+ Anders Bakken, Andrei Karas, Benbuck Nason, Ben Greear, Benjamin Sergeant,
+ Bill Pyne, Brian Carpenter, Dan Fandrich, Daniel Stenberg, David Benjamin,
+ Dirk Feytons, Even Rouault, Frank Denis, Gergely Nagy, Gisle Vanem,
+ Ian Fette, imilli on github, Isaac Boukris, Jackarain on github,
+ Jakub Zakrzewski, Jan Alexander Steffens, Johannes Schindelin,
+ John David Anglin, joshhe on github, Kamil Dudka, Kevin Smith,
+ Lawrence Wagerfield, Maksim Stsepanenka, Marc Aldorasi, Marcel Raad,
+ Max Dymond, Michael Kaufmann, Michael Smith, Nick Zitzmann,
+ Nicolas Morey-Chaisemartin, Oli Kingshott, Patrick Monnerat, Pavel P,
+ Peter Lamare, Peter Wu, Ray Satiro, Rich Gray, Ryan Schmidt, Ryan Winograd,
+ SBKarr on github, Tatsuhiro Tsujikawa, Viktor Szakáts,
+ (47 contributors)
Thanks! (and sorry if I forgot to mention someone)
References to bug reports and discussions on issues:
- [1] = https://curl.haxx.se/bug/?i=1750
- [2] = https://curl.haxx.se/bug/?i=1744
- [3] = https://curl.haxx.se/bug/?i=1742
- [4] = https://curl.haxx.se/bug/?i=1746
- [5] = https://curl.haxx.se/bug/?i=1746
- [6] = https://curl.haxx.se/bug/?i=1753
- [7] = https://curl.haxx.se/bug/?i=1755
- [8] = https://curl.haxx.se/bug/?i=1647
- [9] = https://curl.haxx.se/bug/?i=1743
- [10] = https://curl.haxx.se/mail/lib-2017-08/0050.html
- [11] = https://curl.haxx.se/bug/?i=1759
- [12] = https://curl.haxx.se/bug/?i=1761
- [13] = https://curl.haxx.se/bug/?i=1766
- [14] = https://curl.haxx.se/bug/?i=1770
- [15] = https://curl.haxx.se/bug/?i=1752
- [16] = https://curl.haxx.se/bug/?i=1769
- [17] = https://curl.haxx.se/bug/?i=1763
- [18] = https://curl.haxx.se/bug/?i=1762
- [19] = https://curl.haxx.se/bug/?i=1774
- [20] = https://curl.haxx.se/bug/?i=1764
- [21] = https://curl.haxx.se/bug/?i=1719
+ [1] = https://curl.haxx.se/bug/?i=1777
+ [2] = https://curl.haxx.se/bug/?i=1758
+ [3] = https://curl.haxx.se/bug/?i=1779
+ [4] = https://curl.haxx.se/bug/?i=1785
+ [5] = https://curl.haxx.se/bug/?i=1602
+ [6] = https://curl.haxx.se/bug/?i=1784
+ [7] = https://curl.haxx.se/bug/?i=1786
+ [8] = https://curl.haxx.se/bug/?i=1790
+ [9] = https://curl.haxx.se/bug/?i=1788
+ [10] = https://curl.haxx.se/bug/?i=1793
+ [11] = https://curl.haxx.se/bug/?i=1735
+ [12] = https://curl.haxx.se/bug/?i=1782
+ [13] = https://curl.haxx.se/bug/?i=1767
+ [14] = https://curl.haxx.se/bug/?i=1803
+ [15] = https://curl.haxx.se/bug/?i=1797
+ [16] = https://curl.haxx.se/bug/?i=1021
+ [17] = https://curl.haxx.se/bug/?i=1808
+ [18] = https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=872502#10
+ [19] = https://curl.haxx.se/bug/?i=1799
+ [20] = https://curl.haxx.se/bug/?i=1815
+ [21] = https://curl.haxx.se/bug/?i=1751
+ [22] = https://curl.haxx.se/bug/?i=1810
+ [23] = https://curl.haxx.se/bug/?i=1818
+ [24] = https://curl.haxx.se/bug/?i=1832
+ [25] = https://curl.haxx.se/bug/?i=1828
+ [26] = https://curl.haxx.se/bug/?i=1823
+ [27] = https://curl.haxx.se/bug/?i=1829
+ [28] = https://curl.haxx.se/libcurl/c/curl_global_sslset.html
+ [29] = https://curl.haxx.se/bug/?i=1837
+ [30] = https://curl.haxx.se/mail/lib-2017-08/0120.html
+ [31] = https://curl.haxx.se/bug/?i=1842
+ [32] = https://curl.haxx.se/bug/?i=1839
+ [33] = https://curl.haxx.se/bug/?i=1858
+ [34] = https://curl.haxx.se/bug/?i=1859
+ [35] = https://curl.haxx.se/bug/?i=1846
+ [36] = https://curl.haxx.se/bug/?i=1866
+ [37] = https://curl.haxx.se/bug/?i=1861
+ [38] = https://curl.haxx.se/bug/?i=1868
+ [39] = https://curl.haxx.se/bug/?i=1865
+ [40] = https://curl.haxx.se/bug/?i=1853
+ [41] = https://curl.haxx.se/bug/?i=1870
+ [42] = https://curl.haxx.se/bug/?i=1874
+ [43] = https://curl.haxx.se/bug/?i=1877
+ [44] = https://curl.haxx.se/bug/?i=1878
+ [45] = https://curl.haxx.se/bug/?i=1887
+ [46] = https://curl.haxx.se/bug/?i=1687
+ [47] = https://curl.haxx.se/bug/?i=1880
+ [48] = https://curl.haxx.se/mail/lib-2017-09/0031.html
+ [49] = https://curl.haxx.se/bug/?i=1891
+ [50] = https://curl.haxx.se/bug/?i=1890
+ [51] = https://curl.haxx.se/bug/?i=1892
+ [52] = https://curl.haxx.se/bug/?i=1893
+ [53] = https://curl.haxx.se/bug/?i=1895
+ [54] = https://curl.haxx.se/bug/?i=1894
+ [55] = https://curl.haxx.se/bug/?i=1896
+ [56] = https://curl.haxx.se/bug/?i=1904
+ [57] = https://curl.haxx.se/bug/?i=1902
+ [58] = https://curl.haxx.se/bug/?i=1902
+ [59] = https://curl.haxx.se/bug/?i=1908
+ [60] = https://curl.haxx.se/bug/?i=1925
+ [61] = https://curl.haxx.se/bug/?i=1918
+ [62] = https://curl.haxx.se/bug/?i=1920
+ [63] = https://curl.haxx.se/bug/?i=1921
+ [64] = https://curl.haxx.se/bug/?i=1922
+ [65] = https://curl.haxx.se/bug/?i=1928
+ [66] = https://curl.haxx.se/bug/?i=1932
+ [67] = https://curl.haxx.se/docs/adv_20171004.html
+ [68] = https://curl.haxx.se/bug/?i=1917
+ [69] = https://curl.haxx.se/bug/?i=1919
diff --git a/acinclude.m4 b/acinclude.m4
index 539322870..69bb6c002 100644..100755
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -2084,20 +2084,6 @@ _EOF
])
-dnl CURL_CONFIGURE_LONG
-dnl -------------------------------------------------
-dnl Find out the size of long as reported by sizeof() and define
-dnl CURL_SIZEOF_LONG.
-
-AC_DEFUN([CURL_CONFIGURE_LONG], [
- if test -z "$ac_cv_sizeof_long" ||
- test "$ac_cv_sizeof_long" -eq "0"; then
- AC_MSG_ERROR([cannot find out size of long.])
- fi
- CURL_DEFINE_UNQUOTED([CURL_SIZEOF_LONG], [$ac_cv_sizeof_long])
-])
-
-
dnl CURL_CONFIGURE_CURL_SOCKLEN_T
dnl -------------------------------------------------
dnl The need for the curl_socklen_t definition arises mainly to properly
@@ -2718,291 +2704,6 @@ AC_HELP_STRING([--without-ca-fallback], [Don't use the built in CA store of the
fi
])
-
-dnl DO_CURL_OFF_T_CHECK (TYPE, SIZE)
-dnl -------------------------------------------------
-dnl Internal macro for CURL_CONFIGURE_CURL_OFF_T
-
-AC_DEFUN([DO_CURL_OFF_T_CHECK], [
- AC_REQUIRE([CURL_INCLUDES_INTTYPES])dnl
- if test "$curl_typeof_curl_off_t" = "unknown" && test ! -z "$1"; then
- tmp_includes=""
- tmp_source=""
- tmp_fmt=""
- case XC_SH_TR_SH([$1]) in
- int64_t)
- tmp_includes="$curl_includes_inttypes"
- tmp_source="char f@<:@@:>@ = PRId64;"
- tmp_fmt="PRId64"
- ;;
- int32_t)
- tmp_includes="$curl_includes_inttypes"
- tmp_source="char f@<:@@:>@ = PRId32;"
- tmp_fmt="PRId32"
- ;;
- int16_t)
- tmp_includes="$curl_includes_inttypes"
- tmp_source="char f@<:@@:>@ = PRId16;"
- tmp_fmt="PRId16"
- ;;
- esac
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $tmp_includes
- typedef $1 curl_off_t;
- typedef char dummy_arr[sizeof(curl_off_t) == $2 ? 1 : -1];
- ]],[[
- $tmp_source
- curl_off_t dummy;
- ]])
- ],[
- if test -z "$tmp_fmt"; then
- curl_typeof_curl_off_t="$1"
- curl_sizeof_curl_off_t="$2"
- else
- CURL_CHECK_DEF([$tmp_fmt], [$curl_includes_inttypes], [silent])
- AS_VAR_PUSHDEF([tmp_HaveFmtDef], [curl_cv_have_def_$tmp_fmt])dnl
- AS_VAR_PUSHDEF([tmp_FmtDef], [curl_cv_def_$tmp_fmt])dnl
- if test AS_VAR_GET(tmp_HaveFmtDef) = "yes"; then
- curl_format_curl_off_t=AS_VAR_GET(tmp_FmtDef)
- curl_typeof_curl_off_t="$1"
- curl_sizeof_curl_off_t="$2"
- fi
- AS_VAR_POPDEF([tmp_FmtDef])dnl
- AS_VAR_POPDEF([tmp_HaveFmtDef])dnl
- fi
- ])
- fi
-])
-
-
-dnl DO_CURL_OFF_T_SUFFIX_CHECK (TYPE)
-dnl -------------------------------------------------
-dnl Internal macro for CURL_CONFIGURE_CURL_OFF_T
-
-AC_DEFUN([DO_CURL_OFF_T_SUFFIX_CHECK], [
- AC_REQUIRE([CURL_INCLUDES_INTTYPES])dnl
- AC_MSG_CHECKING([constant suffix string for curl_off_t])
- #
- curl_suffix_curl_off_t="unknown"
- curl_suffix_curl_off_tu="unknown"
- #
- case XC_SH_TR_SH([$1]) in
- long_long | __longlong | __longlong_t)
- tst_suffixes="LL::"
- ;;
- long)
- tst_suffixes="L::"
- ;;
- int)
- tst_suffixes="::"
- ;;
- __int64 | int64_t)
- tst_suffixes="LL:i64::"
- ;;
- __int32 | int32_t)
- tst_suffixes="L:i32::"
- ;;
- __int16 | int16_t)
- tst_suffixes="L:i16::"
- ;;
- *)
- AC_MSG_ERROR([unexpected data type $1])
- ;;
- esac
- #
- old_IFS=$IFS; IFS=':'
- for tmp_ssuf in $tst_suffixes ; do
- IFS=$old_IFS
- if test "x$curl_suffix_curl_off_t" = "xunknown"; then
- case $tmp_ssuf in
- i64 | i32 | i16)
- tmp_usuf="u$tmp_ssuf"
- ;;
- LL | L)
- tmp_usuf="U$tmp_ssuf"
- ;;
- *)
- tmp_usuf=""
- ;;
- esac
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_inttypes
- typedef $1 new_t;
- ]],[[
- new_t s1;
- new_t s2;
- s1 = -10$tmp_ssuf ;
- s2 = 20$tmp_ssuf ;
- if(s1 > s2)
- return 1;
- ]])
- ],[
- curl_suffix_curl_off_t="$tmp_ssuf"
- curl_suffix_curl_off_tu="$tmp_usuf"
- ])
- fi
- done
- IFS=$old_IFS
- #
- if test "x$curl_suffix_curl_off_t" = "xunknown"; then
- AC_MSG_ERROR([cannot find constant suffix string for curl_off_t.])
- else
- AC_MSG_RESULT([$curl_suffix_curl_off_t])
- AC_MSG_CHECKING([constant suffix string for unsigned curl_off_t])
- AC_MSG_RESULT([$curl_suffix_curl_off_tu])
- fi
- #
-])
-
-
-dnl CURL_CONFIGURE_CURL_OFF_T
-dnl -------------------------------------------------
-dnl Find out suitable curl_off_t data type definition and associated
-dnl items
-
-AC_DEFUN([CURL_CONFIGURE_CURL_OFF_T], [
- AC_REQUIRE([CURL_INCLUDES_INTTYPES])dnl
- #
- AC_BEFORE([$0],[AC_SYS_LARGEFILE])dnl
- AC_BEFORE([$0],[CURL_CONFIGURE_REENTRANT])dnl
- AC_BEFORE([$0],[CURL_CHECK_AIX_ALL_SOURCE])dnl
- #
- if test -z "$SED"; then
- AC_MSG_ERROR([SED not set. Cannot continue without SED being set.])
- fi
- #
- AC_CHECK_SIZEOF(long)
- AC_CHECK_SIZEOF(void*)
- #
- if test -z "$ac_cv_sizeof_long" ||
- test "$ac_cv_sizeof_long" -eq "0"; then
- AC_MSG_ERROR([cannot find out size of long.])
- fi
- if test -z "$ac_cv_sizeof_voidp" ||
- test "$ac_cv_sizeof_voidp" -eq "0"; then
- AC_MSG_ERROR([cannot find out size of void*.])
- fi
- #
- x_LP64_long=""
- x_LP32_long=""
- #
- if test "$ac_cv_sizeof_long" -eq "8" &&
- test "$ac_cv_sizeof_voidp" -ge "8"; then
- x_LP64_long="long"
- elif test "$ac_cv_sizeof_long" -eq "4" &&
- test "$ac_cv_sizeof_voidp" -ge "4"; then
- x_LP32_long="long"
- fi
- #
- dnl DO_CURL_OFF_T_CHECK results are stored in next 3 vars
- #
- curl_typeof_curl_off_t="unknown"
- curl_sizeof_curl_off_t="unknown"
- curl_format_curl_off_t="unknown"
- curl_format_curl_off_tu="unknown"
- #
- if test "$curl_typeof_curl_off_t" = "unknown"; then
- AC_MSG_CHECKING([for 64-bit curl_off_t data type])
- for t8 in \
- "$x_LP64_long" \
- 'int64_t' \
- '__int64' \
- 'long long' \
- '__longlong' \
- '__longlong_t' ; do
- DO_CURL_OFF_T_CHECK([$t8], [8])
- done
- AC_MSG_RESULT([$curl_typeof_curl_off_t])
- fi
- if test "$curl_typeof_curl_off_t" = "unknown"; then
- AC_MSG_CHECKING([for 32-bit curl_off_t data type])
- for t4 in \
- "$x_LP32_long" \
- 'int32_t' \
- '__int32' \
- 'int' ; do
- DO_CURL_OFF_T_CHECK([$t4], [4])
- done
- AC_MSG_RESULT([$curl_typeof_curl_off_t])
- fi
- if test "$curl_typeof_curl_off_t" = "unknown"; then
- AC_MSG_ERROR([cannot find data type for curl_off_t.])
- fi
- #
- AC_MSG_CHECKING([size of curl_off_t])
- AC_MSG_RESULT([$curl_sizeof_curl_off_t])
- #
- AC_MSG_CHECKING([formatting string directive for curl_off_t])
- if test "$curl_format_curl_off_t" != "unknown"; then
- x_pull_headers="yes"
- curl_format_curl_off_t=`echo "$curl_format_curl_off_t" | "$SED" 's/[["]]//g'`
- curl_format_curl_off_tu=`echo "$curl_format_curl_off_t" | "$SED" 's/i$/u/'`
- curl_format_curl_off_tu=`echo "$curl_format_curl_off_tu" | "$SED" 's/d$/u/'`
- curl_format_curl_off_tu=`echo "$curl_format_curl_off_tu" | "$SED" 's/D$/U/'`
- else
- x_pull_headers="no"
- case XC_SH_TR_SH([$curl_typeof_curl_off_t]) in
- long_long | __longlong | __longlong_t)
- curl_format_curl_off_t="lld"
- curl_format_curl_off_tu="llu"
- ;;
- long)
- curl_format_curl_off_t="ld"
- curl_format_curl_off_tu="lu"
- ;;
- int)
- curl_format_curl_off_t="d"
- curl_format_curl_off_tu="u"
- ;;
- __int64)
- curl_format_curl_off_t="I64d"
- curl_format_curl_off_tu="I64u"
- ;;
- __int32)
- curl_format_curl_off_t="I32d"
- curl_format_curl_off_tu="I32u"
- ;;
- __int16)
- curl_format_curl_off_t="I16d"
- curl_format_curl_off_tu="I16u"
- ;;
- *)
- AC_MSG_ERROR([cannot find print format string for curl_off_t.])
- ;;
- esac
- fi
- AC_MSG_RESULT(["$curl_format_curl_off_t"])
- #
- AC_MSG_CHECKING([formatting string directive for unsigned curl_off_t])
- AC_MSG_RESULT(["$curl_format_curl_off_tu"])
- #
- DO_CURL_OFF_T_SUFFIX_CHECK([$curl_typeof_curl_off_t])
- #
- if test "$x_pull_headers" = "yes"; then
- if test "x$ac_cv_header_sys_types_h" = "xyes"; then
- CURL_DEFINE_UNQUOTED([CURL_PULL_SYS_TYPES_H])
- fi
- if test "x$ac_cv_header_stdint_h" = "xyes"; then
- CURL_DEFINE_UNQUOTED([CURL_PULL_STDINT_H])
- fi
- if test "x$ac_cv_header_inttypes_h" = "xyes"; then
- CURL_DEFINE_UNQUOTED([CURL_PULL_INTTYPES_H])
- fi
- fi
- #
- CURL_DEFINE_UNQUOTED([CURL_TYPEOF_CURL_OFF_T], [$curl_typeof_curl_off_t])
- CURL_DEFINE_UNQUOTED([CURL_FORMAT_CURL_OFF_T], ["$curl_format_curl_off_t"])
- CURL_DEFINE_UNQUOTED([CURL_FORMAT_CURL_OFF_TU], ["$curl_format_curl_off_tu"])
- CURL_DEFINE_UNQUOTED([CURL_FORMAT_OFF_T], ["%$curl_format_curl_off_t"])
- CURL_DEFINE_UNQUOTED([CURL_SIZEOF_CURL_OFF_T], [$curl_sizeof_curl_off_t])
- CURL_DEFINE_UNQUOTED([CURL_SUFFIX_CURL_OFF_T], [$curl_suffix_curl_off_t])
- CURL_DEFINE_UNQUOTED([CURL_SUFFIX_CURL_OFF_TU], [$curl_suffix_curl_off_tu])
- #
-])
-
-
dnl CURL_CHECK_WIN32_LARGEFILE
dnl -------------------------------------------------
dnl Check if curl's WIN32 large file will be used
@@ -3243,3 +2944,29 @@ AC_DEFUN([CURL_MAC_CFLAGS], [
fi
])
+
+
+dnl CURL_SUPPORTS_BUILTIN_AVAILABLE
+dnl
+dnl Check to see if the compiler supports __builtin_available. This built-in
+dnl compiler function first appeared in Apple LLVM 9.0.0. It's so new that, at
+dnl the time this macro was written, the function was not yet documented. Its
+dnl purpose is to return true if the code is running under a certain OS version
+dnl or later.
+
+AC_DEFUN([CURL_SUPPORTS_BUILTIN_AVAILABLE], [
+ AC_MSG_CHECKING([to see if the compiler supports __builtin_available()])
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+#include <stdlib.h>
+ ]],[[
+ if (__builtin_available(macOS 10.8, iOS 5.0, *)) {}
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ AC_DEFINE_UNQUOTED(HAVE_BUILTIN_AVAILABLE, 1,
+ [Define to 1 if you have the __builtin_available function.])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+])
diff --git a/configure.ac b/configure.ac
index c27c516e4..0bd697327 100644..100755
--- a/configure.ac
+++ b/configure.ac
@@ -124,6 +124,7 @@ AC_SUBST(libext)
dnl figure out the libcurl version
CURLVERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)".*/\1/p' ${srcdir}/include/gnurl/curlver.h`
XC_CHECK_PROG_CC
+AC_PROG_CXX
XC_AUTOMAKE
AC_MSG_CHECKING([curl version])
AC_MSG_RESULT($CURLVERSION)
@@ -165,7 +166,7 @@ curl_verbose_msg="enabled (--disable-verbose)"
curl_mtlnk_msg="no (--with-libmetalink)"
curl_psl_msg="no (--with-libpsl)"
- init_ssl_msg=${curl_ssl_msg}
+ ssl_backends=
dnl
dnl Save some initial values the user might have provided
@@ -183,9 +184,6 @@ AC_DEFINE_UNQUOTED(OS, "${host}", [cpu-machine-OS])
dnl Checks for programs.
-dnl Our curl_off_t internal and external configure settings
-CURL_CONFIGURE_CURL_OFF_T
-
dnl This defines _ALL_SOURCE for AIX
CURL_CHECK_AIX_ALL_SOURCE
@@ -354,6 +352,7 @@ esac
CURL_CHECK_WIN32_LARGEFILE
CURL_MAC_CFLAGS
+CURL_SUPPORTS_BUILTIN_AVAILABLE
dnl ************************************************************
dnl switch off particular protocols
@@ -1329,6 +1328,41 @@ else
CPPFLAGS="$save_CPPFLAGS"
fi
+build_libstubgss=no
+if test x"$want_gss" = "xyes"; then
+ build_libstubgss=yes
+fi
+
+AM_CONDITIONAL(BUILD_STUB_GSS, test "x$build_libstubgss" = "xyes")
+
+dnl -------------------------------------------------------------
+dnl parse --with-default-ssl-backend so it can be validated below
+dnl -------------------------------------------------------------
+
+DEFAULT_SSL_BACKEND=no
+VALID_DEFAULT_SSL_BACKEND=
+AC_ARG_WITH(default-ssl-backend,
+AC_HELP_STRING([--with-default-ssl-backend=NAME],[Use NAME as default SSL backend])
+AC_HELP_STRING([--without-default-ssl-backend],[Use implicit default SSL backend]),
+ [DEFAULT_SSL_BACKEND=$withval])
+case "$DEFAULT_SSL_BACKEND" in
+ no)
+ dnl --without-default-ssl-backend option used
+ ;;
+ default|yes)
+ dnl --with-default-ssl-backend option used without name
+ AC_MSG_ERROR([The name of the default SSL backend is required.])
+ ;;
+ *)
+ dnl --with-default-ssl-backend option used with name
+ AC_SUBST(DEFAULT_SSL_BACKEND)
+ dnl needs to be validated below
+ VALID_DEFAULT_SSL_BACKEND=no
+ ;;
+esac
+
+dnl **********************************************************************
+
dnl -------------------------------------------------
dnl check winssl option before other SSL libraries
dnl -------------------------------------------------
@@ -1340,13 +1374,15 @@ AC_HELP_STRING([--without-winssl], [disable Windows native SSL/TLS]),
OPT_WINSSL=$withval)
AC_MSG_CHECKING([whether to enable Windows native SSL/TLS (Windows native builds only)])
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_WINSSL" != xno; then
+ ssl_msg=
if test "x$OPT_WINSSL" != "xno" &&
test "x$curl_cv_native_windows" = "xyes"; then
AC_MSG_RESULT(yes)
AC_DEFINE(USE_SCHANNEL, 1, [to enable Windows native SSL/TLS support])
AC_SUBST(USE_SCHANNEL, [1])
- curl_ssl_msg="enabled (Windows-native)"
+ ssl_msg="Windows-native"
+ test schannel != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
WINSSL_ENABLED=1
# --with-winssl implies --enable-sspi
AC_DEFINE(USE_WINDOWS_SSPI, 1, [to enable SSPI support])
@@ -1356,6 +1392,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
else
AC_MSG_RESULT(no)
fi
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
else
AC_MSG_RESULT(no)
fi
@@ -1367,18 +1404,20 @@ AC_HELP_STRING([--without-darwinssl], [disable Apple OS native SSL/TLS]),
OPT_DARWINSSL=$withval)
AC_MSG_CHECKING([whether to enable Apple OS native SSL/TLS])
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_DARWINSSL" != xno; then
if test "x$OPT_DARWINSSL" != "xno" &&
test -d "/System/Library/Frameworks/Security.framework"; then
AC_MSG_RESULT(yes)
AC_DEFINE(USE_DARWINSSL, 1, [to enable Apple OS native SSL/TLS support])
AC_SUBST(USE_DARWINSSL, [1])
- curl_ssl_msg="enabled (Apple OS-native)"
+ ssl_msg="Apple OS-native"
+ test darwinssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
DARWINSSL_ENABLED=1
LDFLAGS="$LDFLAGS -framework CoreFoundation -framework Security"
else
AC_MSG_RESULT(no)
fi
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
else
AC_MSG_RESULT(no)
fi
@@ -1396,7 +1435,10 @@ AC_HELP_STRING([--with-ssl=PATH],[Where to look for OpenSSL, PATH points to the
AC_HELP_STRING([--without-ssl], [disable OpenSSL]),
OPT_SSL=$withval)
-if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
+if test -z "$ssl_backends" -o "x$OPT_SSL" != xno &&
+ test X"$OPT_SSL" != Xno; then
+ ssl_msg=
+
dnl backup the pre-ssl variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
@@ -1577,7 +1619,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
dnl Have the libraries--check for OpenSSL headers
AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \
openssl/pem.h openssl/ssl.h openssl/err.h,
- curl_ssl_msg="enabled (OpenSSL)"
+ ssl_msg="OpenSSL"
+ test openssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
OPENSSL_ENABLED=1
AC_DEFINE(USE_OPENSSL, 1, [if OpenSSL is in use]))
@@ -1591,7 +1634,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
test $ac_cv_header_crypto_h = yes &&
test $ac_cv_header_ssl_h = yes; then
dnl three matches
- curl_ssl_msg="enabled (OpenSSL)"
+ ssl_msg="OpenSSL"
OPENSSL_ENABLED=1
fi
fi
@@ -1642,7 +1685,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED(HAVE_BORINGSSL, 1,
[Define to 1 if using BoringSSL.])
- curl_ssl_msg="enabled (BoringSSL)"
+ ssl_msg="BoringSSL"
],[
AC_MSG_RESULT([no])
])
@@ -1658,7 +1701,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED(HAVE_LIBRESSL, 1,
[Define to 1 if using libressl.])
- curl_ssl_msg="enabled (libressl)"
+ ssl_msg="libressl"
],[
AC_MSG_RESULT([no])
])
@@ -1678,6 +1721,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
CURL_CHECK_OPENSSL_API
fi
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
fi
dnl **********************************************************************
@@ -1739,7 +1783,8 @@ AC_HELP_STRING([--with-gnutls=PATH],[where to look for GnuTLS, PATH points to th
AC_HELP_STRING([--without-gnutls], [disable GnuTLS detection]),
OPT_GNUTLS=$withval)
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_GNUTLS" != xno; then
+ ssl_msg=
if test X"$OPT_GNUTLS" != Xno; then
@@ -1813,7 +1858,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_GNUTLS, [1])
GNUTLS_ENABLED=1
USE_GNUTLS="yes"
- curl_ssl_msg="enabled (GnuTLS)"
+ ssl_msg="GnuTLS"
+ test gnutls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
],
[
LIBS="$CLEANLIBS"
@@ -1828,7 +1874,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
dnl linker doesn't search through, we need to add it to
dnl LD_LIBRARY_PATH to prevent further configure tests to fail
dnl due to this
- if test "x$cross_compiling" != "xyes"; then
+ if test "x$cross_compiling" != "xyes"; then
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$gtlslib"
export LD_LIBRARY_PATH
AC_MSG_NOTICE([Added $gtlslib to LD_LIBRARY_PATH])
@@ -1841,6 +1887,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
fi dnl GNUTLS not disabled
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
fi
dnl ---
@@ -1898,7 +1945,8 @@ AC_HELP_STRING([--with-polarssl=PATH],[where to look for PolarSSL, PATH points t
AC_HELP_STRING([--without-polarssl], [disable PolarSSL detection]),
OPT_POLARSSL=$withval)
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_POLARSSL" != xno; then
+ ssl_msg=
if test X"$OPT_POLARSSL" != Xno; then
@@ -1916,7 +1964,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_POLARSSL, [1])
POLARSSL_ENABLED=1
USE_POLARSSL="yes"
- curl_ssl_msg="enabled (PolarSSL)"
+ ssl_msg="PolarSSL"
+ test polarssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
])
fi
@@ -1942,7 +1991,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_POLARSSL, [1])
POLARSSL_ENABLED=1
USE_POLARSSL="yes"
- curl_ssl_msg="enabled (PolarSSL)"
+ ssl_msg="PolarSSL"
+ test polarssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
],
[
CPPFLAGS=$_cppflags
@@ -1970,6 +2020,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
fi dnl PolarSSL not disabled
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
fi
dnl ----------------------------------------------------
@@ -1985,7 +2036,8 @@ AC_HELP_STRING([--with-mbedtls=PATH],[where to look for mbedTLS, PATH points to
AC_HELP_STRING([--without-mbedtls], [disable mbedTLS detection]),
OPT_MBEDTLS=$withval)
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_MBEDTLS" != xno; then
+ ssl_msg=
if test X"$OPT_MBEDTLS" != Xno; then
@@ -2003,7 +2055,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_MBEDTLS, [1])
MBEDTLS_ENABLED=1
USE_MBEDTLS="yes"
- curl_ssl_msg="enabled (mbedTLS)"
+ ssl_msg="mbedTLS"
+ test mbedtls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
], [], -lmbedx509 -lmbedcrypto)
fi
@@ -2029,7 +2082,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_MBEDTLS, [1])
MBEDTLS_ENABLED=1
USE_MBEDTLS="yes"
- curl_ssl_msg="enabled (mbedTLS)"
+ ssl_msg="mbedTLS"
+ test mbedtls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
],
[
CPPFLAGS=$_cppflags
@@ -2057,6 +2111,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
fi dnl mbedTLS not disabled
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
fi
dnl ----------------------------------------------------
@@ -2073,7 +2128,8 @@ AC_HELP_STRING([--with-cyassl=PATH],[where to look for CyaSSL, PATH points to th
AC_HELP_STRING([--without-cyassl], [disable CyaSSL detection]),
OPT_CYASSL=$withval)
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_CYASSL" != xno; then
+ ssl_msg=
if test X"$OPT_CYASSL" != Xno; then
@@ -2095,7 +2151,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_CYASSL, [1])
CYASSL_ENABLED=1
USE_CYASSL="yes"
- curl_ssl_msg="enabled (CyaSSL)"
+ ssl_msg="CyaSSL"
+ test cyassl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
])
fi
@@ -2121,7 +2178,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_CYASSL, [1])
CYASSL_ENABLED=1
USE_CYASSL="yes"
- curl_ssl_msg="enabled (CyaSSL)"
+ ssl_msg="CyaSSL"
+ test cyassl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
],
[
CPPFLAGS=$_cppflags
@@ -2166,7 +2224,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_CYASSL, [1])
CYASSL_ENABLED=1
USE_CYASSL="yes"
- curl_ssl_msg="enabled (WolfSSL)"
+ ssl_msg="WolfSSL"
+ test cyassl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
],
[
AC_MSG_RESULT(no)
@@ -2220,6 +2279,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
fi dnl CyaSSL not disabled
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
fi
dnl ----------------------------------------------------
@@ -2234,7 +2294,8 @@ AC_HELP_STRING([--with-nss=PATH],[where to look for NSS, PATH points to the inst
AC_HELP_STRING([--without-nss], [disable NSS detection]),
OPT_NSS=$withval)
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_NSS" != xno; then
+ ssl_msg=
if test X"$OPT_NSS" != Xno; then
@@ -2309,7 +2370,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_NSS, [1])
USE_NSS="yes"
NSS_ENABLED=1
- curl_ssl_msg="enabled (NSS)"
+ ssl_msg="NSS"
+ test nss != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
],
[
LDFLAGS="$CLEANLDFLAGS"
@@ -2338,7 +2400,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
fi dnl NSS not disabled
-fi dnl curl_ssl_msg = init_ssl_msg
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
+fi
OPT_AXTLS=off
@@ -2347,7 +2410,8 @@ AC_HELP_STRING([--with-axtls=PATH],[Where to look for axTLS, PATH points to the
AC_HELP_STRING([--without-axtls], [disable axTLS]),
OPT_AXTLS=$withval)
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_AXTLS" != xno; then
+ ssl_msg=
if test X"$OPT_AXTLS" != Xno; then
dnl backup the pre-axtls variables
CLEANLDFLAGS="$LDFLAGS"
@@ -2381,7 +2445,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
AC_SUBST(USE_AXTLS, [1])
AXTLS_ENABLED=1
USE_AXTLS="yes"
- curl_ssl_msg="enabled (axTLS)"
+ ssl_msg="axTLS"
+ test axtls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
if test "x$cross_compiling" != "xyes"; then
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LIB_AXTLS"
@@ -2394,15 +2459,46 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
LIBS="$CLEANLIBS"
])
fi
+ test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
fi
-if test "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED$POLARSSL_ENABLED$MBEDTLS_ENABLED$AXTLS_ENABLED$CYASSL_ENABLED$WINSSL_ENABLED$DARWINSSL_ENABLED" = "x"; then
+case "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED$POLARSSL_ENABLED$MBEDTLS_ENABLED$AXTLS_ENABLED$CYASSL_ENABLED$WINSSL_ENABLED$DARWINSSL_ENABLED" in
+x)
AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.])
AC_MSG_WARN([Use --with-ssl, --with-gnutls, --with-polarssl, --with-cyassl, --with-nss, --with-axtls, --with-winssl, or --with-darwinssl to address this.])
-else
- # SSL is enabled, genericly
+ ;;
+x1)
+ # one SSL backend is enabled
+ AC_SUBST(SSL_ENABLED)
+ SSL_ENABLED="1"
+ AC_MSG_NOTICE([built with one SSL backend])
+ ;;
+*)
+ # more than one SSL backend is enabled
AC_SUBST(SSL_ENABLED)
SSL_ENABLED="1"
+ AC_SUBST(CURL_WITH_MULTI_SSL)
+ CURL_WITH_MULTI_SSL="1"
+ AC_DEFINE(CURL_WITH_MULTI_SSL, 1, [built with multiple SSL backends])
+ AC_MSG_NOTICE([built with multiple SSL backends])
+ ;;
+esac
+
+if test -n "$ssl_backends"; then
+ curl_ssl_msg="enabled ($ssl_backends)"
+fi
+
+if test no = "$VALID_DEFAULT_SSL_BACKEND"
+then
+ if test -n "$SSL_ENABLED"
+ then
+ AC_MSG_ERROR([Default SSL backend $DEFAULT_SSL_BACKEND not enabled!])
+ else
+ AC_MSG_ERROR([Default SSL backend requires SSL!])
+ fi
+elif test yes = "$VALID_DEFAULT_SSL_BACKEND"
+then
+ AC_DEFINE_UNQUOTED([CURL_DEFAULT_SSL_BACKEND], ["$DEFAULT_SSL_BACKEND"], [Default SSL backend])
fi
dnl **********************************************************************
@@ -2703,7 +2799,9 @@ AC_HELP_STRING([--disable-versioned-symbols], [Disable versioned symbols in shar
AC_MSG_WARN([You need an ld version supporting the --version-script option])
else
AC_MSG_RESULT(yes)
- if test "x$OPENSSL_ENABLED" = "x1"; then
+ if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
+ versioned_symbols_flavour="MULTISSL_"
+ elif test "x$OPENSSL_ENABLED" = "x1"; then
versioned_symbols_flavour="OPENSSL_"
elif test "x$GNUTLS_ENABLED" = "x1"; then
versioned_symbols_flavour="GNUTLS_"
@@ -3151,18 +3249,15 @@ AC_CHECK_SIZEOF(size_t)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(short)
-CURL_CONFIGURE_LONG
AC_CHECK_SIZEOF(time_t)
AC_CHECK_SIZEOF(off_t)
-soname_bump=no
-if test x"$curl_cv_native_windows" != "xyes" &&
- test $ac_cv_sizeof_off_t -ne $curl_sizeof_curl_off_t; then
- AC_MSG_WARN([This libcurl built is probably not ABI compatible with previous])
- AC_MSG_WARN([builds! You MUST read lib/README.curl_off_t to figure it out.])
- soname_bump=yes
-fi
-
+o=$CPPFLAGS
+CPPFLAGS="-I$srcdir/include $CPPFLAGS"
+AC_CHECK_SIZEOF(curl_off_t, unused , [
+#include <curl/system.h>
+])
+CPPFLAGS=$o
AC_CHECK_TYPE(long long,
[AC_DEFINE(HAVE_LONGLONG, 1,
@@ -3641,26 +3736,6 @@ dnl hiding of library internal symbols
dnl
CURL_CONFIGURE_SYMBOL_HIDING
-dnl ************************************************************
-dnl enforce SONAME bump
-dnl
-
-AC_MSG_CHECKING([whether to enforce SONAME bump])
-AC_ARG_ENABLE(soname-bump,
-AC_HELP_STRING([--enable-soname-bump],[Enable enforced SONAME bump])
-AC_HELP_STRING([--disable-soname-bump],[Disable enforced SONAME bump]),
-[ case "$enableval" in
- yes) AC_MSG_RESULT(yes)
- soname_bump=yes
- ;;
- *)
- AC_MSG_RESULT(no)
- ;;
- esac ],
- AC_MSG_RESULT($soname_bump)
-)
-AM_CONDITIONAL(SONAME_BUMP, test x$soname_bump = xyes)
-
dnl
dnl All the library dependencies put into $LIB apply to libcurl only.
dnl
@@ -3757,6 +3832,10 @@ if test "x$USE_NGHTTP2" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi
+if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES MultiSSL"
+fi
+
if test "x$OPENSSL_ENABLED" = "x1" -o "x$GNUTLS_ENABLED" = "x1" \
-o "x$NSS_ENABLED" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
@@ -3944,14 +4023,3 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
HTTP2 support: ${curl_h2_msg}
Protocols: ${SUPPORT_PROTOCOLS}
])
-
-if test "x$soname_bump" = "xyes"; then
-
-cat <<EOM
- SONAME bump: yes - WARNING: this library will be built with the SONAME
- number bumped due to (a detected) ABI breakage.
- See lib/README.curl_off_t for details on this.
-EOM
-
-fi
-
diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md
index 04ea66ed9..1f71c387b 100644
--- a/docs/CODE_OF_CONDUCT.md
+++ b/docs/CODE_OF_CONDUCT.md
@@ -28,5 +28,5 @@ reported by opening an issue or contacting one or more of the project
maintainers.
This Code of Conduct is adapted from the [Contributor
-Covenant](http://contributor-covenant.org), version 1.1.0, available at
-[http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/)
+Covenant](https://contributor-covenant.org/), version 1.1.0, available at
+[https://contributor-covenant.org/version/1/1/0/](https://contributor-covenant.org/version/1/1/0/)
diff --git a/docs/HELP-US.md b/docs/HELP-US.md
new file mode 100644
index 000000000..d9e0bddc5
--- /dev/null
+++ b/docs/HELP-US.md
@@ -0,0 +1,70 @@
+# How to get started helping out in the curl project
+
+We are always in need of more help. If you are new to the project and are
+looking for ways to contribute and help out, this document aims to give a few
+good starting points.
+
+A good idea is to start by subscribing to the [curl-library mailing
+list](https://cool.haxx.se/mailman/listinfo/curl-library) to keep track of the
+current discussion topics.
+
+## Scratch your own itch
+
+One of the best ways is to start working on any problems or issues you have
+found yourself or perhaps got annoyed at in the past. It can be a spelling
+error in an error text or a weirdly phrased section in a man page. Hunt it
+down and report the bug. Or make your first pull request with a fix for that.
+
+## PR-welcome
+
+In the issue tracker we occasionally mark bugs with
+[PR-welcome](https://github.com/curl/curl/labels/PR-welcome), as a sign that
+the bug is acknowledged to exist and that there's nobody known to work on this
+issue for the moment. Those are bugs that are fine to "grab" and provide a
+pull request for. The complexity level of these will of course vary, so pick
+one that piques your interest.
+
+## Work on known bugs
+
+Some bugs are known and haven't yet received attention and work enough to get
+fixed. We collect such known existing flaws in the
+[KNOWN_BUGS](https://curl.haxx.se/docs/knownbugs.html) page. Many of them link
+to the original bug report with some additional details, but some may also
+have aged a bit and may require some verification that the bug still exists in
+the same way and that what was said about it in the past is still valid.
+
+## Fix autobuild problems
+
+On the [autobuilds page](https://curl.haxx.se/dev/builds.html) we show a
+collection of test results from the automatic curl build and tests that are
+performed by volunteers. Fixing compiler warnings and errors shown there is
+something we value greatly. Also, if you own or run systems or architectures
+that aren't already tested in the autobuilds, we also appreciate more
+volunteers running builds automatically to help us keep curl portable.
+
+## TODO items
+
+Ideas for features and functions that we have considered worthwhile to
+implement and provide are kept in the
+[TODO](https://curl.haxx.se/docs/todo.html) file. Some of the ideas are
+rough. Some are well thought out. Some probably aren't really suitable
+anymore.
+
+Before you invest a lot of time on a TODO item, do bring it up for discussion
+on the mailing list. For discussion on applicability but also for ideas and
+brainstorming on specific ways to do the implementation etc.
+
+## You decide
+
+You can also come up with a completely new thing you think we should do. Or
+not do. Or fix. Or add to the project. You then either bring it to the mailing
+list first to see if people will shoot down the idea at once, or you bring a
+first draft of the idea as a pull request and take the discussion there around
+the specific implementation. Either way is fine.
+
+## CONTRIBUTE
+
+We offer [guidelines](https://curl.haxx.se/dev/contribute.html) that are
+suitable to be familiar with before you decide to contribute to curl. If
+you're used to open source development, you'll probably not find many
+surprises in there.
diff --git a/docs/HISTORY.md b/docs/HISTORY.md
index 551e7d258..a84ad8f1b 100644
--- a/docs/HISTORY.md
+++ b/docs/HISTORY.md
@@ -275,3 +275,21 @@ August:
March: first real release supporting HTTP/2
September: Web site had 245,000 unique visitors and served 236GB data
+
+2016
+----
+
+ December: curl 7.52.0 introduced support for HTTPS-proxy!
+
+2017
+----
+
+ September: Added Multi-SSL support
+
+ The web site serves 3100 GB/month
+
+ Public curl releases: 169
+ Command line options: 211
+ curl_easy_setopt() options: 249
+ Public functions in libcurl: 74
+ Contributors: 1609
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 6c2c8ce64..67a9378ff 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -222,6 +222,9 @@ subdirectory run following command from mentioned subdirectory:
In order to build sample program simplessl.c an SSL enabled libcurl is
required, as well as the OpenSSL libeay32.lib and ssleay32.lib libraries.
+In order to build sample program `sslbackend.c`, an SSL enabled libcurl
+is required.
+
## Disabling Specific Protocols in Windows builds
The configure utility, unfortunately, is not available for the Windows
diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS
index 17731945a..961a62814 100644
--- a/docs/KNOWN_BUGS
+++ b/docs/KNOWN_BUGS
@@ -18,7 +18,6 @@ problems may have been fixed or changed somewhat since this was written!
1.4 multipart formposts file name encoding
1.5 Expect-100 meets 417
1.6 Unnecessary close when 401 received waiting for 100
- 1.8 DNS timing is wrong for HTTP redirects
1.9 HTTP/2 frames while in the connection pool kill reuse
1.10 Strips trailing dot from host name
1.11 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
@@ -83,6 +82,7 @@ problems may have been fixed or changed somewhat since this was written!
11.1 Curl leaks .onion hostnames in DNS
11.2 error buffer not set if connection to multiple addresses fails
11.3 c-ares deviates from stock resolver on http://1346569778
+ 11.4 HTTP test server 'connection-monitor' problems
12. LDAP and OpenLDAP
12.1 OpenLDAP hangs after returning results
@@ -140,12 +140,6 @@ problems may have been fixed or changed somewhat since this was written!
waiting for the the 100-continue response.
https://curl.haxx.se/mail/lib-2008-08/0462.html
-1.8 DNS timing is wrong for HTTP redirects
-
- When extracting timing information after HTTP redirects, only the last
- transfer's results are returned and not the totals:
- https://github.com/curl/curl/issues/522
-
1.9 HTTP/2 frames while in the connection pool kill reuse
If the server sends HTTP/2 frames (like for example an HTTP/2 PING frame) to
@@ -322,7 +316,6 @@ problems may have been fixed or changed somewhat since this was written!
The cmake build setup lacks several features that the autoconf build
offers. This includes:
- - symbol hiding when the shared library is built
- use of correct soname for the shared library build
- support for several TLS backends are missing
- the unit tests cause link failures in regular non-static builds
@@ -559,6 +552,13 @@ problems may have been fixed or changed somewhat since this was written!
See https://github.com/curl/curl/issues/893
+11.4 HTTP test server 'connection-monitor' problems
+
+ The 'connection-monitor' feature of the sws HTTP test server doesn't work
+ properly if some tests are run in unexpected order. Like 1509 and then 1525.
+
+ See https://github.com/curl/curl/issues/868
+
12. LDAP and OpenLDAP
diff --git a/docs/MAIL-ETIQUETTE b/docs/MAIL-ETIQUETTE
index 897fc9f52..54f1090b7 100644
--- a/docs/MAIL-ETIQUETTE
+++ b/docs/MAIL-ETIQUETTE
@@ -15,6 +15,7 @@ MAIL ETIQUETTE
1.6 Handling trolls and spam
1.7 How to unsubscribe
1.8 I posted, now what?
+ 1.9 Your emails are public
2. Sending mail
2.1 Reply or New Mail
@@ -118,9 +119,9 @@ MAIL ETIQUETTE
to the page for the particular mailing list you're subscribed to and you enter
your email address and password and press the unsubscribe button.
- Also, the instructions to unsubscribe are included in the headers of every
- mail that is sent out to all curl related mailing lists and there's a footer
- in each mail that links to the "admin" page on which you can unsubscribe and
+ Also, the instructions to unsubscribe are included in the headers of every
+ mail that is sent out to all curl related mailing lists and there's a footer
+ in each mail that links to the "admin" page on which you can unsubscribe and
change other options.
You NEVER EVER email the mailing list requesting someone else to take you off
@@ -151,7 +152,7 @@ MAIL ETIQUETTE
or repeat the same steps in their locations.
Failing to include details will only delay responses and make people respond
- and ask for more details and you will have to send a follow-up email that
+ and ask for more details and you will have to send a follow-up email that
includes them.
Expect the responses to primarily help YOU debug the issue, or ask YOU
@@ -162,6 +163,27 @@ MAIL ETIQUETTE
chances are that people will ignore you at will and your chances to get
responses in the future will greatly diminish.
+ 1.9 Your emails are public
+
+ Your email, its contents and all its headers and the details in those
+ headers will be received by every subscriber of the mailing list that you
+ send your email to.
+
+ Your email as sent to a curl mailing list will end up in mail archives, on
+ the curl web site and elsewhere, for others to see and read. Today and in
+ the future. In addition to the archives, the mail is sent out to thousands
+ of individuals. There is no way to undo a sent email.
+
+ When sending emails to a curl mailing list, do not include sensitive
+ information such as user names and passwords; use fake ones, temporary ones
+ or just remove them completely from the mail. Note that this includes base64
+ encoded HTTP Basic auth headers.
+
+ This public nature of the curl mailing lists makes automaticly inserted mail
+ footers about mails being "private" or "only meant for the receipient" or
+ similar even more silly than usual. Because they are absolutely not private
+ when sent to a public mailing list.
+
2. Sending mail
@@ -261,4 +283,3 @@ MAIL ETIQUETTE
Getting the solution posted also helps other users that experience the same
problem(s). They get to see (possibly in the web archives) that the
suggested fixes actually has helped at least one person.
-
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 0cc9b5acf..70da87ad5 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -46,7 +46,7 @@ EXTRA_DIST = MANUAL BUGS CONTRIBUTE.md FAQ FEATURES INTERNALS.md SSLCERTS.md
README.netware MAIL-ETIQUETTE HTTP-COOKIES.md SECURITY.md RELEASE-PROCEDURE \
SSL-PROBLEMS.md HTTP2.md ROADMAP.md CODE_OF_CONDUCT.md CODE_STYLE.md \
CHECKSRC.md CMakeLists.txt README.md CIPHERS.md INSTALL.cmake README.cmake \
- $(noinst_man_MANS)
+ $(noinst_man_MANS) HELP-US.md
MAN2HTML= roffit $< >$@
diff --git a/docs/THANKS b/docs/THANKS
index 5e4a98eff..5aa2a122c 100644
--- a/docs/THANKS
+++ b/docs/THANKS
@@ -92,6 +92,7 @@ Andreas Streichardt
Andreas Wurf
Andrei Benea
Andrei Cipu
+Andrei Karas
Andrei Kurushin
Andrei Sedoi
Andrej E Baranov
@@ -158,6 +159,7 @@ Benjamin Gerard
Benjamin Gilbert
Benjamin Johnson
Benjamin Kircher
+Benjamin Sergeant
Benoit Neil
Benoit Sigoure
Bernard Leak
@@ -172,6 +174,7 @@ Bill Egert
Bill Hoffman
Bill Middlecamp
Bill Nagel
+Bill Pyne
Bjoern Sikora
Bjorn Augustsson
Bjorn Reese
@@ -384,6 +387,7 @@ Dimitrios Siganos
Dimitris Sarris
Dinar
Dirk Eddelbuettel
+Dirk Feytons
Dirk Manske
Dmitri Shubin
Dmitriy Sergeyev
@@ -487,6 +491,7 @@ Florian Weimer
Forrest Cahoon
Francisco Moraes
Francois Petitjean
+Frank Denis
Frank Gevaerts
Frank Hempel
Frank Keeney
@@ -595,6 +600,7 @@ Howard Chu
Hubert Kario
Hzhijun
Ian D Allen
+Ian Fette
Ian Ford
Ian Gulliver
Ian Lynagh
@@ -618,6 +624,7 @@ Ishan SinghLevett
Ivan Avdeev
Ivo Bellin Salarin
Jack Zhang
+Jackarain on github
Jacky Lam
Jacob Meuser
Jacob Moshenko
@@ -640,6 +647,7 @@ James Slaughter
Jamie Lokier
Jamie Newton
Jamie Wilkinson
+Jan Alexander Steffens
Jan Ehrhardt
Jan Koen Annot
Jan Kunder
@@ -721,6 +729,7 @@ Johannes Schindelin
John Bradshaw
John Coffey
John Crow
+John David Anglin
John Dennis
John Dunn
John E. Malmberg
@@ -819,6 +828,7 @@ Kevin Ji
Kevin Lussier
Kevin Reed
Kevin Roth
+Kevin Smith
Kim Minjoong
Kim Rinnewitz
Kim Vandry
@@ -852,6 +862,7 @@ Lars Torben Wilson
Lau Hang Kin
Laurent Rabret
Lauri Kasanen
+Lawrence Wagerfield
Legoff Vincent
Lehel Bernadt
Leif W
@@ -903,6 +914,7 @@ Mamoru Tasaka
Mandy Wu
Manfred Schwarb
Manuel Massing
+Marc Aldorasi
Marc Boucher
Marc Deslauriers
Marc Doughty
@@ -1069,6 +1081,7 @@ Nico Baggus
Nicolas Berloquin
Nicolas Croiset
Nicolas François
+Nicolas Morey-Chaisemartin
Niels van Tongeren
Nikita Schmidt
Nikitinskit Dmitriy
@@ -1090,6 +1103,7 @@ Ola Mork
Olaf Flebbe
Olaf Stüben
Oleg Pudeyev
+Oli Kingshott
Oliver Gondža
Oliver Graute
Oliver Kuckertz
@@ -1137,6 +1151,7 @@ Paul Querna
Paul Saab
Pavel Cenek
Pavel Orehov
+Pavel P
Pavel Raiskup
Pavel Rochnyak
Pawel A. Gajda
@@ -1151,6 +1166,7 @@ Peter Gal
Peter Heuchert
Peter Hjalmarsson
Peter Korsgaard
+Peter Lamare
Peter Lamberg
Peter Laser
Peter O'Gorman
@@ -1303,6 +1319,7 @@ Ryan Winograd
Ryuichi KAWAMATA
Rémy Léone
S. Moonesamy
+SBKarr on github
Salah-Eddin Shaban
Salvador Dávila
Salvatore Sorrentino
@@ -1570,12 +1587,13 @@ afrind on github
asavah on github
baumanj on github
bsammon on github
-canavan at github
-destman at github
+canavan on github
+destman on github
dkjjr89 on github
eXeC64 on github
-jonrumsey at github
+imilli on github
jonrumsey on github
+joshhe on github
jveazey on github
ka7 on github
kreshano on github
@@ -1589,17 +1607,17 @@ neex on github
neheb on github
nk
nopjmp on github
-olesteban at github
+olesteban on github
ovidiu-benea on github
paulharris on github
silveja1 on github
-stootill at github
+stootill on github
swalkaus at yahoo.com
tarek112 on github
tommink[at]post.pl
vanillajonathan on github
wmsch on github
-wyattoday at github
+wyattoday on github
zelinchen on github
İsmail Dönmez
Štefan Kremeň
diff --git a/docs/TODO b/docs/TODO
index dde2994b6..18896b070 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -27,7 +27,6 @@
1.9 Cache negative name resolves
1.10 auto-detect proxy
1.11 minimize dependencies with dynamically loaded modules
- 1.12 have form functions use CURL handle argument
1.14 Typesafe curl_easy_setopt()
1.15 Monitor connections in the connection pool
1.16 Try to URL encode given URL
@@ -67,9 +66,7 @@
5.6 Refuse "downgrade" redirects
5.7 Brotli compression
5.8 QUIC
- 5.9 Improve formpost API
5.10 Leave secure cookies alone
- 5.11 Chunked transfer multipart formpost
6. TELNET
6.1 ditch stdin
@@ -139,7 +136,6 @@
18.2 glob posts
18.3 prevent file overwriting
18.4 simultaneous parallel transfers
- 18.5 provide formpost headers
18.6 warning when setting an option
18.8 offer color-coded HTTP header output
18.9 Choose the name of file in braces for complex URLs
@@ -210,7 +206,7 @@
1.5 get rid of PATH_MAX
Having code use and rely on PATH_MAX is not nice:
- http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
+ https://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
Currently the SSH based code uses it a bit, but to remove PATH_MAX from there
we need libssh2 to properly tell us when we pass in a too small buffer and
@@ -276,18 +272,6 @@
app/invoke/used protocols would be necessary to load. See
https://github.com/curl/curl/issues/349
-1.12 have form functions use CURL handle argument
-
- curl_formadd() and curl_formget() both currently have no CURL handle
- argument, but both can use a callback that is set in the easy handle, and
- thus curl_formget() with callback cannot function without first having
- curl_easy_perform() (or similar) called - which is hard to grasp and a design
- mistake.
-
- The curl_formadd() design can probably also be reconsidered to make it easier
- to use and less error-prone. Probably easiest by splitting it into several
- function calls.
-
1.14 Typesafe curl_easy_setopt()
One of the most common problems in libcurl using applications is the lack of
@@ -546,13 +530,6 @@ This is not detailed in any FTP specification.
implemented. This, to allow other projects to benefit from the work and to
thus broaden the interest and chance of others to participate.
-5.9 Improve formpost API
-
- Revamp the formpost API and making something that is easier to use and
- understand:
-
- https://github.com/curl/curl/wiki/formpost-API-redesigned
-
5.10 Leave secure cookies alone
Non-secure origins (HTTP sites) should not be allowed to set or modify
@@ -560,16 +537,6 @@ This is not detailed in any FTP specification.
https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone-01
-5.11 Chunked transfer multipart formpost
-
- For a case where the file is being made during the upload is progressing
- (like passed on stdin to the curl tool), we cannot know the size before-hand
- and we rather not read the entire thing into memory before it can start the
- upload.
-
- https://github.com/curl/curl/issues/1139
-
-
6. TELNET
6.1 ditch stdin
@@ -911,20 +878,6 @@ that doesn't exist on the server, just like --ftp-create-dirs.
Using the multi interface would also allow properly using parallel transfers
with HTTP/2 and supporting HTTP/2 server push from the command line.
-18.5 provide formpost headers
-
- Extending the capabilities of the multipart formposting. How about leaving
- the ';type=foo' syntax as it is and adding an extra tag (headers) which
- works like this: curl -F "coolfiles=@fil1.txt;headers=@fil1.hdr" where
- fil1.hdr contains extra headers like
-
- Content-Type: text/plain; charset=KOI8-R"
- Content-Transfer-Encoding: base64
- X-User-Comment: Please don't use browser specific HTML code
-
- which should overwrite the program reasonable defaults (plain/text,
- 8bit...)
-
18.6 warning when setting an option
Display a warning when libcurl returns an error when setting an option.
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index 7eea5c6c5..e8f46410b 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -1,7 +1,8 @@
# Shared between Makefile.am and CMakeLists.txt
DPAGES = abstract-unix-socket.d anyauth.d append.d basic.d cacert.d capath.d cert.d \
- cert-status.d cert-type.d ciphers.d compressed.d config.d \
+ cert-status.d cert-type.d ciphers.d compressed.d compressed-ssh.d \
+ config.d \
connect-timeout.d connect-to.d continue-at.d cookie.d cookie-jar.d \
create-dirs.d crlf.d crlfile.d data-ascii.d data-binary.d data.d \
data-raw.d data-urlencode.d delegation.d digest.d disable.d \
diff --git a/docs/cmdline-opts/cacert.d b/docs/cmdline-opts/cacert.d
index 04e113980..b2ecf9088 100644
--- a/docs/cmdline-opts/cacert.d
+++ b/docs/cmdline-opts/cacert.d
@@ -1,5 +1,5 @@
Long: cacert
-Arg: <CA certificate>
+Arg: <file>
Help: CA certificate to verify peer against
Protocols: TLS
---
diff --git a/docs/cmdline-opts/compressed-ssh.d b/docs/cmdline-opts/compressed-ssh.d
new file mode 100644
index 000000000..583452ae4
--- /dev/null
+++ b/docs/cmdline-opts/compressed-ssh.d
@@ -0,0 +1,7 @@
+Long: compressed-ssh
+Help: Enable SSH compression
+Protocols: SCP SFTP
+Added: 7.56.0
+---
+Enables built-in SSH compression.
+This is a request, not an order; the server may or may not do it.
diff --git a/docs/cmdline-opts/form-string.d b/docs/cmdline-opts/form-string.d
index 80790553c..49d0d44ef 100644
--- a/docs/cmdline-opts/form-string.d
+++ b/docs/cmdline-opts/form-string.d
@@ -1,6 +1,6 @@
Long: form-string
-Help: Specify HTTP multipart POST data
-Protocols: HTTP
+Help: Specify multipart MIME data
+Protocols: HTTP SMTP IMAP
Arg: <name=string>
See-also: form
---
diff --git a/docs/cmdline-opts/form.d b/docs/cmdline-opts/form.d
index 87a7d0766..232d30c07 100644
--- a/docs/cmdline-opts/form.d
+++ b/docs/cmdline-opts/form.d
@@ -1,21 +1,26 @@
Long: form
Short: F
Arg: <name=content>
-Help: Specify HTTP multipart POST data
-Protocols: HTTP
+Help: Specify multipart MIME data
+Protocols: HTTP SMTP IMAP
Mutexed: data head upload
---
-This lets curl emulate a filled-in form in which a user has pressed the submit
-button. This causes curl to POST data using the Content-Type
-multipart/form-data according to RFC 2388. This enables uploading of binary
+For HTTP protocol family, this lets curl emulate a filled-in form in which a
+user has pressed the submit button. This causes curl to POST data using the
+Content-Type multipart/form-data according to RFC 2388.
+
+For SMTP and IMAP protocols, this is the mean to compose a multipart mail
+message to transmit.
+
+This enables uploading of binary
files etc. To force the 'content' part to be a file, prefix the file name with
an @ sign. To just get the content part from a file, prefix the file name with
the symbol <. The difference between @ and < is then that @ makes a file get
attached in the post as a file upload, while the < makes a text field and just
get the contents for that text field from a file.
-Example: to send an image to a server, where \&'profile' is the name of the
-form-field to which portrait.jpg will be the input:
+Example: to send an image to an HTTP server, where \&'profile' is the name of
+the form-field to which portrait.jpg will be the input:
curl -F profile=@portrait.jpg https://example.com/upload.cgi
@@ -49,6 +54,67 @@ or
Note that if a filename/path is quoted by double-quotes, any double-quote
or backslash within the filename must be escaped by backslash.
+You can add custom headers to the field by setting headers=, like
+
+ curl -F "submit=OK;headers=\\"X-submit-type: OK\\"" example.com
+
+or
+
+ curl -F "submit=OK;headers=@headerfile" example.com
+
+The headers= keyword may appear more that once and above notes about quoting
+apply. When headers are read from a file, Empty lines and lines starting
+with '#' are comments and ignored; each header can be folded by splitting
+between two words and starting the continuation line with a space; embedded
+carriage-returns and trailing spaces are stripped.
+Here is an example of a header file contents:
+
+ # This file contain two headers.
+.br
+ X-header-1: this is a header
+
+ # The following header is folded.
+.br
+ X-header-2: this is
+.br
+ another header
+
+
+To support sending multipart mail messages, the syntax is extended as follows:
+.br
+- name can be omitted: the equal sign is the first character of the argument,
+.br
+- if data starts with '(', this signals to start a new multipart: it can be
+followed by a content type specification.
+.br
+- a multipart can be terminated with a '=)' argument.
+
+Example: the following command sends an SMTP mime e-mail consisting in an
+inline part in two alternative formats: plain text and HTML. It attaches a
+text file:
+
+ curl -F '=(;type=multipart/alternative' \\
+.br
+ -F '=plain text message' \\
+.br
+ -F '= <body>HTML message</body>;type=text/html' \\
+.br
+ -F '=)' -F '=@textfile.txt' ... smtp://example.com
+
+Data can be encoded for transfer using encoder=. Available encodings are
+\fIbinary\fP and \fI8bit\fP that do nothing else than adding the corresponding
+Content-Transfer-Encoding header, \fI7bit\fP that only rejects 8-bit characters
+with a transfer error, \fIquoted-printable\fP and \fIbase64\fP that encodes
+data according to the corresponding schemes, limiting lines length to
+76 characters.
+
+Example: send multipart mail with a quoted-printable text message and a
+base64 attached file:
+
+ curl -F '=text message;encoder=quoted-printable' \\
+.br
+ -F '=@localfile;encoder=base64' ... smtp://example.com
+
See further examples and details in the MANUAL.
This option can be used multiple times.
diff --git a/docs/cmdline-opts/gen.pl b/docs/cmdline-opts/gen.pl
index 6f67be6c1..642170988 100755
--- a/docs/cmdline-opts/gen.pl
+++ b/docs/cmdline-opts/gen.pl
@@ -179,7 +179,7 @@ sub single {
}
if($standalone) {
- print ".TH gnurl 1 \"30 Nov 2016\" \"gnurl 7.52.0\" \"curl manual\"\n";
+ print ".TH gnurl 1 \"30 Nov 2016\" \"gnurl 7.52.0\" \"gnurl manual\"\n";
print ".SH OPTION\n";
print "gnurl $opt\n";
}
diff --git a/docs/cmdline-opts/request-target.d b/docs/cmdline-opts/request-target.d
index 630f8b3b4..b46b4af02 100644
--- a/docs/cmdline-opts/request-target.d
+++ b/docs/cmdline-opts/request-target.d
@@ -1,6 +1,7 @@
Long: request-target
Help: Specify the target for this request
Protocols: HTTP
+Added: 7.55.0
---
Tells curl to use an alternative "target" (path) instead of using the path as
provided in the URL. Particularly useful when wanting to issue HTTP requests
diff --git a/docs/examples/.gitignore b/docs/examples/.gitignore
index aece671c6..f22c7b02f 100644
--- a/docs/examples/.gitignore
+++ b/docs/examples/.gitignore
@@ -70,6 +70,7 @@ smtp-multi
smtp-ssl
smtp-tls
smtp-vrfy
+sslbackend
url2file
usercertinmem
xmlstream
diff --git a/docs/examples/10-at-a-time.c b/docs/examples/10-at-a-time.c
index b0c65b77e..1ffaec301 100644
--- a/docs/examples/10-at-a-time.c
+++ b/docs/examples/10-at-a-time.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -114,7 +114,7 @@ int main(void)
CURLM *cm;
CURLMsg *msg;
long L;
- unsigned int C=0;
+ unsigned int C = 0;
int M, Q, U = -1;
fd_set R, W, E;
struct timeval T;
@@ -162,9 +162,9 @@ int main(void)
T.tv_sec = L/1000;
T.tv_usec = (L%1000)*1000;
- if(0 > select(M+1, &R, &W, &E, &T)) {
+ if(0 > select(M + 1, &R, &W, &E, &T)) {
fprintf(stderr, "E: select(%i,,,,%li): %i: %s\n",
- M+1, L, errno, strerror(errno));
+ M + 1, L, errno, strerror(errno));
return EXIT_FAILURE;
}
}
diff --git a/docs/examples/Makefile.inc b/docs/examples/Makefile.inc
index b92ad6bd5..71b804c75 100644
--- a/docs/examples/Makefile.inc
+++ b/docs/examples/Makefile.inc
@@ -26,18 +26,19 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \
https multi-app multi-debugcallback multi-double multi-post multi-single \
persistant post-callback postit2 sepheaders simple simplepost simplessl \
sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \
- smtp-mail smtp-multi smtp-ssl smtp-tls smtp-vrfy smtp-expn rtsp \
- externalsocket resolve progressfunc pop3-retr pop3-list pop3-uidl \
+ smtp-mail smtp-mime smtp-multi smtp-ssl smtp-tls smtp-vrfy smtp-expn \
+ rtsp externalsocket resolve progressfunc pop3-retr pop3-list pop3-uidl \
pop3-dele pop3-top pop3-stat pop3-noop pop3-ssl pop3-tls pop3-multi \
imap-list imap-lsub imap-fetch imap-store imap-append imap-examine \
imap-search imap-create imap-delete imap-copy imap-noop imap-ssl \
imap-tls imap-multi url2file sftpget ftpsget postinmemory http2-download \
- http2-upload http2-serverpush getredirect ftpuploadfrommem
+ http2-upload http2-serverpush getredirect ftpuploadfrommem \
+ ftpuploadresume sslbackend postit2-formadd multi-formadd
# These examples require external dependencies that may not be commonly
# available on POSIX systems, so don't bother attempting to compile them here.
COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.c \
- ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c \
+ ghiper.c hiperfifo.c htmltidy.c multithread.c \
opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \
multi-uv.c xmlstream.c usercertinmem.c sessioninfo.c
diff --git a/docs/examples/anyauthput.c b/docs/examples/anyauthput.c
index 9881d1a6c..bdbc0cb25 100644
--- a/docs/examples/anyauthput.c
+++ b/docs/examples/anyauthput.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -106,7 +106,7 @@ int main(int argc, char **argv)
if(argc < 3)
return 1;
- file= argv[1];
+ file = argv[1];
url = argv[2];
/* get the file size of the local file */
diff --git a/docs/examples/cacertinmem.c b/docs/examples/cacertinmem.c
index 2a06e51e4..4bbec4663 100644
--- a/docs/examples/cacertinmem.c
+++ b/docs/examples/cacertinmem.c
@@ -37,7 +37,7 @@ size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
{
X509_STORE *store;
- X509 *cert=NULL;
+ X509 *cert = NULL;
BIO *bio;
char *mypem = /* www.cacert.org */
"-----BEGIN CERTIFICATE-----\n"\
@@ -82,7 +82,7 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
"omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"\
"-----END CERTIFICATE-----\n";
/* get a BIO */
- bio=BIO_new_mem_buf(mypem, -1);
+ bio = BIO_new_mem_buf(mypem, -1);
/* use it to read the PEM formatted certificate from memory into an X509
* structure that SSL can use
*/
@@ -91,10 +91,10 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
printf("PEM_read_bio_X509 failed...\n");
/* get a pointer to the X509 certificate store (which may be empty!) */
- store=SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
+ store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
/* add our certificate to this store */
- if(X509_STORE_add_cert(store, cert)==0)
+ if(X509_STORE_add_cert(store, cert) == 0)
printf("error adding certificate\n");
/* decrease reference counts */
@@ -110,24 +110,24 @@ int main(void)
CURL *ch;
CURLcode rv;
- rv=curl_global_init(CURL_GLOBAL_ALL);
- ch=curl_easy_init();
- rv=curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
- rv=curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
- rv=curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
- rv=curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
- rv=curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, *writefunction);
- rv=curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout);
- rv=curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, *writefunction);
- rv=curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr);
- rv=curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
- rv=curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
- rv=curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");
+ rv = curl_global_init(CURL_GLOBAL_ALL);
+ ch = curl_easy_init();
+ rv = curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
+ rv = curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
+ rv = curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
+ rv = curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
+ rv = curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, *writefunction);
+ rv = curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout);
+ rv = curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, *writefunction);
+ rv = curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr);
+ rv = curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
+ rv = curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
+ rv = curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");
/* first try: retrieve page without cacerts' certificate -> will fail
*/
- rv=curl_easy_perform(ch);
- if(rv==CURLE_OK)
+ rv = curl_easy_perform(ch);
+ if(rv == CURLE_OK)
printf("*** transfer succeeded ***\n");
else
printf("*** transfer failed ***\n");
@@ -136,9 +136,9 @@ int main(void)
* load the certificate by installing a function doing the necessary
* "modifications" to the SSL CONTEXT just before link init
*/
- rv=curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
- rv=curl_easy_perform(ch);
- if(rv==CURLE_OK)
+ rv = curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
+ rv = curl_easy_perform(ch);
+ if(rv == CURLE_OK)
printf("*** transfer succeeded ***\n");
else
printf("*** transfer failed ***\n");
diff --git a/docs/examples/chkspeed.c b/docs/examples/chkspeed.c
index 17283bb7d..5c032db8b 100644
--- a/docs/examples/chkspeed.c
+++ b/docs/examples/chkspeed.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -93,7 +93,7 @@ int main(int argc, char *argv[])
prttime = 1;
}
else if(strncasecmp(*argv, "-M=", 3) == 0) {
- long m = strtol((*argv)+3, NULL, 10);
+ long m = strtol((*argv) + 3, NULL, 10);
switch(m) {
case 1:
url = URL_1M;
diff --git a/docs/examples/curlx.c b/docs/examples/curlx.c
index 5e3a00be5..24579fa2a 100644
--- a/docs/examples/curlx.c
+++ b/docs/examples/curlx.c
@@ -195,7 +195,8 @@ static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
if(p->verbose > 2)
BIO_printf(p->errorbio, "entering ssl_app_verify_callback\n");
- if((ok= X509_verify_cert(ctx)) && ctx->cert) {
+ ok = X509_verify_cert(ctx);
+ if(ok && ctx->cert) {
unsigned char *accessinfo;
if(p->verbose > 1)
X509_print_ex(p->errorbio, ctx->cert, 0, 0);
@@ -268,16 +269,16 @@ static CURLcode sslctxfun(CURL *curl, void *sslctx, void *parm)
int main(int argc, char **argv)
{
- BIO* in=NULL;
- BIO* out=NULL;
+ BIO* in = NULL;
+ BIO* out = NULL;
char *outfile = NULL;
char *infile = NULL;
- int tabLength=100;
+ int tabLength = 100;
char *binaryptr;
char *mimetype;
- char *mimetypeaccept=NULL;
+ char *mimetypeaccept = NULL;
char *contenttype;
const char **pp;
unsigned char *hostporturl = NULL;
@@ -288,8 +289,8 @@ int main(int argc, char **argv)
char *response;
CURLcode res;
- struct curl_slist *headers=NULL;
- int badarg=0;
+ struct curl_slist *headers = NULL;
+ int badarg = 0;
binaryptr = malloc(tabLength);
@@ -307,75 +308,75 @@ int main(int argc, char **argv)
while(*args && *args[0] == '-') {
if(!strcmp (*args, "-in")) {
if(args[1]) {
- infile=*(++args);
+ infile = *(++args);
}
else
- badarg=1;
+ badarg = 1;
}
else if(!strcmp (*args, "-out")) {
if(args[1]) {
- outfile=*(++args);
+ outfile = *(++args);
}
else
- badarg=1;
+ badarg = 1;
}
else if(!strcmp (*args, "-p12")) {
if(args[1]) {
p.p12file = *(++args);
}
else
- badarg=1;
+ badarg = 1;
}
else if(strcmp(*args, "-envpass") == 0) {
if(args[1]) {
p.pst = getenv(*(++args));
}
else
- badarg=1;
+ badarg = 1;
}
else if(strcmp(*args, "-connect") == 0) {
if(args[1]) {
hostporturl = *(++args);
}
else
- badarg=1;
+ badarg = 1;
}
else if(strcmp(*args, "-mimetype") == 0) {
if(args[1]) {
mimetype = *(++args);
}
else
- badarg=1;
+ badarg = 1;
}
else if(strcmp(*args, "-acceptmime") == 0) {
if(args[1]) {
mimetypeaccept = *(++args);
}
else
- badarg=1;
+ badarg = 1;
}
else if(strcmp(*args, "-accesstype") == 0) {
if(args[1]) {
p.accesstype = OBJ_obj2nid(OBJ_txt2obj(*++args, 0));
if(p.accesstype == 0)
- badarg=1;
+ badarg = 1;
}
else
- badarg=1;
+ badarg = 1;
}
else if(strcmp(*args, "-verbose") == 0) {
p.verbose++;
}
else
- badarg=1;
+ badarg = 1;
args++;
}
- if(mimetype==NULL || mimetypeaccept == NULL)
+ if(mimetype == NULL || mimetypeaccept == NULL)
badarg = 1;
if(badarg) {
- for(pp=curlx_usage; (*pp != NULL); pp++)
+ for(pp = curlx_usage; (*pp != NULL); pp++)
BIO_printf(p.errorbio, "%s\n", *pp);
BIO_printf(p.errorbio, "\n");
goto err;
@@ -383,7 +384,8 @@ int main(int argc, char **argv)
/* set input */
- if((in=BIO_new(BIO_s_file())) == NULL) {
+ in = BIO_new(BIO_s_file());
+ if(in == NULL) {
BIO_printf(p.errorbio, "Error setting input bio\n");
goto err;
}
@@ -397,7 +399,8 @@ int main(int argc, char **argv)
/* set output */
- if((out=BIO_new(BIO_s_file())) == NULL) {
+ out = BIO_new(BIO_s_file());
+ if(out == NULL) {
BIO_printf(p.errorbio, "Error setting output bio.\n");
goto err;
}
@@ -429,7 +432,7 @@ int main(int argc, char **argv)
goto err;
}
- p.ca= NULL;
+ p.ca = NULL;
if(!(PKCS12_parse (p.p12, p.pst, &(p.pkey), &(p.usercert), &(p.ca) ) )) {
BIO_printf(p.errorbio, "Invalid P12 structure in %s\n", p.p12file);
goto err;
@@ -454,10 +457,10 @@ int main(int argc, char **argv)
given access type */
serverurl = my_get_ext(p.usercert, p.accesstype, NID_info_access);
if(!serverurl) {
- int j=0;
+ int j = 0;
BIO_printf(p.errorbio, "no service URL in user cert "
"cherching in others certificats\n");
- for(j=0; j<sk_X509_num(p.ca); j++) {
+ for(j = 0; j<sk_X509_num(p.ca); j++) {
serverurl = my_get_ext(sk_X509_value(p.ca, j), p.accesstype,
NID_info_access);
if(serverurl)
@@ -489,8 +492,8 @@ int main(int argc, char **argv)
/* pass our list of custom made headers */
- contenttype = malloc(15+strlen(mimetype));
- snprintf(contenttype, 15+strlen(mimetype), "Content-type: %s", mimetype);
+ contenttype = malloc(15 + strlen(mimetype));
+ snprintf(contenttype, 15 + strlen(mimetype), "Content-type: %s", mimetype);
headers = curl_slist_append(headers, contenttype);
curl_easy_setopt(p.curl, CURLOPT_HTTPHEADER, headers);
@@ -512,12 +515,12 @@ int main(int argc, char **argv)
curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_DATA, &p);
{
- int lu; int i=0;
+ int lu; int i = 0;
while((lu = BIO_read(in, &binaryptr[i], tabLength-i)) >0) {
- i+=lu;
- if(i== tabLength) {
- tabLength+=100;
- binaryptr=realloc(binaryptr, tabLength); /* should be more careful */
+ i += lu;
+ if(i == tabLength) {
+ tabLength += 100;
+ binaryptr = realloc(binaryptr, tabLength); /* should be more careful */
}
}
tabLength = i;
@@ -533,7 +536,7 @@ int main(int argc, char **argv)
BIO_printf(p.errorbio, "%d %s %d\n", __LINE__, "curl_easy_perform",
res = curl_easy_perform(p.curl));
{
- int result =curl_easy_getinfo(p.curl, CURLINFO_CONTENT_TYPE, &response);
+ int result = curl_easy_getinfo(p.curl, CURLINFO_CONTENT_TYPE, &response);
if(mimetypeaccept && p.verbose)
if(!strcmp(mimetypeaccept, response))
BIO_printf(p.errorbio, "the response has a correct mimetype : %s\n",
diff --git a/docs/examples/debug.c b/docs/examples/debug.c
index 8a490a281..8f77e1243 100644
--- a/docs/examples/debug.c
+++ b/docs/examples/debug.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,7 +38,7 @@ void dump(const char *text,
size_t i;
size_t c;
- unsigned int width=0x10;
+ unsigned int width = 0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
@@ -47,30 +47,32 @@ void dump(const char *text,
fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
text, (long)size, (long)size);
- for(i=0; i<size; i+= width) {
+ for(i = 0; i<size; i += width) {
fprintf(stream, "%4.4lx: ", (long)i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
- if(i+c < size)
- fprintf(stream, "%02x ", ptr[i+c]);
+ if(i + c < size)
+ fprintf(stream, "%02x ", ptr[i + c]);
else
fputs(" ", stream);
}
- for(c = 0; (c < width) && (i+c < size); c++) {
+ for(c = 0; (c < width) && (i + c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
- if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
- i+=(c+2-width);
+ if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+ ptr[i + c + 1] == 0x0A) {
+ i += (c + 2 - width);
break;
}
fprintf(stream, "%c",
- (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+ (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
- if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
- i+=(c+3-width);
+ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+ ptr[i + c + 2] == 0x0A) {
+ i += (c + 3 - width);
break;
}
}
diff --git a/docs/examples/evhiperfifo.c b/docs/examples/evhiperfifo.c
index a41346e31..c41c21f90 100644
--- a/docs/examples/evhiperfifo.c
+++ b/docs/examples/evhiperfifo.c
@@ -136,28 +136,28 @@ static void mcode_or_die(const char *where, CURLMcode code)
const char *s;
switch(code) {
case CURLM_BAD_HANDLE:
- s="CURLM_BAD_HANDLE";
+ s = "CURLM_BAD_HANDLE";
break;
case CURLM_BAD_EASY_HANDLE:
- s="CURLM_BAD_EASY_HANDLE";
+ s = "CURLM_BAD_EASY_HANDLE";
break;
case CURLM_OUT_OF_MEMORY:
- s="CURLM_OUT_OF_MEMORY";
+ s = "CURLM_OUT_OF_MEMORY";
break;
case CURLM_INTERNAL_ERROR:
- s="CURLM_INTERNAL_ERROR";
+ s = "CURLM_INTERNAL_ERROR";
break;
case CURLM_UNKNOWN_OPTION:
- s="CURLM_UNKNOWN_OPTION";
+ s = "CURLM_UNKNOWN_OPTION";
break;
case CURLM_LAST:
- s="CURLM_LAST";
+ s = "CURLM_LAST";
break;
default:
- s="CURLM_unknown";
+ s = "CURLM_unknown";
break;
case CURLM_BAD_SOCKET:
- s="CURLM_BAD_SOCKET";
+ s = "CURLM_BAD_SOCKET";
fprintf(MSG_OUT, "ERROR: %s returns %s\n", where, s);
/* ignore this error */
return;
@@ -257,7 +257,7 @@ static void setsock(SockInfo *f, curl_socket_t s, CURL *e, int act,
ev_io_stop(g->loop, &f->ev);
ev_io_init(&f->ev, event_cb, f->sockfd, kind);
f->ev.data = g;
- f->evset=1;
+ f->evset = 1;
ev_io_start(g->loop, &f->ev);
}
@@ -371,13 +371,13 @@ static void new_conn(char *url, GlobalInfo *g)
static void fifo_cb(EV_P_ struct ev_io *w, int revents)
{
char s[1024];
- long int rv=0;
- int n=0;
+ long int rv = 0;
+ int n = 0;
GlobalInfo *g = (GlobalInfo *)w->data;
do {
s[0]='\0';
- rv=fscanf(g->input, "%1023s%n", s, &n);
+ rv = fscanf(g->input, "%1023s%n", s, &n);
s[n]='\0';
if(n && s[0]) {
new_conn(s, g); /* if we read a URL, go get it! */
diff --git a/docs/examples/fopen.c b/docs/examples/fopen.c
index d559658a7..590f41a85 100644
--- a/docs/examples/fopen.c
+++ b/docs/examples/fopen.c
@@ -13,7 +13,7 @@
* See the main() function at the bottom that shows an app that retrieves from
* a specified url using fgets() and fread() and saves as two output files.
*
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003, 2017 Simtec Electronics
*
* Re-implemented by Vincent Sanders <vince@kyllikki.org> with extensive
* reference to original curl example code
@@ -58,9 +58,9 @@
#include <gnurl/curl.h>
enum fcurl_type_e {
- CFTYPE_NONE=0,
- CFTYPE_FILE=1,
- CFTYPE_CURL=2
+ CFTYPE_NONE = 0,
+ CFTYPE_FILE = 1,
+ CFTYPE_CURL = 2
};
struct fcurl_data
@@ -102,19 +102,19 @@ static size_t write_callback(char *buffer,
URL_FILE *url = (URL_FILE *)userp;
size *= nitems;
- rembuff=url->buffer_len - url->buffer_pos; /* remaining space in buffer */
+ rembuff = url->buffer_len - url->buffer_pos; /* remaining space in buffer */
if(size > rembuff) {
/* not enough space in buffer */
- newbuff=realloc(url->buffer, url->buffer_len + (size - rembuff));
- if(newbuff==NULL) {
+ newbuff = realloc(url->buffer, url->buffer_len + (size - rembuff));
+ if(newbuff == NULL) {
fprintf(stderr, "callback buffer grow failed\n");
- size=rembuff;
+ size = rembuff;
}
else {
/* realloc succeeded increase buffer size*/
- url->buffer_len+=size - rembuff;
- url->buffer=newbuff;
+ url->buffer_len += size - rembuff;
+ url->buffer = newbuff;
}
}
@@ -189,7 +189,7 @@ static int fill_buffer(URL_FILE *file, size_t want)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
@@ -211,12 +211,12 @@ static int fill_buffer(URL_FILE *file, size_t want)
static int use_buffer(URL_FILE *file, size_t want)
{
/* sort out buffer */
- if((file->buffer_pos - want) <=0) {
+ if((file->buffer_pos - want) <= 0) {
/* ditch buffer - write will recreate */
free(file->buffer);
- file->buffer=NULL;
- file->buffer_pos=0;
- file->buffer_len=0;
+ file->buffer = NULL;
+ file->buffer_pos = 0;
+ file->buffer_len = 0;
}
else {
/* move rest down make it available for later */
@@ -243,7 +243,8 @@ URL_FILE *url_fopen(const char *url, const char *operation)
memset(file, 0, sizeof(URL_FILE));
- if((file->handle.file=fopen(url, operation)))
+ file->handle.file = fopen(url, operation);
+ if(file->handle.file)
file->type = CFTYPE_FILE; /* marked as URL */
else {
@@ -282,11 +283,11 @@ URL_FILE *url_fopen(const char *url, const char *operation)
int url_fclose(URL_FILE *file)
{
- int ret=0;/* default is good return */
+ int ret = 0;/* default is good return */
switch(file->type) {
case CFTYPE_FILE:
- ret=fclose(file->handle.file); /* passthrough */
+ ret = fclose(file->handle.file); /* passthrough */
break;
case CFTYPE_CURL:
@@ -298,8 +299,8 @@ int url_fclose(URL_FILE *file)
break;
default: /* unknown or supported type - oh dear */
- ret=EOF;
- errno=EBADF;
+ ret = EOF;
+ errno = EBADF;
break;
}
@@ -311,11 +312,11 @@ int url_fclose(URL_FILE *file)
int url_feof(URL_FILE *file)
{
- int ret=0;
+ int ret = 0;
switch(file->type) {
case CFTYPE_FILE:
- ret=feof(file->handle.file);
+ ret = feof(file->handle.file);
break;
case CFTYPE_CURL:
@@ -324,8 +325,8 @@ int url_feof(URL_FILE *file)
break;
default: /* unknown or supported type - oh dear */
- ret=-1;
- errno=EBADF;
+ ret = -1;
+ errno = EBADF;
break;
}
return ret;
@@ -337,7 +338,7 @@ size_t url_fread(void *ptr, size_t size, size_t nmemb, URL_FILE *file)
switch(file->type) {
case CFTYPE_FILE:
- want=fread(ptr, size, nmemb, file->handle.file);
+ want = fread(ptr, size, nmemb, file->handle.file);
break;
case CFTYPE_CURL:
@@ -363,8 +364,8 @@ size_t url_fread(void *ptr, size_t size, size_t nmemb, URL_FILE *file)
break;
default: /* unknown or supported type - oh dear */
- want=0;
- errno=EBADF;
+ want = 0;
+ errno = EBADF;
break;
}
@@ -395,24 +396,24 @@ char *url_fgets(char *ptr, size_t size, URL_FILE *file)
/*buffer contains data */
/* look for newline or eof */
- for(loop=0;loop < want;loop++) {
+ for(loop = 0; loop < want; loop++) {
if(file->buffer[loop] == '\n') {
- want=loop+1;/* include newline */
+ want = loop + 1;/* include newline */
break;
}
}
/* xfer data to caller */
memcpy(ptr, file->buffer, want);
- ptr[want]=0;/* always null terminate */
+ ptr[want] = 0;/* always null terminate */
use_buffer(file, want);
break;
default: /* unknown or supported type - oh dear */
- ptr=NULL;
- errno=EBADF;
+ ptr = NULL;
+ errno = EBADF;
break;
}
@@ -435,9 +436,9 @@ void url_rewind(URL_FILE *file)
/* ditch buffer - write will recreate - resets stream pos*/
free(file->buffer);
- file->buffer=NULL;
- file->buffer_pos=0;
- file->buffer_len=0;
+ file->buffer = NULL;
+ file->buffer_pos = 0;
+ file->buffer_len = 0;
break;
@@ -463,12 +464,12 @@ int main(int argc, char *argv[])
const char *url;
if(argc < 2)
- url="http://192.168.7.3/testfile";/* default to testurl */
+ url = "http://192.168.7.3/testfile";/* default to testurl */
else
- url=argv[1];/* use passed url */
+ url = argv[1];/* use passed url */
/* copy from url line by line with fgets */
- outf=fopen(FGETSFILE, "wb+");
+ outf = fopen(FGETSFILE, "wb+");
if(!outf) {
perror("couldn't open fgets output file\n");
return 1;
@@ -492,7 +493,7 @@ int main(int argc, char *argv[])
/* Copy from url with fread */
- outf=fopen(FREADFILE, "wb+");
+ outf = fopen(FREADFILE, "wb+");
if(!outf) {
perror("couldn't open fread output file\n");
return 1;
@@ -516,7 +517,7 @@ int main(int argc, char *argv[])
/* Test rewind */
- outf=fopen(REWINDFILE, "wb+");
+ outf = fopen(REWINDFILE, "wb+");
if(!outf) {
perror("couldn't open fread output file\n");
return 1;
diff --git a/docs/examples/ftpget.c b/docs/examples/ftpget.c
index bfb6acb05..f9d78ae7f 100644
--- a/docs/examples/ftpget.c
+++ b/docs/examples/ftpget.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,10 +35,10 @@ struct FtpFile {
static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
- struct FtpFile *out=(struct FtpFile *)stream;
+ struct FtpFile *out = (struct FtpFile *)stream;
if(out && !out->stream) {
/* open file for writing */
- out->stream=fopen(out->filename, "wb");
+ out->stream = fopen(out->filename, "wb");
if(!out->stream)
return -1; /* failure, can't open file to write */
}
@@ -50,7 +50,7 @@ int main(void)
{
CURL *curl;
CURLcode res;
- struct FtpFile ftpfile={
+ struct FtpFile ftpfile = {
"curl.tar.gz", /* name to store the file as if successful */
NULL
};
diff --git a/docs/examples/ftpsget.c b/docs/examples/ftpsget.c
index 021cdae13..348747ab4 100644
--- a/docs/examples/ftpsget.c
+++ b/docs/examples/ftpsget.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,10 +37,10 @@ struct FtpFile {
static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
void *stream)
{
- struct FtpFile *out=(struct FtpFile *)stream;
+ struct FtpFile *out = (struct FtpFile *)stream;
if(out && !out->stream) {
/* open file for writing */
- out->stream=fopen(out->filename, "wb");
+ out->stream = fopen(out->filename, "wb");
if(!out->stream)
return -1; /* failure, can't open file to write */
}
@@ -52,7 +52,7 @@ int main(void)
{
CURL *curl;
CURLcode res;
- struct FtpFile ftpfile={
+ struct FtpFile ftpfile = {
"yourfile.bin", /* name to store the file as if successful */
NULL
};
diff --git a/docs/examples/ftpupload.c b/docs/examples/ftpupload.c
index 3692449f1..ec91c818b 100644
--- a/docs/examples/ftpupload.c
+++ b/docs/examples/ftpupload.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -71,7 +71,7 @@ int main(void)
struct stat file_info;
curl_off_t fsize;
- struct curl_slist *headerlist=NULL;
+ struct curl_slist *headerlist = NULL;
static const char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
static const char buf_2 [] = "RNTO " RENAME_FILE_TO;
diff --git a/docs/examples/ftpuploadresume.c b/docs/examples/ftpuploadresume.c
index 4b6d6677e..c966c76e9 100644
--- a/docs/examples/ftpuploadresume.c
+++ b/docs/examples/ftpuploadresume.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,44 +26,32 @@
#include <stdlib.h>
#include <stdio.h>
-
#include <gnurl/curl.h>
-#if defined(_MSC_VER) && (_MSC_VER < 1300)
-# error _snscanf requires MSVC 7.0 or later.
-#endif
-
-/* The MinGW headers are missing a few Win32 function definitions,
- you shouldn't need this if you use VC++ */
-#if defined(__MINGW32__) && !defined(__MINGW64__)
-int __cdecl _snscanf(const char *input, size_t length,
- const char *format, ...);
-#endif
-
-
/* parse headers for Content-Length */
-size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream)
+static size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb,
+ void *stream)
{
int r;
long len = 0;
- /* _snscanf() is Win32 specific */
- r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);
-
- if(r) /* Microsoft: we don't read the specs */
+ r = sscanf(ptr, "Content-Length: %ld\n", &len);
+ if(r)
*((long *) stream) = len;
return size * nmemb;
}
/* discard downloaded data */
-size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream)
+static size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
+ (void)ptr;
+ (void)stream;
return size * nmemb;
}
/* read data to upload */
-size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
+static size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
FILE *f = stream;
size_t n;
@@ -77,8 +65,8 @@ size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
}
-int upload(CURL *curlhandle, const char *remotepath, const char *localpath,
- long timeout, long tries)
+static int upload(CURL *curlhandle, const char *remotepath,
+ const char *localpath, long timeout, long tries)
{
FILE *f;
long uploaded_len = 0;
@@ -156,7 +144,7 @@ int upload(CURL *curlhandle, const char *remotepath, const char *localpath,
}
}
-int main(int c, char **argv)
+int main(void)
{
CURL *curlhandle = NULL;
diff --git a/docs/examples/ghiper.c b/docs/examples/ghiper.c
index 6c5c5e45e..c76d31d0e 100644
--- a/docs/examples/ghiper.c
+++ b/docs/examples/ghiper.c
@@ -99,14 +99,14 @@ static void mcode_or_die(const char *where, CURLMcode code)
if(CURLM_OK != code) {
const char *s;
switch(code) {
- case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break;
- case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break;
- case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break;
- case CURLM_INTERNAL_ERROR: s="CURLM_INTERNAL_ERROR"; break;
- case CURLM_BAD_SOCKET: s="CURLM_BAD_SOCKET"; break;
- case CURLM_UNKNOWN_OPTION: s="CURLM_UNKNOWN_OPTION"; break;
- case CURLM_LAST: s="CURLM_LAST"; break;
- default: s="CURLM_unknown";
+ case CURLM_BAD_HANDLE: s = "CURLM_BAD_HANDLE"; break;
+ case CURLM_BAD_EASY_HANDLE: s = "CURLM_BAD_EASY_HANDLE"; break;
+ case CURLM_OUT_OF_MEMORY: s = "CURLM_OUT_OF_MEMORY"; break;
+ case CURLM_INTERNAL_ERROR: s = "CURLM_INTERNAL_ERROR"; break;
+ case CURLM_BAD_SOCKET: s = "CURLM_BAD_SOCKET"; break;
+ case CURLM_UNKNOWN_OPTION: s = "CURLM_UNKNOWN_OPTION"; break;
+ case CURLM_LAST: s = "CURLM_LAST"; break;
+ default: s = "CURLM_unknown";
}
MSG_OUT("ERROR: %s returns %s\n", where, s);
exit(code);
@@ -156,7 +156,7 @@ static gboolean timer_cb(gpointer data)
static int update_timeout_cb(CURLM *multi, long timeout_ms, void *userp)
{
struct timeval timeout;
- GlobalInfo *g=(GlobalInfo *)userp;
+ GlobalInfo *g = (GlobalInfo *)userp;
timeout.tv_sec = timeout_ms/1000;
timeout.tv_usec = (timeout_ms%1000)*1000;
@@ -181,7 +181,7 @@ static gboolean event_cb(GIOChannel *ch, GIOCondition condition, gpointer data)
{
GlobalInfo *g = (GlobalInfo*) data;
CURLMcode rc;
- int fd=g_io_channel_unix_get_fd(ch);
+ int fd = g_io_channel_unix_get_fd(ch);
int action =
(condition & G_IO_IN ? CURL_CSELECT_IN : 0) |
@@ -228,7 +228,7 @@ static void setsock(SockInfo *f, curl_socket_t s, CURL *e, int act,
if(f->ev) {
g_source_remove(f->ev);
}
- f->ev=g_io_add_watch(f->ch, kind, event_cb, g);
+ f->ev = g_io_add_watch(f->ch, kind, event_cb, g);
}
/* Initialize a new SockInfo structure */
@@ -237,7 +237,7 @@ static void addsock(curl_socket_t s, CURL *easy, int action, GlobalInfo *g)
SockInfo *fdp = g_malloc0(sizeof(SockInfo));
fdp->global = g;
- fdp->ch=g_io_channel_unix_new(s);
+ fdp->ch = g_io_channel_unix_new(s);
setsock(fdp, s, easy, action, g);
curl_multi_assign(g->multi, s, fdp);
}
@@ -319,7 +319,7 @@ static void new_conn(char *url, GlobalInfo *g)
curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_TIME, 30L);
MSG_OUT("Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url);
- rc =curl_multi_add_handle(g->multi, conn->easy);
+ rc = curl_multi_add_handle(g->multi, conn->easy);
mcode_or_die("new_conn: curl_multi_add_handle", rc);
/* note that the add_handle() will set a time-out to trigger very soon so
@@ -331,11 +331,11 @@ static gboolean fifo_cb(GIOChannel *ch, GIOCondition condition, gpointer data)
{
#define BUF_SIZE 1024
gsize len, tp;
- gchar *buf, *tmp, *all=NULL;
+ gchar *buf, *tmp, *all = NULL;
GIOStatus rv;
do {
- GError *err=NULL;
+ GError *err = NULL;
rv = g_io_channel_read_line(ch, &buf, &len, &tp, &err);
if(buf) {
if(tp) {
@@ -345,15 +345,15 @@ static gboolean fifo_cb(GIOChannel *ch, GIOCondition condition, gpointer data)
g_free(buf);
}
else {
- buf = g_malloc(BUF_SIZE+1);
+ buf = g_malloc(BUF_SIZE + 1);
while(TRUE) {
buf[BUF_SIZE]='\0';
g_io_channel_read_chars(ch, buf, BUF_SIZE, &len, &err);
if(len) {
buf[len]='\0';
if(all) {
- tmp=all;
- all=g_strdup_printf("%s%s", tmp, buf);
+ tmp = all;
+ all = g_strdup_printf("%s%s", tmp, buf);
g_free(tmp);
}
else {
@@ -417,12 +417,12 @@ int main(int argc, char **argv)
GMainLoop*gmain;
int fd;
GIOChannel* ch;
- g=g_malloc0(sizeof(GlobalInfo));
+ g = g_malloc0(sizeof(GlobalInfo));
- fd=init_fifo();
- ch=g_io_channel_unix_new(fd);
+ fd = init_fifo();
+ ch = g_io_channel_unix_new(fd);
g_io_add_watch(ch, G_IO_IN, fifo_cb, g);
- gmain=g_main_loop_new(NULL, FALSE);
+ gmain = g_main_loop_new(NULL, FALSE);
g->multi = curl_multi_init();
curl_multi_setopt(g->multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
curl_multi_setopt(g->multi, CURLMOPT_SOCKETDATA, g);
diff --git a/docs/examples/hiperfifo.c b/docs/examples/hiperfifo.c
index 2d0dc7a31..a502d48f0 100644
--- a/docs/examples/hiperfifo.c
+++ b/docs/examples/hiperfifo.c
@@ -137,15 +137,15 @@ static void mcode_or_die(const char *where, CURLMcode code)
if(CURLM_OK != code) {
const char *s;
switch(code) {
- case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break;
- case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break;
- case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break;
- case CURLM_INTERNAL_ERROR: s="CURLM_INTERNAL_ERROR"; break;
- case CURLM_UNKNOWN_OPTION: s="CURLM_UNKNOWN_OPTION"; break;
- case CURLM_LAST: s="CURLM_LAST"; break;
- default: s="CURLM_unknown";
+ case CURLM_BAD_HANDLE: s = "CURLM_BAD_HANDLE"; break;
+ case CURLM_BAD_EASY_HANDLE: s = "CURLM_BAD_EASY_HANDLE"; break;
+ case CURLM_OUT_OF_MEMORY: s = "CURLM_OUT_OF_MEMORY"; break;
+ case CURLM_INTERNAL_ERROR: s = "CURLM_INTERNAL_ERROR"; break;
+ case CURLM_UNKNOWN_OPTION: s = "CURLM_UNKNOWN_OPTION"; break;
+ case CURLM_LAST: s = "CURLM_LAST"; break;
+ default: s = "CURLM_unknown";
break;
- case CURLM_BAD_SOCKET: s="CURLM_BAD_SOCKET";
+ case CURLM_BAD_SOCKET: s = "CURLM_BAD_SOCKET";
fprintf(MSG_OUT, "ERROR: %s returns %s\n", where, s);
/* ignore this error */
return;
@@ -359,15 +359,15 @@ static void new_conn(char *url, GlobalInfo *g)
static void fifo_cb(int fd, short event, void *arg)
{
char s[1024];
- long int rv=0;
- int n=0;
+ long int rv = 0;
+ int n = 0;
GlobalInfo *g = (GlobalInfo *)arg;
(void)fd; /* unused */
(void)event; /* unused */
do {
s[0]='\0';
- rv=fscanf(g->input, "%1023s%n", s, &n);
+ rv = fscanf(g->input, "%1023s%n", s, &n);
s[n]='\0';
if(n && s[0]) {
new_conn(s, arg); /* if we read a URL, go get it! */
diff --git a/docs/examples/htmltidy.c b/docs/examples/htmltidy.c
index e6f2f4058..2da21fe6c 100644
--- a/docs/examples/htmltidy.c
+++ b/docs/examples/htmltidy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -52,7 +52,7 @@ void dumpNode(TidyDoc doc, TidyNode tnod, int indent)
TidyAttr attr;
printf("%*.*s%s ", indent, indent, "<", name);
/* walk the attribute list */
- for(attr=tidyAttrFirst(child); attr; attr=tidyAttrNext(attr) ) {
+ for(attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr) ) {
printf(tidyAttrName(attr));
tidyAttrValue(attr)?printf("=\"%s\" ",
tidyAttrValue(attr)):printf(" ");
@@ -95,7 +95,7 @@ int main(int argc, char **argv)
tidyBufInit(&docbuf);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &docbuf);
- err=curl_easy_perform(curl);
+ err = curl_easy_perform(curl);
if(!err) {
err = tidyParseBuffer(tdoc, &docbuf); /* parse the input */
if(err >= 0) {
diff --git a/docs/examples/http2-download.c b/docs/examples/http2-download.c
index 3ccd2e2ee..0a8847b3e 100644
--- a/docs/examples/http2-download.c
+++ b/docs/examples/http2-download.c
@@ -51,7 +51,7 @@ static int num_transfers;
static int hnd2num(CURL *hnd)
{
int i;
- for(i=0; i< num_transfers; i++) {
+ for(i = 0; i< num_transfers; i++) {
if(curl_hnd[i] == hnd)
return i;
}
@@ -65,7 +65,7 @@ void dump(const char *text, int num, unsigned char *ptr, size_t size,
size_t i;
size_t c;
- unsigned int width=0x10;
+ unsigned int width = 0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
@@ -74,30 +74,32 @@ void dump(const char *text, int num, unsigned char *ptr, size_t size,
fprintf(stderr, "%d %s, %ld bytes (0x%lx)\n",
num, text, (long)size, (long)size);
- for(i=0; i<size; i+= width) {
+ for(i = 0; i<size; i += width) {
fprintf(stderr, "%4.4lx: ", (long)i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
- if(i+c < size)
- fprintf(stderr, "%02x ", ptr[i+c]);
+ if(i + c < size)
+ fprintf(stderr, "%02x ", ptr[i + c]);
else
fputs(" ", stderr);
}
- for(c = 0; (c < width) && (i+c < size); c++) {
+ for(c = 0; (c < width) && (i + c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
- if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
- i+=(c+2-width);
+ if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+ ptr[i + c + 1] == 0x0A) {
+ i += (c + 2 - width);
break;
}
fprintf(stderr, "%c",
- (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+ (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
- if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
- i+=(c+3-width);
+ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+ ptr[i + c + 2] == 0x0A) {
+ i += (c + 3 - width);
break;
}
}
@@ -199,7 +201,7 @@ int main(int argc, char **argv)
/* init a multi stack */
multi_handle = curl_multi_init();
- for(i=0; i<num_transfers; i++) {
+ for(i = 0; i<num_transfers; i++) {
easy[i] = curl_easy_init();
/* set options */
setup(easy[i], i);
@@ -269,7 +271,7 @@ int main(int argc, char **argv)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
@@ -286,7 +288,7 @@ int main(int argc, char **argv)
curl_multi_cleanup(multi_handle);
- for(i=0; i<num_transfers; i++)
+ for(i = 0; i<num_transfers; i++)
curl_easy_cleanup(easy[i]);
return 0;
diff --git a/docs/examples/http2-serverpush.c b/docs/examples/http2-serverpush.c
index a01d165ff..9ad621b97 100644
--- a/docs/examples/http2-serverpush.c
+++ b/docs/examples/http2-serverpush.c
@@ -45,7 +45,7 @@ void dump(const char *text, unsigned char *ptr, size_t size,
size_t i;
size_t c;
- unsigned int width=0x10;
+ unsigned int width = 0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
@@ -54,30 +54,32 @@ void dump(const char *text, unsigned char *ptr, size_t size,
fprintf(stderr, "%s, %ld bytes (0x%lx)\n",
text, (long)size, (long)size);
- for(i=0; i<size; i+= width) {
+ for(i = 0; i<size; i += width) {
fprintf(stderr, "%4.4lx: ", (long)i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
- if(i+c < size)
- fprintf(stderr, "%02x ", ptr[i+c]);
+ if(i + c < size)
+ fprintf(stderr, "%02x ", ptr[i + c]);
else
fputs(" ", stderr);
}
- for(c = 0; (c < width) && (i+c < size); c++) {
+ for(c = 0; (c < width) && (i + c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
- if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
- i+=(c+2-width);
+ if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+ ptr[i + c + 1] == 0x0A) {
+ i += (c + 2 - width);
break;
}
fprintf(stderr, "%c",
- (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+ (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
- if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
- i+=(c+3-width);
+ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+ ptr[i + c + 2] == 0x0A) {
+ i += (c + 3 - width);
break;
}
}
@@ -181,7 +183,7 @@ static int server_push_callback(CURL *parent,
fprintf(stderr, "**** push callback approves stream %u, got %d headers!\n",
count, (int)num_headers);
- for(i=0; i<num_headers; i++) {
+ for(i = 0; i<num_headers; i++) {
headp = curl_pushheader_bynum(headers, i);
fprintf(stderr, "**** header %u: %s\n", (int)i, headp);
}
@@ -204,7 +206,7 @@ int main(void)
CURL *easy;
CURLM *multi_handle;
int still_running; /* keep number of running handles */
- int transfers=1; /* we start with one */
+ int transfers = 1; /* we start with one */
struct CURLMsg *m;
/* init a multi stack */
@@ -281,7 +283,7 @@ int main(void)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
diff --git a/docs/examples/http2-upload.c b/docs/examples/http2-upload.c
index 57bee796b..a2561fe7e 100644
--- a/docs/examples/http2-upload.c
+++ b/docs/examples/http2-upload.c
@@ -53,7 +53,7 @@ static int num_transfers;
static int hnd2num(CURL *hnd)
{
int i;
- for(i=0; i< num_transfers; i++) {
+ for(i = 0; i< num_transfers; i++) {
if(curl_hnd[i] == hnd)
return i;
}
@@ -66,7 +66,7 @@ void dump(const char *text, int num, unsigned char *ptr, size_t size,
{
size_t i;
size_t c;
- unsigned int width=0x10;
+ unsigned int width = 0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
@@ -75,30 +75,32 @@ void dump(const char *text, int num, unsigned char *ptr, size_t size,
fprintf(stderr, "%d %s, %ld bytes (0x%lx)\n",
num, text, (long)size, (long)size);
- for(i=0; i<size; i+= width) {
+ for(i = 0; i<size; i += width) {
fprintf(stderr, "%4.4lx: ", (long)i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
- if(i+c < size)
- fprintf(stderr, "%02x ", ptr[i+c]);
+ if(i + c < size)
+ fprintf(stderr, "%02x ", ptr[i + c]);
else
fputs(" ", stderr);
}
- for(c = 0; (c < width) && (i+c < size); c++) {
+ for(c = 0; (c < width) && (i + c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
- if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
- i+=(c+2-width);
+ if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+ ptr[i + c + 1] == 0x0A) {
+ i += (c + 2 - width);
break;
}
fprintf(stderr, "%c",
- (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+ (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
- if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
- i+=(c+3-width);
+ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+ ptr[i + c + 2] == 0x0A) {
+ i += (c + 3 - width);
break;
}
}
@@ -260,7 +262,7 @@ int main(int argc, char **argv)
/* init a multi stack */
multi_handle = curl_multi_init();
- for(i=0; i<num_transfers; i++) {
+ for(i = 0; i<num_transfers; i++) {
easy[i] = curl_easy_init();
/* set options */
setup(easy[i], i, filename);
@@ -333,7 +335,7 @@ int main(int argc, char **argv)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
@@ -350,7 +352,7 @@ int main(int argc, char **argv)
curl_multi_cleanup(multi_handle);
- for(i=0; i<num_transfers; i++)
+ for(i = 0; i<num_transfers; i++)
curl_easy_cleanup(easy[i]);
return 0;
diff --git a/docs/examples/httpput.c b/docs/examples/httpput.c
index 19d205b78..8399dbfe7 100644
--- a/docs/examples/httpput.c
+++ b/docs/examples/httpput.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -69,7 +69,7 @@ int main(int argc, char **argv)
if(argc < 3)
return 1;
- file= argv[1];
+ file = argv[1];
url = argv[2];
/* get the file size of the local file */
diff --git a/docs/examples/imap-multi.c b/docs/examples/imap-multi.c
index 587be2906..c1f429e14 100644
--- a/docs/examples/imap-multi.c
+++ b/docs/examples/imap-multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -144,7 +144,7 @@ int main(void)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
diff --git a/docs/examples/multi-app.c b/docs/examples/multi-app.c
index d7e7af78d..01b76c558 100644
--- a/docs/examples/multi-app.c
+++ b/docs/examples/multi-app.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -55,7 +55,7 @@ int main(void)
int msgs_left; /* how many messages are left */
/* Allocate one CURL handle per transfer */
- for(i=0; i<HANDLECOUNT; i++)
+ for(i = 0; i<HANDLECOUNT; i++)
handles[i] = curl_easy_init();
/* set the options (I left out a few, you'll get the point anyway) */
@@ -68,7 +68,7 @@ int main(void)
multi_handle = curl_multi_init();
/* add the individual transfers */
- for(i=0; i<HANDLECOUNT; i++)
+ for(i = 0; i<HANDLECOUNT; i++)
curl_multi_add_handle(multi_handle, handles[i]);
/* we start some action by calling perform right away */
@@ -130,7 +130,7 @@ int main(void)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
@@ -150,7 +150,7 @@ int main(void)
int idx, found = 0;
/* Find out which handle this message is about */
- for(idx=0; idx<HANDLECOUNT; idx++) {
+ for(idx = 0; idx<HANDLECOUNT; idx++) {
found = (msg->easy_handle == handles[idx]);
if(found)
break;
@@ -170,7 +170,7 @@ int main(void)
curl_multi_cleanup(multi_handle);
/* Free the CURL handles */
- for(i=0; i<HANDLECOUNT; i++)
+ for(i = 0; i<HANDLECOUNT; i++)
curl_easy_cleanup(handles[i]);
return 0;
diff --git a/docs/examples/multi-debugcallback.c b/docs/examples/multi-debugcallback.c
index 50c127b97..82ca5cb0f 100644
--- a/docs/examples/multi-debugcallback.c
+++ b/docs/examples/multi-debugcallback.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,7 +45,7 @@ void dump(const char *text,
size_t i;
size_t c;
- unsigned int width=0x10;
+ unsigned int width = 0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
@@ -54,30 +54,32 @@ void dump(const char *text,
fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
text, (long)size, (long)size);
- for(i=0; i<size; i+= width) {
+ for(i = 0; i<size; i += width) {
fprintf(stream, "%4.4lx: ", (long)i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
- if(i+c < size)
- fprintf(stream, "%02x ", ptr[i+c]);
+ if(i + c < size)
+ fprintf(stream, "%02x ", ptr[i + c]);
else
fputs(" ", stream);
}
- for(c = 0; (c < width) && (i+c < size); c++) {
+ for(c = 0; (c < width) && (i + c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
- if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
- i+=(c+2-width);
+ if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+ ptr[i + c + 1] == 0x0A) {
+ i += (c + 2 - width);
break;
}
fprintf(stream, "%c",
- (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+ (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
- if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
- i+=(c+3-width);
+ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+ ptr[i + c + 2] == 0x0A) {
+ i += (c + 3 - width);
break;
}
}
@@ -204,7 +206,7 @@ int main(void)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
diff --git a/docs/examples/multi-double.c b/docs/examples/multi-double.c
index dc6f23e68..c4b134d6c 100644
--- a/docs/examples/multi-double.c
+++ b/docs/examples/multi-double.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -119,7 +119,7 @@ int main(void)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
diff --git a/docs/examples/multi-formadd.c b/docs/examples/multi-formadd.c
new file mode 100644
index 000000000..bd85cc641
--- /dev/null
+++ b/docs/examples/multi-formadd.c
@@ -0,0 +1,171 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/* <DESC>
+ * using the multi interface to do a multipart formpost without blocking
+ * </DESC>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+
+ CURLM *multi_handle;
+ int still_running;
+
+ struct curl_httppost *formpost = NULL;
+ struct curl_httppost *lastptr = NULL;
+ struct curl_slist *headerlist = NULL;
+ static const char buf[] = "Expect:";
+
+ /* Fill in the file upload field. This makes libcurl load data from
+ the given file name when curl_easy_perform() is called. */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "sendfile",
+ CURLFORM_FILE, "postit2.c",
+ CURLFORM_END);
+
+ /* Fill in the filename field */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "filename",
+ CURLFORM_COPYCONTENTS, "postit2.c",
+ CURLFORM_END);
+
+ /* Fill in the submit field too, even if this is rarely needed */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "submit",
+ CURLFORM_COPYCONTENTS, "send",
+ CURLFORM_END);
+
+ curl = curl_easy_init();
+ multi_handle = curl_multi_init();
+
+ /* initialize custom header list (stating that Expect: 100-continue is not
+ wanted */
+ headerlist = curl_slist_append(headerlist, buf);
+ if(curl && multi_handle) {
+
+ /* what URL that receives this POST */
+ curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com/upload.cgi");
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+
+ curl_multi_add_handle(multi_handle, curl);
+
+ curl_multi_perform(multi_handle, &still_running);
+
+ do {
+ struct timeval timeout;
+ int rc; /* select() return code */
+ CURLMcode mc; /* curl_multi_fdset() return code */
+
+ fd_set fdread;
+ fd_set fdwrite;
+ fd_set fdexcep;
+ int maxfd = -1;
+
+ long curl_timeo = -1;
+
+ FD_ZERO(&fdread);
+ FD_ZERO(&fdwrite);
+ FD_ZERO(&fdexcep);
+
+ /* set a suitable timeout to play around with */
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ curl_multi_timeout(multi_handle, &curl_timeo);
+ if(curl_timeo >= 0) {
+ timeout.tv_sec = curl_timeo / 1000;
+ if(timeout.tv_sec > 1)
+ timeout.tv_sec = 1;
+ else
+ timeout.tv_usec = (curl_timeo % 1000) * 1000;
+ }
+
+ /* get file descriptors from the transfers */
+ mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+ if(mc != CURLM_OK) {
+ fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+ break;
+ }
+
+ /* On success the value of maxfd is guaranteed to be >= -1. We call
+ select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
+ no fds ready yet so we call select(0, ...) --or Sleep() on Windows--
+ to sleep 100ms, which is the minimum suggested value in the
+ curl_multi_fdset() doc. */
+
+ if(maxfd == -1) {
+#ifdef _WIN32
+ Sleep(100);
+ rc = 0;
+#else
+ /* Portable sleep for platforms other than Windows. */
+ struct timeval wait = { 0, 100 * 1000 }; /* 100ms */
+ rc = select(0, NULL, NULL, NULL, &wait);
+#endif
+ }
+ else {
+ /* Note that on some platforms 'timeout' may be modified by select().
+ If you need access to the original value save a copy beforehand. */
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+ }
+
+ switch(rc) {
+ case -1:
+ /* select error */
+ break;
+ case 0:
+ default:
+ /* timeout or readable/writable sockets */
+ printf("perform!\n");
+ curl_multi_perform(multi_handle, &still_running);
+ printf("running: %d!\n", still_running);
+ break;
+ }
+ } while(still_running);
+
+ curl_multi_cleanup(multi_handle);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+
+ /* then cleanup the formpost chain */
+ curl_formfree(formpost);
+
+ /* free slist */
+ curl_slist_free_all(headerlist);
+ }
+ return 0;
+}
diff --git a/docs/examples/multi-post.c b/docs/examples/multi-post.c
index d6c082cc7..a5df2d237 100644
--- a/docs/examples/multi-post.c
+++ b/docs/examples/multi-post.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,47 +37,43 @@ int main(void)
CURLM *multi_handle;
int still_running;
- struct curl_httppost *formpost=NULL;
- struct curl_httppost *lastptr=NULL;
- struct curl_slist *headerlist=NULL;
+ curl_mime *form = NULL;
+ curl_mimepart *field = NULL;
+ struct curl_slist *headerlist = NULL;
static const char buf[] = "Expect:";
- /* Fill in the file upload field. This makes libcurl load data from
- the given file name when curl_easy_perform() is called. */
- curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "sendfile",
- CURLFORM_FILE, "postit2.c",
- CURLFORM_END);
-
- /* Fill in the filename field */
- curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "filename",
- CURLFORM_COPYCONTENTS, "postit2.c",
- CURLFORM_END);
-
- /* Fill in the submit field too, even if this is rarely needed */
- curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "submit",
- CURLFORM_COPYCONTENTS, "send",
- CURLFORM_END);
-
curl = curl_easy_init();
multi_handle = curl_multi_init();
- /* initialize custom header list (stating that Expect: 100-continue is not
- wanted */
- headerlist = curl_slist_append(headerlist, buf);
if(curl && multi_handle) {
+ /* Create the form */
+ form = curl_mime_init(curl);
+
+ /* Fill in the file upload field */
+ field = curl_mime_addpart(form);
+ curl_mime_name(field, "sendfile");
+ curl_mime_filedata(field, "multi-post.c");
+
+ /* Fill in the filename field */
+ field = curl_mime_addpart(form);
+ curl_mime_name(field, "filename");
+ curl_mime_data(field, "multi-post.c", CURL_ZERO_TERMINATED);
+
+ /* Fill in the submit field too, even if this is rarely needed */
+ field = curl_mime_addpart(form);
+ curl_mime_name(field, "submit");
+ curl_mime_data(field, "send", CURL_ZERO_TERMINATED);
+
+ /* initialize custom header list (stating that Expect: 100-continue is not
+ wanted */
+ headerlist = curl_slist_append(headerlist, buf);
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com/upload.cgi");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
- curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+ curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
curl_multi_add_handle(multi_handle, curl);
@@ -139,7 +135,7 @@ int main(void)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
@@ -161,8 +157,8 @@ int main(void)
/* always cleanup */
curl_easy_cleanup(curl);
- /* then cleanup the formpost chain */
- curl_formfree(formpost);
+ /* then cleanup the form */
+ curl_mime_free(form);
/* free slist */
curl_slist_free_all(headerlist);
diff --git a/docs/examples/multithread.c b/docs/examples/multithread.c
index d3ea526dd..b0f0eb21d 100644
--- a/docs/examples/multithread.c
+++ b/docs/examples/multithread.c
@@ -74,7 +74,7 @@ int main(int argc, char **argv)
/* Must initialize libcurl before any threads are started */
curl_global_init(CURL_GLOBAL_ALL);
- for(i=0; i< NUMT; i++) {
+ for(i = 0; i< NUMT; i++) {
error = pthread_create(&tid[i],
NULL, /* default attributes please */
pull_one_url,
@@ -86,7 +86,7 @@ int main(int argc, char **argv)
}
/* now wait for all threads to terminate */
- for(i=0; i< NUMT; i++) {
+ for(i = 0; i< NUMT; i++) {
error = pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
}
diff --git a/docs/examples/opensslthreadlock.c b/docs/examples/opensslthreadlock.c
index 6f86c7f70..649ef93a9 100644
--- a/docs/examples/opensslthreadlock.c
+++ b/docs/examples/opensslthreadlock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,7 +50,7 @@ void handle_error(const char *file, int lineno, const char *msg)
}
/* This array will store all of the mutexes available to OpenSSL. */
-static MUTEX_TYPE *mutex_buf= NULL;
+static MUTEX_TYPE *mutex_buf = NULL;
static void locking_function(int mode, int n, const char *file, int line)
{
diff --git a/docs/examples/pop3-multi.c b/docs/examples/pop3-multi.c
index c95a37341..e86084394 100644
--- a/docs/examples/pop3-multi.c
+++ b/docs/examples/pop3-multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -144,7 +144,7 @@ int main(void)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
diff --git a/docs/examples/post-callback.c b/docs/examples/post-callback.c
index ad4d62b6b..324767bc1 100644
--- a/docs/examples/post-callback.c
+++ b/docs/examples/post-callback.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,36 +20,45 @@
*
***************************************************************************/
/* <DESC>
- * An example source code that issues a HTTP POST and we provide the actual
- * data through a read callback.
+ * Issue an HTTP POST and provide the data through the read callback.
* </DESC>
*/
#include <stdio.h>
#include <string.h>
#include <gnurl/curl.h>
-static const char data[]="this is what we post to the silly web server";
+/* silly test data to POST */
+static const char data[]="Lorem ipsum dolor sit amet, consectetur adipiscing "
+ "elit. Sed vel urna neque. Ut quis leo metus. Quisque eleifend, ex at "
+ "laoreet rhoncus, odio ipsum semper metus, at tempus ante urna in mauris. "
+ "Suspendisse ornare tempor venenatis. Ut dui neque, pellentesque a varius "
+ "eget, mattis vitae ligula. Fusce ut pharetra est. Ut ullamcorper mi ac "
+ "sollicitudin semper. Praesent sit amet tellus varius, posuere nulla non, "
+ "rhoncus ipsum.";
struct WriteThis {
const char *readptr;
- long sizeleft;
+ size_t sizeleft;
};
-static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
+static size_t read_callback(void *dest, size_t size, size_t nmemb, void *userp)
{
- struct WriteThis *pooh = (struct WriteThis *)userp;
-
- if(size*nmemb < 1)
- return 0;
-
- if(pooh->sizeleft) {
- *(char *)ptr = pooh->readptr[0]; /* copy one single byte */
- pooh->readptr++; /* advance pointer */
- pooh->sizeleft--; /* less data left */
- return 1; /* we return 1 byte at a time! */
+ struct WriteThis *wt = (struct WriteThis *)userp;
+ size_t buffer_size = size*nmemb;
+
+ if(wt->sizeleft) {
+ /* copy as much as possible from the source to the destination */
+ size_t copy_this_much = wt->sizeleft;
+ if(copy_this_much > buffer_size)
+ copy_this_much = buffer_size;
+ memcpy(dest, wt->readptr, copy_this_much);
+
+ wt->readptr += copy_this_much;
+ wt->sizeleft -= copy_this_much;
+ return copy_this_much; /* we copied this many bytes */
}
- return 0; /* no more data left to deliver */
+ return 0; /* no more data left to deliver */
}
int main(void)
@@ -57,10 +66,10 @@ int main(void)
CURL *curl;
CURLcode res;
- struct WriteThis pooh;
+ struct WriteThis wt;
- pooh.readptr = data;
- pooh.sizeleft = (long)strlen(data);
+ wt.readptr = data;
+ wt.sizeleft = strlen(data);
/* In windows, this will init the winsock stuff */
res = curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -75,7 +84,7 @@ int main(void)
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. */
- curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/index.cgi");
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/index.cgi");
/* Now specify we want to POST data */
curl_easy_setopt(curl, CURLOPT_POST, 1L);
@@ -84,7 +93,7 @@ int main(void)
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* pointer to pass to our read function */
- curl_easy_setopt(curl, CURLOPT_READDATA, &pooh);
+ curl_easy_setopt(curl, CURLOPT_READDATA, &wt);
/* get verbose debug output please */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
@@ -108,7 +117,7 @@ int main(void)
#else
/* Set the expected POST size. If you want to POST large amounts of data,
consider CURLOPT_POSTFIELDSIZE_LARGE */
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, pooh.sizeleft);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)wt.sizeleft);
#endif
#ifdef DISABLE_EXPECT
diff --git a/docs/examples/postinmemory.c b/docs/examples/postinmemory.c
index 8af16790f..5d32ef462 100644
--- a/docs/examples/postinmemory.c
+++ b/docs/examples/postinmemory.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -58,7 +58,7 @@ int main(void)
CURL *curl;
CURLcode res;
struct MemoryStruct chunk;
- static const char *postthis="Field=1&Field=2&Field=3";
+ static const char *postthis = "Field=1&Field=2&Field=3";
chunk.memory = malloc(1); /* will be grown as needed by realloc above */
chunk.size = 0; /* no data at this point */
diff --git a/docs/examples/postit2-formadd.c b/docs/examples/postit2-formadd.c
new file mode 100644
index 000000000..0ac09f259
--- /dev/null
+++ b/docs/examples/postit2-formadd.c
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/* <DESC>
+ * HTTP Multipart formpost with file upload and two additional parts.
+ * </DESC>
+ */
+/* Example code that uploads a file name 'foo' to a remote script that accepts
+ * "HTML form based" (as described in RFC1738) uploads using HTTP POST.
+ *
+ * The imaginary form we'll fill in looks like:
+ *
+ * <form method="post" enctype="multipart/form-data" action="examplepost.cgi">
+ * Enter file: <input type="file" name="sendfile" size="40">
+ * Enter file name: <input type="text" name="filename" size="30">
+ * <input type="submit" value="send" name="submit">
+ * </form>
+ *
+ * This exact source code has not been verified to work.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <curl/curl.h>
+
+int main(int argc, char *argv[])
+{
+ CURL *curl;
+ CURLcode res;
+
+ struct curl_httppost *formpost = NULL;
+ struct curl_httppost *lastptr = NULL;
+ struct curl_slist *headerlist = NULL;
+ static const char buf[] = "Expect:";
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ /* Fill in the file upload field */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "sendfile",
+ CURLFORM_FILE, "postit2.c",
+ CURLFORM_END);
+
+ /* Fill in the filename field */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "filename",
+ CURLFORM_COPYCONTENTS, "postit2.c",
+ CURLFORM_END);
+
+
+ /* Fill in the submit field too, even if this is rarely needed */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "submit",
+ CURLFORM_COPYCONTENTS, "send",
+ CURLFORM_END);
+
+ curl = curl_easy_init();
+ /* initialize custom header list (stating that Expect: 100-continue is not
+ wanted */
+ headerlist = curl_slist_append(headerlist, buf);
+ if(curl) {
+ /* what URL that receives this POST */
+ curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/examplepost.cgi");
+ if((argc == 2) && (!strcmp(argv[1], "noexpectheader")))
+ /* only disable 100-continue header if explicitly requested */
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+
+ /* then cleanup the formpost chain */
+ curl_formfree(formpost);
+ /* free slist */
+ curl_slist_free_all(headerlist);
+ }
+ return 0;
+}
diff --git a/docs/examples/postit2.c b/docs/examples/postit2.c
index b40743637..d357ecc2f 100644
--- a/docs/examples/postit2.c
+++ b/docs/examples/postit2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,46 +47,42 @@ int main(int argc, char *argv[])
CURL *curl;
CURLcode res;
- struct curl_httppost *formpost=NULL;
- struct curl_httppost *lastptr=NULL;
- struct curl_slist *headerlist=NULL;
+ curl_mime *form = NULL;
+ curl_mimepart *field = NULL;
+ struct curl_slist *headerlist = NULL;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
- /* Fill in the file upload field */
- curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "sendfile",
- CURLFORM_FILE, "postit2.c",
- CURLFORM_END);
+ curl = curl_easy_init();
+ if(curl) {
+ /* Create the form */
+ form = curl_mime_init(curl);
- /* Fill in the filename field */
- curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "filename",
- CURLFORM_COPYCONTENTS, "postit2.c",
- CURLFORM_END);
+ /* Fill in the file upload field */
+ field = curl_mime_addpart(form);
+ curl_mime_name(field, "sendfile");
+ curl_mime_filedata(field, "postit2.c");
+ /* Fill in the filename field */
+ field = curl_mime_addpart(form);
+ curl_mime_name(field, "filename");
+ curl_mime_data(field, "postit2.c", CURL_ZERO_TERMINATED);
- /* Fill in the submit field too, even if this is rarely needed */
- curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "submit",
- CURLFORM_COPYCONTENTS, "send",
- CURLFORM_END);
+ /* Fill in the submit field too, even if this is rarely needed */
+ field = curl_mime_addpart(form);
+ curl_mime_name(field, "submit");
+ curl_mime_data(field, "send", CURL_ZERO_TERMINATED);
- curl = curl_easy_init();
- /* initialize custom header list (stating that Expect: 100-continue is not
- wanted */
- headerlist = curl_slist_append(headerlist, buf);
- if(curl) {
+ /* initialize custom header list (stating that Expect: 100-continue is not
+ wanted */
+ headerlist = curl_slist_append(headerlist, buf);
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/examplepost.cgi");
if((argc == 2) && (!strcmp(argv[1], "noexpectheader")))
/* only disable 100-continue header if explicitly requested */
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
- curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+ curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
@@ -98,8 +94,8 @@ int main(int argc, char *argv[])
/* always cleanup */
curl_easy_cleanup(curl);
- /* then cleanup the formpost chain */
- curl_formfree(formpost);
+ /* then cleanup the form */
+ curl_mime_free(form);
/* free slist */
curl_slist_free_all(headerlist);
}
diff --git a/docs/examples/sendrecv.c b/docs/examples/sendrecv.c
index 015462974..1e7075e3c 100644
--- a/docs/examples/sendrecv.c
+++ b/docs/examples/sendrecv.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,7 +36,7 @@ static int wait_on_socket(curl_socket_t sockfd, int for_recv, long timeout_ms)
int res;
tv.tv_sec = timeout_ms / 1000;
- tv.tv_usec= (timeout_ms % 1000) * 1000;
+ tv.tv_usec = (timeout_ms % 1000) * 1000;
FD_ZERO(&infd);
FD_ZERO(&outfd);
diff --git a/docs/examples/sftpget.c b/docs/examples/sftpget.c
index 02adc878e..7d0aa4292 100644
--- a/docs/examples/sftpget.c
+++ b/docs/examples/sftpget.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -46,10 +46,10 @@ struct FtpFile {
static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
void *stream)
{
- struct FtpFile *out=(struct FtpFile *)stream;
+ struct FtpFile *out = (struct FtpFile *)stream;
if(out && !out->stream) {
/* open file for writing */
- out->stream=fopen(out->filename, "wb");
+ out->stream = fopen(out->filename, "wb");
if(!out->stream)
return -1; /* failure, can't open file to write */
}
@@ -61,7 +61,7 @@ int main(void)
{
CURL *curl;
CURLcode res;
- struct FtpFile ftpfile={
+ struct FtpFile ftpfile = {
"yourfile.bin", /* name to store the file as if successful */
NULL
};
diff --git a/docs/examples/simplepost.c b/docs/examples/simplepost.c
index 7e88f944b..613eacc39 100644
--- a/docs/examples/simplepost.c
+++ b/docs/examples/simplepost.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,7 +32,7 @@ int main(void)
CURL *curl;
CURLcode res;
- static const char *postthis="moo mooo moo moo";
+ static const char *postthis = "moo mooo moo moo";
curl = curl_easy_init();
if(curl) {
diff --git a/docs/examples/simplessl.c b/docs/examples/simplessl.c
index 036cd58a5..7b6a2b71b 100644
--- a/docs/examples/simplessl.c
+++ b/docs/examples/simplessl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -53,7 +53,7 @@ int main(void)
const char *pPassphrase = NULL;
static const char *pCertFile = "testcert.pem";
- static const char *pCACertFile="cacert.pem";
+ static const char *pCACertFile = "cacert.pem";
static const char *pHeaderFile = "dumpit";
const char *pKeyName;
diff --git a/docs/examples/smooth-gtk-thread.c b/docs/examples/smooth-gtk-thread.c
index 909f97605..54150aabb 100644
--- a/docs/examples/smooth-gtk-thread.c
+++ b/docs/examples/smooth-gtk-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -134,7 +134,7 @@ void *create_thread(void *progress_bar)
int error;
/* Make sure I don't create more threads than urls. */
- for(i=0; i < NUMT && i < num_urls ; i++) {
+ for(i = 0; i < NUMT && i < num_urls ; i++) {
error = pthread_create(&tid[i],
NULL, /* default attributes please */
pull_one_url,
@@ -146,7 +146,7 @@ void *create_thread(void *progress_bar)
}
/* Wait for all threads to terminate. */
- for(i=0; i < NUMT && i < num_urls; i++) {
+ for(i = 0; i < NUMT && i < num_urls; i++) {
error = pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
}
diff --git a/docs/examples/smtp-mail.c b/docs/examples/smtp-mail.c
index 77101dda8..6d209e64b 100644
--- a/docs/examples/smtp-mail.c
+++ b/docs/examples/smtp-mail.c
@@ -43,8 +43,8 @@
static const char *payload_text[] = {
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
"To: " TO "\r\n",
- "From: " FROM "(Example User)\r\n",
- "Cc: " CC "(Another example User)\r\n",
+ "From: " FROM " (Example User)\r\n",
+ "Cc: " CC " (Another example User)\r\n",
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n",
"Subject: SMTP example message\r\n",
diff --git a/docs/examples/smtp-mime.c b/docs/examples/smtp-mime.c
new file mode 100644
index 000000000..dcd867f68
--- /dev/null
+++ b/docs/examples/smtp-mime.c
@@ -0,0 +1,162 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* <DESC>
+ * SMTP example showing how to send mime e-mails
+ * </DESC>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <curl/curl.h>
+
+/* This is a simple example showing how to send mime mail using libcurl's SMTP
+ * capabilities. For an example of using the multi interface please see
+ * smtp-multi.c.
+ *
+ * Note that this example requires libcurl 7.56.0 or above.
+ */
+
+#define FROM "<sender@example.org>"
+#define TO "<addressee@example.net>"
+#define CC "<info@example.org>"
+
+static const char *headers_text[] = {
+ "Date: Tue, 22 Aug 2017 14:08:43 +0100",
+ "To: " TO,
+ "From: " FROM " (Example User)",
+ "Cc: " CC " (Another example User)",
+ "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
+ "rfcpedant.example.org>",
+ "Subject: example sending a MIME-formatted message",
+ NULL
+};
+
+static const char inline_text[] =
+ "This is the inline text message of the e-mail.\r\n"
+ "\r\n"
+ " It could be a lot of lines that would be displayed in an e-mail\r\n"
+ "viewer that is not able to handle HTML.\r\n";
+
+static const char inline_html[] =
+ "<html><body>\r\n"
+ "<p>This is the inline <b>HTML</b> message of the e-mail.</p>"
+ "<br />\r\n"
+ "<p>It could be a lot of HTML data that would be displayed by "
+ "e-mail viewers able to handle HTML.</p>"
+ "</body></html>\r\n";
+
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+ struct curl_slist *headers = NULL;
+ struct curl_slist *recipients = NULL;
+ struct curl_slist *slist = NULL;
+ curl_mime *mime;
+ curl_mime *alt;
+ curl_mimepart *part;
+ const char **cpp;
+
+ curl = curl_easy_init();
+ if(curl) {
+ /* This is the URL for your mailserver */
+ curl_easy_setopt(curl, CURLOPT_URL, "smtp://mail.example.com");
+
+ /* Note that this option isn't strictly required, omitting it will result
+ * in libcurl sending the MAIL FROM command with empty sender data. All
+ * autoresponses should have an empty reverse-path, and should be directed
+ * to the address in the reverse-path which triggered them. Otherwise,
+ * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more
+ * details.
+ */
+ curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
+
+ /* Add two recipients, in this particular case they correspond to the
+ * To: and Cc: addressees in the header, but they could be any kind of
+ * recipient. */
+ recipients = curl_slist_append(recipients, TO);
+ recipients = curl_slist_append(recipients, CC);
+ curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
+
+ /* Build and set the message header list. */
+ for(cpp = headers_text; *cpp; cpp++)
+ headers = curl_slist_append(headers, *cpp);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
+ /* Build the mime message. */
+ mime = curl_mime_init(curl);
+
+ /* The inline part is an alterative proposing the html and the text
+ versions of the e-mail. */
+ alt = curl_mime_init(curl);
+
+ /* HTML message. */
+ part = curl_mime_addpart(alt);
+ curl_mime_data(part, inline_html, CURL_ZERO_TERMINATED);
+ curl_mime_type(part, "text/html");
+
+ /* Text message. */
+ part = curl_mime_addpart(alt);
+ curl_mime_data(part, inline_text, CURL_ZERO_TERMINATED);
+
+ /* Create the inline part. */
+ part = curl_mime_addpart(mime);
+ curl_mime_subparts(part, alt);
+ curl_mime_type(part, "multipart/alternative");
+ slist = curl_slist_append(NULL, "Content-Disposition: inline");
+ curl_mime_headers(part, slist, 1);
+
+ /* Add the current source program as an attachment. */
+ part = curl_mime_addpart(mime);
+ curl_mime_filedata(part, "smtp-mime.c");
+ curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
+
+ /* Send the message */
+ res = curl_easy_perform(curl);
+
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* Free lists. */
+ curl_slist_free_all(recipients);
+ curl_slist_free_all(headers);
+
+ /* curl won't send the QUIT command until you call cleanup, so you should
+ * be able to re-use this connection for additional messages (setting
+ * CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and calling
+ * curl_easy_perform() again. It may not be a good idea to keep the
+ * connection open for a very long time though (more than a few minutes
+ * may result in the server timing out the connection), and you do want to
+ * clean up in the end.
+ */
+ curl_easy_cleanup(curl);
+
+ /* Free multipart message. */
+ curl_mime_free(mime);
+ }
+
+ return (int)res;
+}
diff --git a/docs/examples/smtp-multi.c b/docs/examples/smtp-multi.c
index c749092e5..a58f3282f 100644
--- a/docs/examples/smtp-multi.c
+++ b/docs/examples/smtp-multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,8 +44,8 @@
static const char *payload_text[] = {
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
"To: " TO "\r\n",
- "From: " FROM "(Example User)\r\n",
- "Cc: " CC "(Another example User)\r\n",
+ "From: " FROM " (Example User)\r\n",
+ "Cc: " CC " (Another example User)\r\n",
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n",
"Subject: SMTP multi example message\r\n",
@@ -211,7 +211,7 @@ int main(void)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
diff --git a/docs/examples/smtp-ssl.c b/docs/examples/smtp-ssl.c
index 838f01eec..dff450eea 100644
--- a/docs/examples/smtp-ssl.c
+++ b/docs/examples/smtp-ssl.c
@@ -44,8 +44,8 @@
static const char *payload_text[] = {
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
"To: " TO "\r\n",
- "From: " FROM "(Example User)\r\n",
- "Cc: " CC "(Another example User)\r\n",
+ "From: " FROM " (Example User)\r\n",
+ "Cc: " CC " (Another example User)\r\n",
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n",
"Subject: SMTP SSL example message\r\n",
diff --git a/docs/examples/smtp-tls.c b/docs/examples/smtp-tls.c
index 161b0292e..ffc0e504b 100644
--- a/docs/examples/smtp-tls.c
+++ b/docs/examples/smtp-tls.c
@@ -44,8 +44,8 @@
static const char *payload_text[] = {
"Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
"To: " TO "\r\n",
- "From: " FROM "(Example User)\r\n",
- "Cc: " CC "(Another example User)\r\n",
+ "From: " FROM " (Example User)\r\n",
+ "Cc: " CC " (Another example User)\r\n",
"Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
"rfcpedant.example.org>\r\n",
"Subject: SMTP TLS example message\r\n",
diff --git a/docs/examples/sslbackend.c b/docs/examples/sslbackend.c
new file mode 100644
index 000000000..1483dcc2e
--- /dev/null
+++ b/docs/examples/sslbackend.c
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Shows HTTPS usage with client certs and optional ssl engine use.
+ * </DESC>
+ */
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <curl/curl.h>
+
+/*
+ * An SSL-enabled libcurl is required for this sample to work (at least one
+ * SSL backend has to be configured).
+ *
+ * **** This example only works with libcurl 7.56.0 and later! ****
+*/
+
+int main(int argc, char **argv)
+{
+ const char *name = argc > 1 ? argv[1] : "openssl";
+ CURLsslset result;
+
+ if(!strcmp("list", name)) {
+ const curl_ssl_backend **list;
+ int i;
+
+ result = curl_global_sslset(-1, NULL, &list);
+ assert(result == CURLSSLSET_UNKNOWN_BACKEND);
+
+ for(i = 0; list[i]; i++)
+ printf("SSL backend #%d: '%s' (ID: %d)\n",
+ i, list[i]->name, list[i]->id);
+
+ return 0;
+ }
+ else if(isdigit(*name)) {
+ curl_sslbackend id = (curl_sslbackend)atoi(name);
+
+ result = curl_global_sslset(id, NULL, NULL);
+ }
+ else
+ result = curl_global_sslset(-1, name, NULL);
+
+ if(result == CURLSSLSET_UNKNOWN_BACKEND) {
+ fprintf(stderr, "Unknown SSL backend id: %s\n", name);
+ return 1;
+ }
+
+ assert(result == CURLSSLSET_OK);
+
+ printf("Version with SSL backend '%s':\n\n\t%s\n", name, curl_version());
+
+ return 0;
+}
diff --git a/docs/examples/synctime.c b/docs/examples/synctime.c
index d5ecc78a2..5d2c0dcb4 100644
--- a/docs/examples/synctime.c
+++ b/docs/examples/synctime.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -94,7 +94,7 @@
#define MAX_STRING 256
-#define MAX_STRING1 MAX_STRING+1
+#define MAX_STRING1 MAX_STRING + 1
#define SYNCTIME_UA "synctime/1.0"
@@ -158,9 +158,9 @@ size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, size_t nmemb,
if(RetVal == 7) {
SYSTime.wMilliseconds = 500; /* adjust to midpoint, 0.5 sec */
- for(i=0; i<12; i++) {
+ for(i = 0; i<12; i++) {
if(strcmp(MthStr[i], TmpStr2) == 0) {
- SYSTime.wMonth = i+1;
+ SYSTime.wMonth = i + 1;
break;
}
}
@@ -243,7 +243,7 @@ int conf_init(conf_t *conf)
int i;
*conf->http_proxy = 0;
- for(i=0; i<MAX_STRING1; i++)
+ for(i = 0; i<MAX_STRING1; i++)
conf->proxy_user[i] = 0; /* Clean up password from memory */
*conf->timeserver = 0;
return 1;
diff --git a/docs/examples/threaded-ssl.c b/docs/examples/threaded-ssl.c
index 30ba60727..280e1c1af 100644
--- a/docs/examples/threaded-ssl.c
+++ b/docs/examples/threaded-ssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,7 +25,7 @@
* </DESC>
*/
/* A multi-threaded example that uses pthreads and fetches 4 remote files at
- * once over HTTPS. The lock callbacks and stuff assume OpenSSL or GnuTLS
+ * once over HTTPS. The lock callbacks and stuff assume OpenSSL <1.1 or GnuTLS
* (libgcrypt) so far.
*
* OpenSSL docs for this:
@@ -63,7 +63,7 @@ static unsigned long thread_id(void)
{
unsigned long ret;
- ret=(unsigned long)pthread_self();
+ ret = (unsigned long)pthread_self();
return ret;
}
@@ -71,9 +71,9 @@ static void init_locks(void)
{
int i;
- lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
- sizeof(pthread_mutex_t));
- for(i=0; i<CRYPTO_num_locks(); i++) {
+ lockarray = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
+ sizeof(pthread_mutex_t));
+ for(i = 0; i<CRYPTO_num_locks(); i++) {
pthread_mutex_init(&(lockarray[i]), NULL);
}
@@ -86,7 +86,7 @@ static void kill_locks(void)
int i;
CRYPTO_set_locking_callback(NULL);
- for(i=0; i<CRYPTO_num_locks(); i++)
+ for(i = 0; i<CRYPTO_num_locks(); i++)
pthread_mutex_destroy(&(lockarray[i]));
OPENSSL_free(lockarray);
@@ -144,7 +144,7 @@ int main(int argc, char **argv)
init_locks();
- for(i=0; i< NUMT; i++) {
+ for(i = 0; i< NUMT; i++) {
error = pthread_create(&tid[i],
NULL, /* default attributes please */
pull_one_url,
@@ -156,7 +156,7 @@ int main(int argc, char **argv)
}
/* now wait for all threads to terminate */
- for(i=0; i< NUMT; i++) {
+ for(i = 0; i< NUMT; i++) {
error = pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
}
diff --git a/docs/examples/usercertinmem.c b/docs/examples/usercertinmem.c
index 6235ccfd1..47740dc65 100644
--- a/docs/examples/usercertinmem.c
+++ b/docs/examples/usercertinmem.c
@@ -200,7 +200,7 @@ int main(void)
/* first try: retrieve page without user certificate and key -> will fail
*/
rv = curl_easy_perform(ch);
- if(rv==CURLE_OK) {
+ if(rv == CURLE_OK) {
printf("*** transfer succeeded ***\n");
}
else {
@@ -213,7 +213,7 @@ int main(void)
*/
rv = curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
rv = curl_easy_perform(ch);
- if(rv==CURLE_OK) {
+ if(rv == CURLE_OK) {
printf("*** transfer succeeded ***\n");
}
else {
diff --git a/docs/libcurl/Makefile.inc b/docs/libcurl/Makefile.inc
index b4e49af9a..fc7a7472b 100644
--- a/docs/libcurl/Makefile.inc
+++ b/docs/libcurl/Makefile.inc
@@ -17,4 +17,8 @@ man_MANS = gnurl_easy_cleanup.3 gnurl_easy_getinfo.3 gnurl_easy_init.3 \
gnurl_multi_timeout.3 gnurl_formget.3 gnurl_multi_assign.3 \
gnurl_easy_pause.3 gnurl_easy_recv.3 gnurl_easy_send.3 \
gnurl_multi_socket_action.3 gnurl_multi_wait.3 libgnurl-symbols.3 \
- libgnurl-thread.3 gnurl_multi_socket_all.3
+ libgnurl-thread.3 gnurl_multi_socket_all.3 gnurl_global_sslset.3 \
+ gnurl_mime_init.3 gnurl_mime_free.3 gnurl_mime_addpart.3 gnurl_mime_name.3 \
+ gnurl_mime_data.3 gnurl_mime_data_cb.3 gnurl_mime_filedata.3 \
+ gnurl_mime_filename.3 gnurl_mime_subparts.3 \
+ gnurl_mime_type.3 gnurl_mime_headers.3 gnurl_mime_encoder.3
diff --git a/docs/libcurl/gnurl_easy_setopt.3 b/docs/libcurl/gnurl_easy_setopt.3
index f756852ba..cafcf0819 100644
--- a/docs/libcurl/gnurl_easy_setopt.3
+++ b/docs/libcurl/gnurl_easy_setopt.3
@@ -411,6 +411,8 @@ Size of file to send. \fICURLOPT_INFILESIZE(3)\fP
Size of file to send. \fICURLOPT_INFILESIZE_LARGE(3)\fP
.IP CURLOPT_UPLOAD
Upload data. See \fICURLOPT_UPLOAD(3)\fP
+.IP CURLOPT_MIMEPOST
+Post/send MIME data. See \fICURLOPT_MIMEPOST(3)\fP
.IP CURLOPT_MAXFILESIZE
Maximum file size to get. See \fICURLOPT_MAXFILESIZE(3)\fP
.IP CURLOPT_MAXFILESIZE_LARGE
@@ -547,6 +549,8 @@ Disable GSS-API delegation. See \fICURLOPT_GSSAPI_DELEGATION(3)\fP
.SH SSH OPTIONS
.IP CURLOPT_SSH_AUTH_TYPES
SSH authentication types. See \fICURLOPT_SSH_AUTH_TYPES(3)\fP
+.IP CURLOPT_SSH_COMPRESSION
+Enable SSH compression. See \fICURLOPT_SSH_COMPRESSION(3)\fP
.IP CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
MD5 of host's public key. See \fICURLOPT_SSH_HOST_PUBLIC_KEY_MD5(3)\fP
.IP CURLOPT_SSH_PUBLIC_KEYFILE
diff --git a/docs/libcurl/gnurl_formadd.3 b/docs/libcurl/gnurl_formadd.3
index e3ef58366..12604f1ae 100644
--- a/docs/libcurl/gnurl_formadd.3
+++ b/docs/libcurl/gnurl_formadd.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -29,6 +29,8 @@ curl_formadd - add a section to a multipart/formdata HTTP POST
.BI "struct curl_httppost ** " lastitem, " ...);"
.ad
.SH DESCRIPTION
+This function is deprecated. Do not use! See \fIcurl_mime_init(3)\fP instead!
+
curl_formadd() is used to append sections when building a multipart/formdata
HTTP POST (sometimes referred to as RFC2388-style posts). Append one section
at a time until you've added all the sections you want included and then you
@@ -60,16 +62,15 @@ parts.
.IP CURLFORM_COPYNAME
followed by a string which provides the \fIname\fP of this part. libcurl
copies the string so your application doesn't need to keep it around after
-this function call. If the name isn't NUL-terminated, or if you'd
-like it to contain zero bytes, you must set its length with
-\fBCURLFORM_NAMELENGTH\fP. The copied data will be freed by
-\fIcurl_formfree(3)\fP.
+this function call. If the name isn't NUL-terminated, you must set its length
+with \fBCURLFORM_NAMELENGTH\fP. The \fIname\fP is not allowed to contain
+zero-valued bytes. The copied data will be freed by \fIcurl_formfree(3)\fP.
.IP CURLFORM_PTRNAME
followed by a string which provides the \fIname\fP of this part. libcurl
will use the pointer and refer to the data in your application, so you
must make sure it remains until curl no longer needs it. If the name
-isn't NUL-terminated, or if you'd like it to contain zero
-bytes, you must set its length with \fBCURLFORM_NAMELENGTH\fP.
+isn't NUL-terminated, you must set its length with \fBCURLFORM_NAMELENGTH\fP.
+The \fIname\fP is not allowed to contain zero-valued bytes.
.IP CURLFORM_COPYCONTENTS
followed by a pointer to the contents of this part, the actual data
to send away. libcurl copies the provided data, so your application doesn't
@@ -169,6 +170,9 @@ the \fICURLOPT_HTTPPOST(3)\fP option), you must not free the list until after
you've called \fIcurl_easy_cleanup(3)\fP for the curl handle.
See example below.
+.SH AVAILABILITY
+Deprecated in 7.56.0. Before this release, field names were allowed to
+contain zero-valued bytes.
.SH RETURN VALUE
0 means everything was ok, non-zero means an error occurred corresponding
to a CURL_FORMADD_* constant defined in
@@ -254,5 +258,6 @@ to a CURL_FORMADD_* constant defined in
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
.SH "SEE ALSO"
-.BR curl_easy_setopt "(3), "
-.BR curl_formfree "(3)"
+.BR curl_easy_setopt "(3),"
+.BR curl_formfree "(3),"
+.BR curl_mime_init "(3)"
diff --git a/docs/libcurl/gnurl_formfree.3 b/docs/libcurl/gnurl_formfree.3
index 9c204ea93..80eabd3fd 100644
--- a/docs/libcurl/gnurl_formfree.3
+++ b/docs/libcurl/gnurl_formfree.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -28,6 +28,8 @@ curl_formfree - free a previously build multipart/formdata HTTP POST chain
.BI "void curl_formfree(struct curl_httppost *" form);
.ad
.SH DESCRIPTION
+This function is deprecated. Do not use! See \fIcurl_mime_init(3)\fP instead!
+
curl_formfree() is used to clean up data previously built/appended with
\fIcurl_formadd(3)\fP. This must be called when the data has been used, which
typically means after \fIcurl_easy_perform(3)\fP has been called.
@@ -38,7 +40,9 @@ the \fIcurl_formadd(3)\fP invoke(s).
\fBform\fP is the pointer as returned from a previous call to
\fIcurl_formadd(3)\fP and may be NULL.
+.SH AVAILABILITY
+Deprecated in 7.56.0.
.SH RETURN VALUE
None
.SH "SEE ALSO"
-.BR curl_formadd "(3) "
+.BR curl_formadd "(3), " curl_mime_init "(3), " curl_mime_free "(3)"
diff --git a/docs/libcurl/gnurl_formget.3 b/docs/libcurl/gnurl_formget.3
index d8ed80af1..f32ce2634 100644
--- a/docs/libcurl/gnurl_formget.3
+++ b/docs/libcurl/gnurl_formget.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -65,6 +65,7 @@ request as only then will libcurl get the actual read callback to use!
return total_size;
}
.SH AVAILABILITY
-This function was added in libcurl 7.15.5
+This function was added in libcurl 7.15.5. The form API is deprecated in
+libcurl 7.56.0.
.SH "SEE ALSO"
-.BR curl_formadd "(3) "
+.BR curl_formadd "(3), " curl_mime_init "(3)"
diff --git a/docs/libcurl/gnurl_global_init.3 b/docs/libcurl/gnurl_global_init.3
index daa8a3c8b..2d32e6474 100644
--- a/docs/libcurl/gnurl_global_init.3
+++ b/docs/libcurl/gnurl_global_init.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -93,5 +93,6 @@ other curl functions.
.SH "SEE ALSO"
.BR curl_global_init_mem "(3), "
.BR curl_global_cleanup "(3), "
+.BR curl_global_sslset "(3), "
.BR curl_easy_init "(3) "
.BR libcurl "(3) "
diff --git a/docs/libcurl/gnurl_global_sslset.3 b/docs/libcurl/gnurl_global_sslset.3
new file mode 100644
index 000000000..cee84458f
--- /dev/null
+++ b/docs/libcurl/gnurl_global_sslset.3
@@ -0,0 +1,97 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_global_sslset 3 "15 July 2017" "libcurl 7.56" "libcurl Manual"
+.SH NAME
+curl_global_sslset - Select SSL backend to use with libcurl
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.nf
+
+typedef struct {
+ curl_sslbackend id;
+ const char *name;
+} curl_ssl_backend;
+
+typedef enum {
+ CURLSSLBACKEND_NONE = 0,
+ CURLSSLBACKEND_OPENSSL = 1,
+ CURLSSLBACKEND_GNUTLS = 2,
+ CURLSSLBACKEND_NSS = 3,
+ CURLSSLBACKEND_GSKIT = 5,
+ CURLSSLBACKEND_POLARSSL = 6,
+ CURLSSLBACKEND_WOLFSSL = 7,
+ CURLSSLBACKEND_SCHANNEL = 8,
+ CURLSSLBACKEND_DARWINSSL = 9,
+ CURLSSLBACKEND_AXTLS = 10,
+ CURLSSLBACKEND_MBEDTLS = 11
+} curl_sslbackend;
+
+.B "CURLsslset curl_global_sslset(curl_sslbackend " id,
+.B " const char *" name,
+.B " curl_ssl_backend ***" avail ");"
+.fi
+.SH DESCRIPTION
+This function configures at runtime which SSL backend to use with
+libcurl. This function can only be used to select an SSL backend once, and it
+must be called \fBbefore\fP \fIcurl_global_init(3)\fP.
+
+The backend can be identified by the \fIid\fP
+(e.g. \fBCURLSSLBACKEND_OPENSSL\fP). The backend can also be specified via the
+\fIname\fP parameter for a case insensitive match (passing -1 as \fIid\fP). If
+both \fIid\fP and \fIname\fP are specified, the \fIname\fP will be ignored.
+
+If neither \fIid\fP nor \fPname\fP are specified, the function will fail with
+CURLSSLSET_UNKNOWN_BACKEND and set the \fIavail\fP pointer to the
+NULL-terminated list of available backends. The available backends are those
+that this particular build of libcurl supports.
+
+Upon success, the function returns CURLSSLSET_OK.
+
+If the specified SSL backend is not available, the function returns
+CURLSSLSET_UNKNOWN_BACKEND and sets the \fIavail\fP pointer to a
+NULL-terminated list of available SSL backends. In this case, you may call the
+function again to try to select a different backend.
+
+The SSL backend can be set only once. If it has already been set, a subsequent
+attempt to change it will result in a \fBCURLSSLSET_TOO_LATE\fP.
+
+\fBThis function is not thread safe.\fP You must not call it when any other
+thread in the program (i.e. a thread sharing the same memory) is running.
+This doesn't just mean no other thread that is using libcurl.
+
+.SH AVAILABILITY
+This function was added in libcurl 7.56.0. Before this version, there was no
+support for choosing SSL backends at runtime.
+.SH RETURN VALUE
+If this function returns CURLSSLSET_OK, the backend was successfully selected.
+
+If the chosen backend is unknown (or support for the chosed backend has not
+been compiled into libcurl), the function returns \fICURLSSLSET_UNKNOWN_BACKEND\fP.
+
+If the backend had been configured previously, or if \fIcurl_global_init(3)\fP
+has already been called, the function returns \fICURLSSLSET_TOO_LATE\fP.
+
+If this libcurl was built completely without SSL support, with no backends at
+all, this function returns \fICURLSSLSET_NO_BACKENDS\fP.
+.SH "SEE ALSO"
+.BR curl_global_init "(3), "
+.BR libcurl "(3) "
diff --git a/docs/libcurl/gnurl_mime_addpart.3 b/docs/libcurl/gnurl_mime_addpart.3
new file mode 100644
index 000000000..22350668a
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_addpart.3
@@ -0,0 +1,66 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_addpart 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_addpart - append a new empty part to a mime structure
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "curl_mimepart * curl_mime_addpart(curl_mime * " mime ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_addpart(3)\fP creates and appends a new empty part to the given
+mime structure and returns a handle to it. The returned part handle can
+subsequently be populated using functions from the mime API.
+
+\fImime\fP is the handle of the mime structure in which the new part must be
+appended.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+A mime part structure handle, or NULL upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* continue and set name + data to the part */
+ curl_mime_data(part, "This is the field data", CURL_ZERO_TERMINATED);
+ curl_mime_name(part, "data");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_init "(3),"
+.BR curl_mime_name "(3),"
+.BR curl_mime_data "(3),"
+.BR curl_mime_data_cb "(3),"
+.BR curl_mime_filedata "(3),"
+.BR curl_mime_filename "(3),"
+.BR curl_mime_subparts "(3),"
+.BR curl_mime_type "(3),"
+.BR curl_mime_headers "(3),"
+.BR curl_mime_encoder "(3)"
diff --git a/docs/libcurl/gnurl_mime_data.3 b/docs/libcurl/gnurl_mime_data.3
new file mode 100644
index 000000000..d2112f2d4
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_data.3
@@ -0,0 +1,69 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_data 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_data - set a mime part's body data from memory
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_data(curl_mimepart * " part ", const char * " data
+.BI ", size_t " datasize ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_data(3)\fP sets a mime part's body content from memory data.
+
+\fIdata\fP points to the data bytes: those are copied to the part and their
+storage may safely be reused after call.
+\fIdatasize\fP is the number of data bytes: it can be set to
+\fICURL_ZERO_TERMINATED\fP to indicate \fIdata\fP is a nul-terminated
+character string.
+\fIpart\fP is the part's to assign contents to.
+
+Setting a part's contents twice is valid: only the value set by the last call
+is retained. It is possible to unassign part's contents by setting
+\fIdata\fP to NULL.
+
+Setting very large data is memory consuming: one might consider using
+\fIcurl_mime_data_cb(3)\fP in such a case.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* add data to the part */
+ curl_mime_data(part, "raw contents to send", CURL_ZERO_TERMINATED);
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_data_cb "(3),"
+.BR curl_mime_name "(3),"
+.BR curl_mime_type "(3)"
diff --git a/docs/libcurl/gnurl_mime_data_cb.3 b/docs/libcurl/gnurl_mime_data_cb.3
new file mode 100644
index 000000000..bc74a85a5
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_data_cb.3
@@ -0,0 +1,160 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_data_cb 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_data_cb - set a callback-based data source for a mime part's body
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+size_t readfunc(char *buffer, size_t size, size_t nitems, void *arg);
+.br
+int seekfunc(void *arg, curl_off_t offset, int origin);
+.br
+void freefunc(void *arg);
+.sp
+.BI "CURLcode curl_mime_data(curl_mimepart * " part ", curl_off_t " datasize ,
+.br
+.BI " curl_read_callback " readfunc ", curl_seek_callback " seekfunc ,
+.br
+.BI " curl_free_callback " freefunc ", void * " arg ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_data_cb(3)\fP sets the data source of a mime part's body content
+from a data read callback function.
+
+\fIpart\fP is the part's to assign contents to.
+
+\fIreadfunc\fP is a pointer to a data read callback function, with a signature
+as shown by the above prototype. It may not be set to NULL.
+
+\fIseekfunc\fP is a pointer to a seek callback function, with a signature as
+shown by the above prototype. This function will be used upon resending data
+(i.e.: after a redirect); this pointer may be set to NULL, in which case a
+resend is not possible.
+
+\fIfreefunc\fP is a pointer to a user resource freeing callback function, with
+a signature as shown by the above prototype. If no resource is to be freed, it
+may safely be set to NULL. This function will be called upon mime structure
+freeing.
+
+\fIarg\fP is a user defined argument to callback functions.
+
+The read callback function gets called by libcurl as soon as it needs to
+read data in order to send it to the peer - like if you ask it to upload or
+post data to the server. The data area pointed at by the pointer \fIbuffer\fP
+should be filled up with at most \fIsize\fP multiplied with \fInmemb\fP number
+of bytes by your function.
+
+Your read function must then return the actual number of bytes that it stored
+in that memory area. Returning 0 will signal end-of-file to the library and
+cause it to stop the current transfer.
+
+If you stop the current transfer by returning 0 "pre-maturely" (i.e before the
+server expected it, like when you've said you will upload N bytes and you
+upload less than N bytes), you may experience that the server "hangs" waiting
+for the rest of the data that won't come.
+
+The read callback may return \fICURL_READFUNC_ABORT\fP to stop the current
+operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error
+code from the transfer.
+
+The callback can return \fICURL_READFUNC_PAUSE\fP to cause reading from this
+connection to pause. See \fIcurl_easy_pause(3)\fP for further details.
+
+The seek function gets called by libcurl to rewind input stream data or to
+seek to a certain position. The function shall work like fseek(3) or lseek(3)
+and it gets SEEK_SET, SEEK_CUR or SEEK_END as argument for \fIorigin\fP,
+although libcurl currently only passes SEEK_SET.
+
+The callback function must return \fICURL_SEEKFUNC_OK\fP on success,
+\fICURL_SEEKFUNC_FAIL\fP to cause the upload operation to fail or
+\fICURL_SEEKFUNC_CANTSEEK\fP to indicate that while the seek failed, libcurl
+is free to work around the problem if possible. The latter can sometimes be
+done by instead reading from the input or similar.
+
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+Sending a huge data string will cause the same amount of memory to be
+allocated: to avoid overhead resources consumption, one might want to use a
+callback source to avoid data duplication. In this case, original data
+must be retained until after the transfer terminates.
+.nf
+
+char hugedata[512000];
+
+struct ctl {
+ char *buffer;
+ curl_off_t size;
+ curl_off_t position;
+};
+
+size_t read_callback(char *buffer, size_t size, size_t nitems, void *arg)
+{
+ struct ctl *p = (struct ctl *) arg;
+ curl_off_t sz = p->size - p->position;
+
+ nitems *= size;
+ if(sz > nitems)
+ sz = nitems;
+ if(sz)
+ memcpy(buffer, p->buffer + p->position, sz);
+ p->position += sz;
+ return sz;
+}
+
+int seek_callback(void *arg, curl_off_t offset, int origin)
+{
+ struct ctl *p = (struct ctl *) arg;
+
+ switch(origin) {
+ case SEEK_END:
+ offset += p->size;
+ break;
+ case SEEK_CUR:
+ offset += p->position;
+ break;
+ }
+
+ if(offset < 0)
+ return CURL_SEEKFUNC_FAIL;
+ p->position = offset;
+ return CURL_SEEKFUNC_OK;
+}
+
+ CURL *easy = curl_easy_init();
+ curl_mime *mime = curl_mime_init(easy);
+ curl_mimepart *part = curl_mime_addpart(mime);
+ struct ctl hugectl;
+
+ hugectl.buffer = hugedata;
+ hugectl.size = sizeof hugedata;
+ hugectl.position = 0;
+ curl_mime_data_cb(part, hugectl.size, read_callback, seek_callback, NULL,
+ &hugectl);
+
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_data "(3),"
+.BR curl_mime_name "(3)"
diff --git a/docs/libcurl/gnurl_mime_encoder.3 b/docs/libcurl/gnurl_mime_encoder.3
new file mode 100644
index 000000000..c17cf25b3
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_encoder.3
@@ -0,0 +1,97 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_encoder 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_encoder - set a mime part's encoder and content transfer encoding
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_encoder(curl_mimepart * " part ,
+.BI "const char * " encoding ");"
+.ad
+.SH DESCRIPTION
+curl_mime_encoder() requests a mime part's content to be encoded before being
+transmitted.
+
+\fIpart\fP is the part's handle to assign an encoder.
+\fIencoding\fP is a pointer to a zero-terminated encoding scheme. It may be
+set to NULL to disable an encoder previously attached to the part. The encoding
+scheme storage may safely be reused after this function returns.
+
+Setting a part's encoder twice is valid: only the value set by the last call is
+retained.
+
+Upon multipart rendering, the part's content is encoded according to the
+pertaining scheme and a corresponding \fIContent-Transfer-Encoding"\fP header
+is added to the part.
+
+Supported encoding schemes are:
+.br
+"\fIbinary\fP": the data is left unchanged, the header is added.
+.br
+"\fI8bit\fP": header added, no data change.
+.br
+"\fI7bit\fP": the data is unchanged, but is each byte is checked
+to be a 7-bit value; if not, a read error occurs.
+.br
+"\fIbase64\fP": Data is converted to base64 encoding, then split in
+CRLF-terminated lines of at most 76 characters.
+.br
+"\fIquoted-printable\fP": data is encoded in quoted printable lines of
+at most 76 characters. Since the resulting size of the final data cannot be
+determined prior to reading the original data, it is left as unknown, causing
+chunked transfer in HTTP. For the same reason, this encoder may not be used
+with IMAP. This encoder targets text data that is mostly ASCII and should
+not be used with other types of data.
+
+If the original data is already encoded in such a scheme, a custom
+\fIContent-Transfer-Encoding\fP header should be added with
+\FIcurl_mime_headers\fP() instead of setting a part encoder.
+
+Encoding should not be applied to multiparts, thus the use of this
+function on a part with content set with \fIcurl_mime_subparts\fP() is
+strongly discouraged.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send a file */
+ curl_mime_filedata(part, "image.png");
+
+ /* encode file data in base64 for transfer */
+ curl_mime_encoder(part, "base64");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_headers "(3),"
+.BR curl_mime_subparts "(3)"
diff --git a/docs/libcurl/gnurl_mime_filedata.3 b/docs/libcurl/gnurl_mime_filedata.3
new file mode 100644
index 000000000..9a57068de
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_filedata.3
@@ -0,0 +1,77 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_filedata 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_filedata - set a mime part's body data from a file contents
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_filedata(curl_mimepart * " part ,
+.BI " const char * " filename ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_filedata(3)\fP sets a mime part's body content from the named
+file's contents. This is an alernative to \fIcurl_mime_data(3)\fP for setting
+data to a mime part.
+
+\fIpart\fP is the part's to assign contents to.
+
+\fIfilename\fP points to the nul-terminated file's path name. The pointer can
+be NULL to detach previous part contents settings. Filename storage can be
+safely be reused after this call.
+
+As a side effect, the part's remote file name is set to the base name of the
+given \fIfilename\fP if it is a valid named file. This can be undone or
+overriden by a subsequent call to \fIcurl_mime_filename(3)\fP.
+
+The contents of the file is read during the file transfer in a streaming
+manner to allow huge files to get transfered without using much memory. It
+therefore requires that the file is kept intact during the entire request.
+
+Setting a part's contents twice is valid: only the value set by the last call
+is retained.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send data from this file */
+ curl_mime_filedata(part, "image.png");
+
+ /* set name */
+ curl_mime_name(part, "data");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_data "(3),"
+.BR curl_mime_filename "(3),"
+.BR curl_mime_name "(3)"
diff --git a/docs/libcurl/gnurl_mime_filename.3 b/docs/libcurl/gnurl_mime_filename.3
new file mode 100644
index 000000000..42916e598
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_filename.3
@@ -0,0 +1,72 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_filename 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_filename - set a mime part's remote file name
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_filename(curl_mimepart * " part ,
+.BI "const char * " filename ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_filename(3)\fP sets a mime part's remote file name. When remote
+file name is set, content data is processed as a file, whatever is the part's
+content source. A part's remote file name is transmitted to the server in the
+associated Content-Disposition generated header.
+
+\fIpart\fP is the part's handle to assign the remote file name to.
+
+\fIfilename\fP points to the nul-terminated file name string; it may be set to
+NULL to remove a previously attached remote file name.
+
+The remote file name string is copied into the part, thus the associated
+storage may safely be released or reused after call. Setting a part's file
+name twice is valid: only the value set by the last call is retained.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send image data from memory */
+ curl_mime_data(part, imagebuf, imagebuf_len);
+
+ /* set a file name to make it look like a file upload */
+ curl_mime_filename(part, "image.png");
+
+ /* set name */
+ curl_mime_name(part, "data");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_filedata "(3),"
+.BR curl_mime_data "(3)"
diff --git a/docs/libcurl/gnurl_mime_free.3 b/docs/libcurl/gnurl_mime_free.3
new file mode 100644
index 000000000..9394b5748
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_free.3
@@ -0,0 +1,48 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_free 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_free - free a previously built mime structure
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "void curl_mime_free(curl_mime *" mime);
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_free(3)\fP is used to clean up data previously built/appended
+with \fIcurl_mime_addpart(3)\fP and other mime-handling functions. This must
+be called when the data has been used, which typically means after
+\fIcurl_easy_perform(3)\fP has been called.
+
+The handle to free is the one you passed to
+the \fICURLOPT_MIMEPOST(3)\fP option: attached subparts mime structures must
+not be explicitly freed as they are by the top structure freeing.
+
+\fBmime\fP is the handle as returned from a previous call to
+\fIcurl_mime_init(3)\fP and may be NULL.
+
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+None
+.SH "SEE ALSO"
+.BR curl_mime_init "(3)"
diff --git a/docs/libcurl/gnurl_mime_headers.3 b/docs/libcurl/gnurl_mime_headers.3
new file mode 100644
index 000000000..1d02e1ee5
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_headers.3
@@ -0,0 +1,65 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_headers 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_headers - set a mime part's custom headers
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_headers(curl_mimepart * " part ,
+.BI "struct curl_slist * " headers ", int " take_ownership ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_headers(3)\fP sets a mime part's custom headers.
+
+\fIpart\fP is the part's handle to assign the custom headers list to.
+
+\fIheaders\fP is the head of a list of custom headers; it may be set to NULL
+to remove a previously attached custom header list.
+
+\fItake_ownership\fP: when non-zero, causes the list to be freed upon
+replacement or mime structure deletion; in this case the list must not be
+freed explicitly.
+
+Setting a part's custom headers list twice is valid: only the value set by
+the last call is retained.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ struct curl_slist *headers = NULL;
+
+ headers = curl_slist_append("Custom-Header: mooo", headers);
+
+ /* use these headers, please take ownership */
+ curl_mime_headers(part, headers, TRUE);
+
+ /* pass on this data */
+ curl_mime_data(part, "12345679", CURL_ZERO_TERMINATED);
+
+ /* set name */
+ curl_mime_name(part, "numbers");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3)"
diff --git a/docs/libcurl/gnurl_mime_init.3 b/docs/libcurl/gnurl_mime_init.3
new file mode 100644
index 000000000..469f02b7c
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_init.3
@@ -0,0 +1,69 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_init 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_init - create a mime handle
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "curl_mime * curl_mime_init(CURL * " easy_handle ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_init(3)\fP creates a handle to a new empty mime structure
+intended to be used with \fIeasy_handle\fP. This mime structure can be
+subsequently filled using the mime API, then attached to \fIeasy_handle\fP
+using option \fICURLOPT_MIMEPOST(3)\fP within a \fIcurl_easy_setopt(3)\fP
+call.
+
+Using a mime handle is the recommended way to post an HTTP form, format and
+send a multi-part e-mail with SMTP or upload such an e-mail to an IMAP server.
+
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+A mime struct handle, or NULL upon failure.
+.SH EXAMPLE
+.nf
+
+ CURL *easy = curl_easy_init();
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* Build an HTTP form with a single field named "data", */
+ mime = curl_mime_init(easy);
+ part = curl_mime_addpart(mime);
+ curl_mime_data(part, "This is the field data", CURL_ZERO_TERMINATED);
+ curl_mime_name(part, "data");
+
+ /* Post and send it. */
+ curl_easy_setopt(easy, CURLOPT_MIMEPOST, mime);
+ curl_easy_setopt(easy, CURLOPT_URL, "http://example.com");
+ curl_easy_perform(easy);
+
+ /* Clean-up. */
+ curl_easy_cleanup(easy);
+ curl_mime_free(mime);
+
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_free "(3),"
+.BR CURLOPT_MIMEPOST "(3)"
diff --git a/docs/libcurl/gnurl_mime_name.3 b/docs/libcurl/gnurl_mime_name.3
new file mode 100644
index 000000000..f821d9082
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_name.3
@@ -0,0 +1,63 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_name 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_name - set a mime part's name
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_name(curl_mimepart * " part ", const char * " name ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_name(3)\fP sets a mime part's name. This is the way HTTP form
+fields are named.
+
+\fIpart\fP is the part's handle to assign a name to.
+
+\fIname\fP points to the zero-terminated name string.
+
+The name string is copied into the part, thus the associated storage may
+safely be released or reused after call. Setting a part's name twice is valid:
+only the value set by the last call is retained. It is possible to "unname" a
+part by setting \fIname\fP to NULL.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* give the part a name */
+ curl_mime_name(part, "shoe_size");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_data "(3),"
+.BR curl_mime_type "(3)"
diff --git a/docs/libcurl/gnurl_mime_subparts.3 b/docs/libcurl/gnurl_mime_subparts.3
new file mode 100644
index 000000000..d5d46febb
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_subparts.3
@@ -0,0 +1,53 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_subparts 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_subparts - set subparts of a multipart mime part
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_subparts(curl_mimepart * " part ,
+.BI "curl_mime * " subparts ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_subparts(3)\fP sets a multipart mime part's content from a mime
+structure.
+
+\fIpart\fP is a handle to the multipart part.
+
+\fIsubparts\fP is a mime structure handle holding the subparts. After
+\fIcurl_mime_subparts\fP succeeds, the mime structure handle belongs to the
+multipart part and must not be freed explicitly. It may however be updated by
+subsequent calls to mime API functions.
+
+Setting a part's contents twice is valid: only the value set by the last call
+is retained. It is possible to unassign previous part's contents by setting
+\fIsubparts\fP to NULL.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+TODO
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_init "(3)"
diff --git a/docs/libcurl/gnurl_mime_type.3 b/docs/libcurl/gnurl_mime_type.3
new file mode 100644
index 000000000..59841d5bd
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_type.3
@@ -0,0 +1,83 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.TH curl_mime_type 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_type - set a mime part's content type
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_type(curl_mimepart * " part ,
+.BI "const char * " mimetype ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_type(3)\fP sets a mime part's content type.
+
+\fIpart\fP is the part's handle to assign the content type to.
+
+\fImimetype\fP points to the nul-terminated file mime type string; it may be
+set to NULL to remove a previously attached mime type.
+
+The mime type string is copied into the part, thus the associated storage may
+safely be released or reused after call. Setting a part's type twice is valid:
+only the value set by the last call is retained.
+
+In the absence of a mime type and if needed by the protocol specifications,
+a default mime type is determined by the context:
+.br
+- If set as a custom header, use this value.
+.br
+- application/form-data for a HTTP form post.
+.br
+- If a remote file name is set, the mime type is taken from the file name
+extension, or application/octet-stream by default.
+.br
+- For a multipart part, multipart/mixed.
+.br
+- text/plain in other cases.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* get data from this file */
+ curl_mime_filedata(part, "image.png");
+
+ /* content-type for this part */
+ curl_mime_type(part, "image/png");
+
+ /* set name */
+ curl_mime_name(part, "image");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_name "(3),"
+.BR curl_mime_data "(3)"
diff --git a/docs/libcurl/gnurl_version_info.3 b/docs/libcurl/gnurl_version_info.3
index fb590f954..35d7f4522 100644
--- a/docs/libcurl/gnurl_version_info.3
+++ b/docs/libcurl/gnurl_version_info.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -156,6 +156,10 @@ libcurl ignore cookies with a domain that's on the list.
.IP CURL_VERSION_HTTPS_PROXY
libcurl was built with support for HTTPS-proxy.
(Added in 7.52.0)
+.IP CURL_VERSION_MULTI_SSL
+libcurl was built with multiple SSL backends. For details, see
+\fIcurl_global_sslset(3)\fP.
+(Added in 7.56.0)
.RE
\fIssl_version\fP is an ASCII string for the OpenSSL version used. If libcurl
has no SSL support, this is NULL.
diff --git a/docs/libcurl/libgnurl-tutorial.3 b/docs/libcurl/libgnurl-tutorial.3
index cbfb081dc..187d5ca0f 100644
--- a/docs/libcurl/libgnurl-tutorial.3
+++ b/docs/libcurl/libgnurl-tutorial.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -477,14 +477,67 @@ multi-part because they're built by a chain of parts, each part being a single
unit of data. Each part has its own name and contents. You can in fact create
and post a multi-part formpost with the regular libcurl POST support described
above, but that would require that you build a formpost yourself and provide
-to libcurl. To make that easier, libcurl provides \fIcurl_formadd(3)\fP. Using
-this function, you add parts to the form. When you're done adding parts, you
-post the whole form.
+to libcurl. To make that easier, libcurl provides a MIME API consisting in
+several functions: using those, you can create and fill a multi-part form.
+Function \fIcurl_mime_init(3)\fP creates a multi-part body; you can then
+append new parts to a multi-part body using \fIcurl_mime_addpart(3)\fP.
+There are three possible data sources for a part: memory using
+\fIcurl_mime_data(3)\fP, file using \fIcurl_mime_filedata(3)\fP and
+user-defined data read callback using \fIcurl_mime_data_cb(3)\fP.
+\fIcurl_mime_name(3)\fP sets a part's (i.e.: form field) name, while
+\fIcurl_mime_filename(3)\fP fills in the remote file name. With
+\fIcurl_mime_type(3)\fP, you can tell the MIME type of a part,
+\fIcurl_mime_headers(3)\fP allows defining the part's headers. When a
+multi-part body is no longer needed, you can destroy it using
+\fIcurl_mime_free(3)\fP.
The following example sets two simple text parts with plain textual contents,
and then a file with binary contents and uploads the whole thing.
.nf
+ curl_mime *multipart = curl_mime_init(easyhandle);
+ curl_mimepart *part = curl_mime_addpart(mutipart);
+ curl_mime_name(part, "name");
+ curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(mutipart);
+ curl_mime_name(part, "project");
+ curl_mime_data(part, "curl", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(mutipart);
+ curl_mime_name(part, "logotype-image");
+ curl_mime_filedata(part, "curl.png");
+
+ /* Set the form info */
+ curl_easy_setopt(easyhandle, CURLOPT_MIMEPOST, multipart);
+
+ curl_easy_perform(easyhandle); /* post away! */
+
+ /* free the post data again */
+ curl_mime_free(multipart);
+.fi
+
+To post multiple files for a single form field, you must supply each file in
+a separate part, all with the same field name. Although function
+\fIcurl_mime_subparts(3)\fP implements nested muti-parts, this way of
+multiple files posting is deprecated by RFC 7578, chapter 4.3.
+
+To set the data source from an already opened FILE pointer, use:
+
+.nf
+ curl_mime_data_cb(part, filesize, (curl_read_callback) fread,
+ (curl_seek_callback) fseek, NULL, filepointer);
+.fi
+
+A deprecated \fIcurl_formadd(3)\fP function is still supported in libcurl.
+It should however not be used anymore for new designs and programs using it
+ought to be converted to the MIME API. It is however described here as an
+aid to conversion.
+
+Using \fIcurl_formadd\fP, you add parts to the form. When you're done adding
+parts, you post the whole form.
+
+The MIME API example above is expressed as follows using this function:
+
+.nf
struct curl_httppost *post=NULL;
struct curl_httppost *last=NULL;
curl_formadd(&post, &last,
@@ -542,6 +595,136 @@ request. You force an easyhandle to go back to GET by using the
Just setting \fICURLOPT_POSTFIELDS(3)\fP to "" or NULL will *not* stop libcurl
from doing a POST. It will just make it POST without any data to send!
+.SH "Converting from deprecated form API to MIME API"
+Four rules have to be respected in building the multi-part:
+.br
+- The easy handle must be created before building the multi-part.
+.br
+- The multi-part is always created by a call to curl_mime_init(easyhandle).
+.br
+- Each part is created by a call to curl_mime_addpart(multipart).
+.br
+- When complete, the multi-part must be bound to the easy handle using
+\fICURLOPT_MIMEPOST(3)\fP instead of \fICURLOPT_HTTPPOST(3)\fP.
+
+Here are some example of \fIcurl_formadd\fP calls to MIME API sequences:
+
+.nf
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "id",
+ CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
+ CURLFORM_CONTENTHEADER, headers,
+ CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "id");
+ curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
+ curl_mime_headers(part, headers, FALSE);
+.fi
+
+Setting the last \fIcurl_mime_headers\fP argument to TRUE would have caused
+the headers to be automatically released upon destroyed the multi-part, thus
+saving a clean-up call to \fIcurl_slist_free_all(3)\fP.
+
+.nf
+ curl_formadd(&post, &last,
+ CURLFORM_PTRNAME, "logotype-image",
+ CURLFORM_FILECONTENT, "-",
+ CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "logotype-image");
+ curl_mime_data_cb(part, (curl_off_t) -1, fread, fseek, NULL, stdin);
+.fi
+
+\fIcurl_mime_name\fP always copies the field name. The special file name "-"
+is not supported by \fIcurl_mime_file\fP: to read an open file, use
+a callback source using fread(). The transfer will be chunked since the data
+size is unknown.
+
+.nf
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "datafile[]",
+ CURLFORM_FILE, "file1",
+ CURLFORM_FILE, "file2",
+ CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "datafile[]");
+ curl_mime_filedata(part, "file1");
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "datafile[]");
+ curl_mime_filedata(part, "file2");
+.fi
+
+The deprecated multipart/mixed implementation of multiple files field is
+translated to two distinct parts with the same name.
+
+.nf
+ curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, myreadfunc);
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "stream",
+ CURLFORM_STREAM, arg,
+ CURLFORM_CONTENTLEN, (curl_off_t) datasize,
+ CURLFORM_FILENAME, "archive.zip",
+ CURLFORM_CONTENTTYPE, "application/zip",
+ CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "stream");
+ curl_mime_data_cb(part, (curl_off_t) datasize,
+ myreadfunc, NULL, NULL, arg);
+ curl_mime_filename(part, "archive.zip");
+ curl_mime_type(part, "application/zip");
+.fi
+
+\fICURLOPT_READFUNCTION\fP callback is not used: it is replace by directly
+setting the part source data from the callback read function.
+
+.nf
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "memfile",
+ CURLFORM_BUFFER, "memfile.bin",
+ CURLFORM_BUFFERPTR, databuffer,
+ CURLFORM_BUFFERLENGTH, (long) sizeof databuffer,
+ CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "memfile");
+ curl_mime_data(part, databuffer, (curl_off_t) sizeof databuffer);
+ curl_mime_filename(part, "memfile.bin");
+.fi
+
+\fIcurl_mime_data\fP always copies the initial data: data buffer is thus
+free for immediate reuse.
+
+.nf
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "message",
+ CURLFORM_FILECONTENT, "msg.txt",
+ CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "message");
+ curl_mime_filedata(part, "msg.txt");
+ curl_mime_filename(part, NULL);
+.fi
+
+Use of \fIcurl_mime_filedata\fP sets the remote file name as a side effect: it
+is therefore necessary to clear it for \fICURLFORM_FILECONTENT\fP emulation.
+
.SH "Showing Progress"
For historical and traditional reasons, libcurl has a built-in progress meter
@@ -1005,6 +1188,81 @@ When doing the "PORT" approach, libcurl will attempt to use the EPRT and the
LPRT before trying PORT, as they work with more protocols. You can disable
this behavior by setting \fICURLOPT_FTP_USE_EPRT(3)\fP to zero.
+.SH "MIME API revisited for SMTP and IMAP"
+In addition to support HTTP multi-part form fields, the MIME API can be used
+to build structured e-mail messages and send them via SMTP or append such
+messages to IMAP directories.
+
+A structured e-mail message may contain several parts: some are displayed
+inline by the MUA, some are attachments. Parts can also be structured as
+multi-part, for example to include another e-mail message or to offer several
+text formats alternatives. This can be nested to any level.
+
+To build such a message, you prepare the nth-level multi-part and then include
+it as a source to the parent multi-part using function
+\fIcurl_mime_subparts(3)\fP. Once it has been
+bound to its parent multi-part, a nth-level multi-part belongs to it and
+should not be freed explicitly.
+
+E-mail messages data is not supposed to be non-ascii and line length is
+limited: fortunately, some transfer encodings are defined by the standards
+to support the transmission of such incompatible data. Function
+\fIcurl_mime_encoder(3)\fP tells a part that its source data must be encoded
+before being sent. It also generates the corresponding header for that part.
+If the part data you want to send is already encoded in such a scheme,
+do not use this function (this would over-encode it), but explicitly set the
+corresponding part header.
+
+Upon sending such a message, libcurl prepends it with the header list
+set with \fICURLOPT_HTTPHEADER(3)\fP, as 0th-level mime part headers.
+
+Here is an example building an e-mail message with an inline plain/html text
+alternative and a file attachment encoded in base64:
+
+.nf
+ curl_mime *message = curl_mime_init(easyhandle);
+
+ /* The inline part is an alterative proposing the html and the text
+ versions of the e-mail. */
+ curl_mime *alt = curl_mime_init(easyhandle);
+
+ /* HTML message. */
+ curl_mimepart *part = curl_mime_addpart(alt);
+ curl_mime_data(part, "<html><body><p>This is HTML</p></body></html>",
+ CURL_ZERO_TERMINATED);
+ curl_mime_type(part, "text/html");
+
+ /* Text message. */
+ part = curl_mime_addpart(alt);
+ curl_mime_data(part, "This is plain text message",
+ CURL_ZERO_TERMINATED);
+
+ /* Create the inline part. */
+ part = curl_mime_addpart(message);
+ curl_mime_subparts(part, alt);
+ curl_mime_type(part, "multipart/alternative");
+ struct curl_slist *headers = curl_slist_append(NULL,
+ "Content-Disposition: inline");
+ curl_mime_headers(part, headers, TRUE);
+
+ /* Add the attachment. */
+ part = curl_mime_addpart(message);
+ curl_mime_filedata(part, "manual.pdf");
+ curl_mime_encoder(part, "base64");
+
+ /* Build the mail headers. */
+ headers = curl_slist_append(NULL, "From: me@example.com");
+ headers = curl_slist_append(headers, "To: you@example.com");
+
+ /* Set these into the easy handle. */
+ curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(easyhandle, CURLOPT_MIMEPOST, mime);
+.fi
+
+It should be noted that appending a message to an IMAP directory requires
+the message size to be known prior upload. It is therefore not possible to
+include parts with unknown data size in this context.
+
.SH "Headers Equal Fun"
Some protocols provide "headers", meta-data separated from the normal
diff --git a/docs/libcurl/libgnurl.3 b/docs/libcurl/libgnurl.3
index 6618734b4..e8ecc31da 100644
--- a/docs/libcurl/libgnurl.3
+++ b/docs/libcurl/libgnurl.3
@@ -38,6 +38,10 @@ while using libcurl. This essentially means you call
\fIcurl_global_cleanup(3)\fP at the end. See \fBGLOBAL CONSTANTS\fP below for
details.
+If libcurl was compiled with support for multiple SSL backends, the function
+\fIcurl_global_sslset(3)\fP can be called before \fIcurl_global_init(3)\fP
+to select the active SSL backend.
+
To transfer files, you create an "easy handle" using \fIcurl_easy_init(3)\fP
for a single individual transfer (in either direction). You then set your
desired set of options in that handle with \fIcurl_easy_setopt(3)\fP. Options
diff --git a/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3 b/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
index cfbe876d0..f418d13d7 100644
--- a/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T \- get content-length of download
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
curl_off_t *content_length);
diff --git a/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3 b/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3
index af92fd3df..04b7811f4 100644
--- a/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_CONTENT_LENGTH_UPLOAD_T \- get the specified size of the upload
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD_T,
curl_off_t *content_length);
diff --git a/docs/libcurl/opts/GNURLINFO_PROTOCOL.3 b/docs/libcurl/opts/GNURLINFO_PROTOCOL.3
index e6dc4ac15..b82111876 100644
--- a/docs/libcurl/opts/GNURLINFO_PROTOCOL.3
+++ b/docs/libcurl/opts/GNURLINFO_PROTOCOL.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_PROTOCOL \- get the protocol used in the connection
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3 b/docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3
index c148bf329..b6ef7d13e 100644
--- a/docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3
+++ b/docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_PROXY_SSL_VERIFYRESULT \- get the result of the proxy certificate verification
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_SSL_VERIFYRESULT, long *result);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SCHEME.3 b/docs/libcurl/opts/GNURLINFO_SCHEME.3
index acc501f6d..38a3d15ba 100644
--- a/docs/libcurl/opts/GNURLINFO_SCHEME.3
+++ b/docs/libcurl/opts/GNURLINFO_SCHEME.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the connection
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, char **scheme);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3 b/docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3
index e41411151..834c6d6f0 100644
--- a/docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_SIZE_DOWNLOAD_T \- get the number of downloaded bytes
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD_T, curl_off_t *dlp);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3 b/docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3
index 813ef4913..2999be460 100644
--- a/docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_SIZE_UPLOAD_T \- get the number of uploaded bytes
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD_T, curl_off_t *uploadp);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3 b/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3
index 262d3b90f..413389c80 100644
--- a/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_SPEED_DOWNLOAD_T \- get download speed
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD_T, curl_off_t *speed);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3 b/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3
index 5a8ba22f7..36389b34b 100644
--- a/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3
@@ -24,7 +24,7 @@
.SH NAME
CURLINFO_SPEED_UPLOAD_T \- get upload speed
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD_T, curl_off_t *speed);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3 b/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
index b9ee4fff3..8b61854c0 100644
--- a/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
+++ b/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_ABSTRACT_UNIX_SOCKET \- set an abstract Unix domain socket
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ABSTRACT_UNIX_SOCKET, char *path);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_CAPATH.3 b/docs/libcurl/opts/GNURLOPT_CAPATH.3
index dfef33b4d..bceffdc83 100644
--- a/docs/libcurl/opts/GNURLOPT_CAPATH.3
+++ b/docs/libcurl/opts/GNURLOPT_CAPATH.3
@@ -54,8 +54,9 @@ if(curl) {
}
.fi
.SH AVAILABILITY
-This option is supported by the OpenSSL, GnuTLS and PolarSSL backends. The NSS
-backend provides the option only for backward compatibility.
+This option is supported by the OpenSSL, GnuTLS, PolarSSL and mbedTLS
+(since 7.56.0) backends. The NSS backend provides the option only for
+backward compatibility.
.SH RETURN VALUE
CURLE_OK if supported; or an error such as:
diff --git a/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3 b/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3
index 56b371292..3e3dca396 100644
--- a/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3
+++ b/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3
@@ -36,6 +36,9 @@ default built-in connection timeout - 300 seconds. See also the
In unix-like systems, this might cause signals to be used unless
\fICURLOPT_NOSIGNAL(3)\fP is set.
+
+If both \fICURLOPT_CONNECTTIMEOUT(3)\fP and \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
+are set, the value set last will be used.
.SH DEFAULT
300
.SH PROTOCOLS
@@ -57,4 +60,5 @@ Always
.SH RETURN VALUE
Returns CURLE_OK
.SH "SEE ALSO"
+.BR CURLOPT_CONNECTTIMEOUT_MS "(3), "
.BR CURLOPT_TIMEOUT "(3), " CURLOPT_LOW_SPEED_LIMIT "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3 b/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3
index 2d86042cc..7a7ee9302 100644
--- a/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3
+++ b/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3
@@ -36,6 +36,9 @@ default built-in connection timeout - 300 seconds. See also the
In unix-like systems, this might cause signals to be used unless
\fICURLOPT_NOSIGNAL(3)\fP is set.
+
+If both \fICURLOPT_CONNECTTIMEOUT(3)\fP and \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
+are set, the value set last will be used.
.SH DEFAULT
300000
.SH PROTOCOLS
@@ -57,4 +60,5 @@ Always
.SH RETURN VALUE
Returns CURLE_OK
.SH "SEE ALSO"
+.BR CURLOPT_CONNECTTIMEOUT "(3), "
.BR CURLOPT_TIMEOUT "(3), " CURLOPT_LOW_SPEED_LIMIT "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_HTTPPOST.3 b/docs/libcurl/opts/GNURLOPT_HTTPPOST.3
index 942045000..8cf6018b6 100644
--- a/docs/libcurl/opts/GNURLOPT_HTTPPOST.3
+++ b/docs/libcurl/opts/GNURLOPT_HTTPPOST.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -42,6 +42,9 @@ You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP.
When setting \fICURLOPT_HTTPPOST(3)\fP, it will automatically set
\fICURLOPT_NOBODY(3)\fP to 0.
+
+This option is deprecated! Do not use it. Use \fICURLOPT_MIMEPOST(3)\fP
+instead after having prepared mime data.
.SH DEFAULT
NULL
.SH PROTOCOLS
@@ -71,9 +74,9 @@ curl_formadd(&formpost,
CURLFORM_END);
.fi
.SH AVAILABILITY
-As long as HTTP is enabled
+As long as HTTP is enabled. Deprecated in 7.56.0.
.SH RETURN VALUE
Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
-.BR CURLOPT_POSTFIELDS "(3), " CURLOPT_POST "(3), "
-.BR curl_formadd "(3), " curl_formfree "(3), "
+.BR CURLOPT_POSTFIELDS "(3), " CURLOPT_POST "(3), " CURLOPT_MIMEPOST "(3),"
+.BR curl_formadd "(3), " curl_formfree "(3), " curl_mime_init "(3)"
diff --git a/docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3 b/docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3
index 232e64abf..79a059446 100644
--- a/docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3
+++ b/docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3
@@ -22,15 +22,16 @@
.\"
.TH CURLOPT_INTERLEAVEDATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
.SH NAME
-CURLOPT_INTERLEAVEDATA \- custom pointer to RTSP interleave callback
+CURLOPT_INTERLEAVEDATA \- custom pointer passed to RTSP interleave callback
.SH SYNOPSIS
#include <gnurl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERLEAVEDATA, void *pointer);
.SH DESCRIPTION
This is the userdata \fIpointer\fP that will be passed to
-\fICURLOPT_INTERLEAVEFUNCTION(3)\fP when interleaved RTP data is
-received.
+\fICURLOPT_INTERLEAVEFUNCTION(3)\fP when interleaved RTP data is received. If
+the interleave function callback is not set, this pointer is not used
+anywhere.
.SH DEFAULT
NULL
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3 b/docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3
index 25bcd0f94..326a29c46 100644
--- a/docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3
+++ b/docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3
@@ -54,8 +54,12 @@ connection may close. The application may use \fICURL_RTSPREQ_RECEIVE\fP to
service RTP data when no requests are desired. If the application makes a
request, (e.g. \fICURL_RTSPREQ_PAUSE\fP) then the response handler will
process any pending RTP data before marking the request as finished.
+
+The \fICURLOPT_WRITEDATA(3)\fP is passed in the \fIuserdata\fP argument in the
+callback.
.SH DEFAULT
-NULL
+NULL, the interleave data is then passed to the regular write function:
+\fICURLOPT_WRITEFUNCTION(3)\fP.
.SH PROTOCOLS
RTSP
.SH EXAMPLE
@@ -77,4 +81,4 @@ Added in 7.20.0
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
-.BR CURLOPT_INTERLEAVEFUNCTION "(3), " CURLOPT_RTSP_REQUEST "(3), "
+.BR CURLOPT_INTERLEAVEDATA "(3), " CURLOPT_RTSP_REQUEST "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3 b/docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3
index fbef74c07..384ca756c 100644
--- a/docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3
+++ b/docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_KEEP_SENDING_ON_ERROR \- keep sending on early HTTP response >= 300
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEEP_SENDING_ON_ERROR,
long keep_sending);
diff --git a/docs/libcurl/opts/GNURLOPT_MIMEPOST.3 b/docs/libcurl/opts/GNURLOPT_MIMEPOST.3
new file mode 100644
index 000000000..dd64c4b17
--- /dev/null
+++ b/docs/libcurl/opts/GNURLOPT_MIMEPOST.3
@@ -0,0 +1,52 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_MIMEPOST 3 "22 Aug 2017" "libcurl 7.56.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_MIMEPOST \- set post/send data from mime structure
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+curl_mime *mime;
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIMEPOST, mime);
+.SH DESCRIPTION
+Pass a mime handle previously obtained from \fIcurl_mime_init(3)\fP.
+
+This setting is supported by the HTTP protocol to post forms and by the
+SMTP and IMAP protocols to provide the e-mail data to send/upload.
+
+This option is the preferred way of posting an HTTP form, replacing and
+extending the deprecated \fICURLOPT_HTTPPOST(3)\fP option.
+.SH PROTOCOLS
+HTTP, SMTP, IMAP.
+.SH AVAILABILITY
+Since 7.56.0.
+.SH RETURN VALUE
+This will return CURLE_OK.
+.SH EXAMPLE
+Using this option implies the use of several mime structure building
+functions: see https://curl.haxx.se/libcurl/c/smtp-mime.html for a complete
+example.
+.SH "SEE ALSO"
+.BR curl_mime_init "(3)"
diff --git a/docs/libcurl/opts/GNURLOPT_NOPROXY.3 b/docs/libcurl/opts/GNURLOPT_NOPROXY.3
index 9b01eba1f..873724484 100644
--- a/docs/libcurl/opts/GNURLOPT_NOPROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_NOPROXY.3
@@ -41,8 +41,13 @@ If the name in the noproxy list has a leading period, it is a domain match
against the provided host name. This way ".example.com" will switch off proxy
use for both "www.example.com" as well as for "foo.example.com".
+Setting the noproxy string to "" (an empty string) will explicitly enable the
+proxy for all host names, even if there is an environment variable set for it.
+
The application does not have to keep the string around after setting this
option.
+.SH "Environment variables"
+See \fIGNURLOPT_PROXY(3)\fP
.SH DEFAULT
NULL
.SH PROTOCOLS
@@ -66,4 +71,4 @@ Added in 7.19.4
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
.SH "SEE ALSO"
-.BR CURLOPT_PROXY "(3), " CURLOPT_PROXYAUTH "(3), "
+.BR GNURLOPT_PROXY "(3), " GNURLOPT_PROXYAUTH "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3 b/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
index 57dfcf6fe..8894c16da 100644
--- a/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PRE_PROXY \- set pre-proxy to use
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRE_PROXY, char *preproxy);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY.3 b/docs/libcurl/opts/GNURLOPT_PROXY.3
index 1fc4000b3..615af887d 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY.3
@@ -84,7 +84,8 @@ names to not use a proxy for (even if one of the previous mention variables
are set). That is the exact equivalent of setting the \fICURLOPT_NOPROXY(3)\fP
option.
-The \fICURLOPT_PROXY(3)\fP option overrides environment variables.
+The \fICURLOPT_PROXY(3)\fP and \fICURLOPT_NOPROXY(3)\fP options override
+environment variables.
.SH DEFAULT
Default is NULL, meaning no proxy is used.
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3 b/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
index 792fab689..a5f61a5bd 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_CAINFO \- path to proxy Certificate Authority (CA) bundle
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO, char *path);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3 b/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
index 91a807f89..1e7345ed3 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_CAPATH \- specify directory holding proxy CA certificates
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAPATH, char *capath);
.SH DESCRIPTION
@@ -55,8 +55,9 @@ if(curl) {
.SH AVAILABILITY
Added in 7.52.0
-This option is supported by the OpenSSL, GnuTLS and PolarSSL backends. The NSS
-backend provides the option only for backward compatibility.
+This option is supported by the OpenSSL, GnuTLS, PolarSSL and mbedTLS
+(since 7.56.0) backends. The NSS backend provides the option only for
+backward compatibility.
.SH RETURN VALUE
CURLE_OK if supported; or an error such as:
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3 b/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
index 602e09ede..310ad7a4e 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_CRLFILE \- specify a proxy Certificate Revocation List file
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CRLFILE, char *file);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3 b/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
index 52ed676df..594290274 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_KEYPASSWD \- set passphrase to proxy private key
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_KEYPASSWD, char *pwd);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3 b/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
index 14a011e87..f6d56ebe9 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_PINNEDPUBLICKEY \- set pinned public key for https proxy
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_PINNEDPUBLICKEY, char *pinnedpubkey);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
index 5402c0df6..41e73190e 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSLCERT \- set SSL proxy client certificate
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
index 8603acc35..b8a6be0bb 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSLCERTTYPE \- specify type of the proxy client SSL certificate
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERTTYPE, char *type);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
index 585ff00fc..8df1c1ee6 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSLKEY \- specify private keyfile for TLS and SSL proxy client cert
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY, char *keyfile);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
index d9de3218c..687c229a0 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSLKEYTYPE \- set type of the proxy private key file
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEYTYPE, char *type);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3
index 40adadc1a..6b9ff7dee 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSLVERSION \- set preferred proxy TLS/SSL version
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLVERSION, long version);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
index c959607fa..caaef81a3 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSL_CIPHER_LIST \- specify ciphers to use for proxy TLS
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_CIPHER_LIST, char *list);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
index f0a70fda6..428efc38e 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSL_OPTIONS \- set proxy SSL behavior options
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_OPTIONS, long bitmask);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3
index 584a6b5f1..de4b15b34 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSL_VERIFYHOST \- verify the proxy certificate's name against host
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYHOST, long verify);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3
index 9f156d1f2..9473495cf 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_SSL_VERIFYPEER \- verify the proxy's SSL certificate
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYPEER, long verify);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3 b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
index 3bde5392b..db3a3d1bb 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_TLSAUTH_PASSWORD \- password to use for proxy TLS authentication
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_PASSWORD, char *pwd);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3 b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
index 6130577d3..47f4dae4a 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_TLSAUTH_TYPE \- set proxy TLS authentication methods
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_TYPE, char *type);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3 b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
index 7623ba37a..6a2c4388d 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_PROXY_TLSAUTH_USERNAME \- user name to use for proxy TLS authentication
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_USERNAME, char *user);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3 b/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
index 88ae1397e..eabefaa2d 100644
--- a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
+++ b/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_REQUEST_TARGET \- specify an alternative target for this request
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3 b/docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3
index 2b66830db..7b5e5822b 100644
--- a/docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3
+++ b/docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_SOCKS5_AUTH \- set allowed methods for SOCKS5 proxy authentication
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_AUTH, long bitmask);
.SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_SSH_COMPRESSION.3 b/docs/libcurl/opts/GNURLOPT_SSH_COMPRESSION.3
new file mode 100644
index 000000000..5445cb0d2
--- /dev/null
+++ b/docs/libcurl/opts/GNURLOPT_SSH_COMPRESSION.3
@@ -0,0 +1,58 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_SSH_COMPRESSION 3 "05 Aug 2017" "libcurl 7.56.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_SSH_COMPRESSION \- enables automatic decompression of HTTP downloads
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_COMPRESSION, long enable);
+.SH DESCRIPTION
+Pass a long as parameter set to 1L to enable or 0L to disable.
+
+Enables built-in SSH compression. This is a request, not an order; the server
+may or may not do it.
+.SH DEFAULT
+0, disabled
+.SH PROTOCOLS
+All SSH based protocols: SCP, SFTP
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com");
+
+ /* enable built-in compression */
+ curl_easy_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.56.0
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_ACCEPT_ENCODING "(3), " CURLOPT_TRANSFER_ENCODING "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3 b/docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3
index 7b6dec4b3..216bdec3a 100644
--- a/docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3
+++ b/docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3
@@ -24,7 +24,7 @@
.SH NAME
CURLOPT_SSL_CTX_DATA \- custom pointer passed to ssl_ctx callback
.SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_DATA, void *pointer);
.SH DESCRIPTION
@@ -40,7 +40,7 @@ All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
/* OpenSSL specific */
#include <openssl/ssl.h>
-#include <gnurl/curl.h>
+#include <curl/curl.h>
#include <stdio.h>
static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
diff --git a/docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3 b/docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3
index 22f83790f..8cfec7a8f 100644
--- a/docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3
+++ b/docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3
@@ -25,7 +25,7 @@
CURLOPT_SUPPRESS_CONNECT_HEADERS \- Suppress proxy CONNECT response headers from user callbacks
.SH SYNOPSIS
.nf
-#include <gnurl/curl.h>
+#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SUPPRESS_CONNECT_HEADERS, long onoff);
.fi
diff --git a/docs/libcurl/opts/GNURLOPT_USERPWD.3 b/docs/libcurl/opts/GNURLOPT_USERPWD.3
index b0bd19bb0..c303d39c3 100644
--- a/docs/libcurl/opts/GNURLOPT_USERPWD.3
+++ b/docs/libcurl/opts/GNURLOPT_USERPWD.3
@@ -88,3 +88,4 @@ Returns CURLE_OK on success or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
.SH "SEE ALSO"
.BR CURLOPT_USERNAME "(3), " CURLOPT_PASSWORD "(3), "
+.BR CURLOPT_PROXYUSERPWD "(3), "
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index fc20ee351..4300ec1cd 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -56,21 +56,21 @@ man_MANS = \
GNURLINFO_TLS_SESSION.3 \
GNURLINFO_TLS_SSL_PTR.3 \
GNURLINFO_TOTAL_TIME.3 \
- GNURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3 \
- GNURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3 \
- GNURLMOPT_MAXCONNECTS.3 \
- GNURLMOPT_MAX_HOST_CONNECTIONS.3 \
- GNURLMOPT_MAX_PIPELINE_LENGTH.3 \
- GNURLMOPT_MAX_TOTAL_CONNECTIONS.3 \
- GNURLMOPT_PIPELINING.3 \
- GNURLMOPT_PIPELINING_SERVER_BL.3 \
- GNURLMOPT_PIPELINING_SITE_BL.3 \
- GNURLMOPT_PUSHDATA.3 \
- GNURLMOPT_PUSHFUNCTION.3 \
- GNURLMOPT_SOCKETDATA.3 \
- GNURLMOPT_SOCKETFUNCTION.3 \
- GNURLMOPT_TIMERDATA.3 \
- GNURLMOPT_TIMERFUNCTION.3 \
+ GNURLMOPTCHUNK_LENGTH_PENALTY_SIZE.3 \
+ GNURLMOPTCONTENT_LENGTH_PENALTY_SIZE.3 \
+ GNURLMOPTMAXCONNECTS.3 \
+ GNURLMOPTMAX_HOST_CONNECTIONS.3 \
+ GNURLMOPTMAX_PIPELINE_LENGTH.3 \
+ GNURLMOPTMAX_TOTAL_CONNECTIONS.3 \
+ GNURLMOPTPIPELINING.3 \
+ GNURLMOPTPIPELINING_SERVER_BL.3 \
+ GNURLMOPTPIPELINING_SITE_BL.3 \
+ GNURLMOPTPUSHDATA.3 \
+ GNURLMOPTPUSHFUNCTION.3 \
+ GNURLMOPTSOCKETDATA.3 \
+ GNURLMOPTSOCKETFUNCTION.3 \
+ GNURLMOPTTIMERDATA.3 \
+ GNURLMOPTTIMERFUNCTION.3 \
GNURLOPT_ABSTRACT_UNIX_SOCKET.3 \
GNURLOPT_ACCEPTTIMEOUT_MS.3 \
GNURLOPT_ACCEPT_ENCODING.3 \
@@ -175,6 +175,7 @@ man_MANS = \
GNURLOPT_MAXREDIRS.3 \
GNURLOPT_MAX_RECV_SPEED_LARGE.3 \
GNURLOPT_MAX_SEND_SPEED_LARGE.3 \
+ GNURLOPT_MIMEPOST.3 \
GNURLOPT_NETRC.3 \
GNURLOPT_NETRC_FILE.3 \
GNURLOPT_NEW_DIRECTORY_PERMS.3 \
@@ -258,6 +259,7 @@ man_MANS = \
GNURLOPT_SOCKS5_GSSAPI_NEC.3 \
GNURLOPT_SOCKS5_GSSAPI_SERVICE.3 \
GNURLOPT_SSH_AUTH_TYPES.3 \
+ GNURLOPT_SSH_COMPRESSION.3 \
GNURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3 \
GNURLOPT_SSH_KEYDATA.3 \
GNURLOPT_SSH_KEYFUNCTION.3 \
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index e141b6a57..f912fb719 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -160,27 +160,27 @@ CURLFINFOFLAG_KNOWN_PERM 7.21.0
CURLFINFOFLAG_KNOWN_SIZE 7.21.0
CURLFINFOFLAG_KNOWN_TIME 7.21.0
CURLFINFOFLAG_KNOWN_UID 7.21.0
-CURLFORM_ARRAY 7.9.1
+CURLFORM_ARRAY 7.9.1 7.56.0
CURLFORM_ARRAY_END 7.9.1 7.9.5 7.9.6
CURLFORM_ARRAY_START 7.9.1 7.9.5 7.9.6
-CURLFORM_BUFFER 7.9.8
-CURLFORM_BUFFERLENGTH 7.9.8
-CURLFORM_BUFFERPTR 7.9.8
-CURLFORM_CONTENTHEADER 7.9.3
-CURLFORM_CONTENTLEN 7.46.0
-CURLFORM_CONTENTSLENGTH 7.9
-CURLFORM_CONTENTTYPE 7.9
-CURLFORM_COPYCONTENTS 7.9
-CURLFORM_COPYNAME 7.9
-CURLFORM_END 7.9
-CURLFORM_FILE 7.9
-CURLFORM_FILECONTENT 7.9.1
-CURLFORM_FILENAME 7.9.6
-CURLFORM_NAMELENGTH 7.9
-CURLFORM_NOTHING 7.9
-CURLFORM_PTRCONTENTS 7.9
-CURLFORM_PTRNAME 7.9
-CURLFORM_STREAM 7.18.2
+CURLFORM_BUFFER 7.9.8 7.56.0
+CURLFORM_BUFFERLENGTH 7.9.8 7.56.0
+CURLFORM_BUFFERPTR 7.9.8 7.56.0
+CURLFORM_CONTENTHEADER 7.9.3 7.56.0
+CURLFORM_CONTENTLEN 7.46.0 7.56.0
+CURLFORM_CONTENTSLENGTH 7.9 7.56.0
+CURLFORM_CONTENTTYPE 7.9 7.56.0
+CURLFORM_COPYCONTENTS 7.9 7.56.0
+CURLFORM_COPYNAME 7.9 7.56.0
+CURLFORM_END 7.9 7.56.0
+CURLFORM_FILE 7.9 7.56.0
+CURLFORM_FILECONTENT 7.9.1 7.56.0
+CURLFORM_FILENAME 7.9.6 7.56.0
+CURLFORM_NAMELENGTH 7.9 7.56.0
+CURLFORM_NOTHING 7.9 7.56.0
+CURLFORM_PTRCONTENTS 7.9 7.56.0
+CURLFORM_PTRNAME 7.9 7.56.0
+CURLFORM_STREAM 7.18.2 7.56.0
CURLFTPAUTH_DEFAULT 7.12.2
CURLFTPAUTH_SSL 7.12.2
CURLFTPAUTH_TLS 7.12.2
@@ -406,7 +406,7 @@ CURLOPT_HTTP200ALIASES 7.10.3
CURLOPT_HTTPAUTH 7.10.6
CURLOPT_HTTPGET 7.8.1
CURLOPT_HTTPHEADER 7.1
-CURLOPT_HTTPPOST 7.1
+CURLOPT_HTTPPOST 7.1 7.56.0
CURLOPT_HTTPPROXYTUNNEL 7.3
CURLOPT_HTTPREQUEST 7.1 - 7.15.5
CURLOPT_HTTP_CONTENT_DECODING 7.16.2
@@ -441,6 +441,7 @@ CURLOPT_MAXFILESIZE_LARGE 7.11.0
CURLOPT_MAXREDIRS 7.5
CURLOPT_MAX_RECV_SPEED_LARGE 7.15.5
CURLOPT_MAX_SEND_SPEED_LARGE 7.15.5
+CURLOPT_MIMEPOST 7.56.0
CURLOPT_MUTE 7.1 7.8 7.15.5
CURLOPT_NETRC 7.1
CURLOPT_NETRC_FILE 7.11.0
@@ -540,6 +541,7 @@ CURLOPT_SOURCE_QUOTE 7.13.0 - 7.15.5
CURLOPT_SOURCE_URL 7.13.0 - 7.15.5
CURLOPT_SOURCE_USERPWD 7.12.1 - 7.15.5
CURLOPT_SSH_AUTH_TYPES 7.16.1
+CURLOPT_SSH_COMPRESSION 7.56.0
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 7.17.1
CURLOPT_SSH_KEYDATA 7.19.6
CURLOPT_SSH_KEYFUNCTION 7.19.6
@@ -689,6 +691,10 @@ CURLSSLBACKEND_SCHANNEL 7.34.0
CURLSSLBACKEND_WOLFSSL 7.49.0
CURLSSLOPT_ALLOW_BEAST 7.25.0
CURLSSLOPT_NO_REVOKE 7.44.0
+CURLSSLSET_NO_BACKENDS 7.56.0
+CURLSSLSET_OK 7.56.0
+CURLSSLSET_TOO_LATE 7.56.0
+CURLSSLSET_UNKNOWN_BACKEND 7.56.0
CURLUSESSL_ALL 7.17.0
CURLUSESSL_CONTROL 7.17.0
CURLUSESSL_NONE 7.17.0
@@ -713,14 +719,14 @@ CURL_ERROR_SIZE 7.1
CURL_FNMATCHFUNC_FAIL 7.21.0
CURL_FNMATCHFUNC_MATCH 7.21.0
CURL_FNMATCHFUNC_NOMATCH 7.21.0
-CURL_FORMADD_DISABLED 7.12.1
-CURL_FORMADD_ILLEGAL_ARRAY 7.9.8
-CURL_FORMADD_INCOMPLETE 7.9.8
-CURL_FORMADD_MEMORY 7.9.8
-CURL_FORMADD_NULL 7.9.8
-CURL_FORMADD_OK 7.9.8
-CURL_FORMADD_OPTION_TWICE 7.9.8
-CURL_FORMADD_UNKNOWN_OPTION 7.9.8
+CURL_FORMADD_DISABLED 7.12.1 7.56.0
+CURL_FORMADD_ILLEGAL_ARRAY 7.9.8 7.56.0
+CURL_FORMADD_INCOMPLETE 7.9.8 7.56.0
+CURL_FORMADD_MEMORY 7.9.8 7.56.0
+CURL_FORMADD_NULL 7.9.8 7.56.0
+CURL_FORMADD_OK 7.9.8 7.56.0
+CURL_FORMADD_OPTION_TWICE 7.9.8 7.56.0
+CURL_FORMADD_UNKNOWN_OPTION 7.9.8 7.56.0
CURL_GLOBAL_ACK_EINTR 7.30.0
CURL_GLOBAL_ALL 7.8
CURL_GLOBAL_DEFAULT 7.8
@@ -836,6 +842,7 @@ CURL_VERSION_KERBEROS4 7.10 7.33.0
CURL_VERSION_KERBEROS5 7.40.0
CURL_VERSION_LARGEFILE 7.11.1
CURL_VERSION_LIBZ 7.10
+CURL_VERSION_MULTI_SSL 7.56.0
CURL_VERSION_NTLM 7.10.6
CURL_VERSION_NTLM_WB 7.22.0
CURL_VERSION_PSL 7.47.0
@@ -848,3 +855,4 @@ CURL_WAIT_POLLIN 7.28.0
CURL_WAIT_POLLOUT 7.28.0
CURL_WAIT_POLLPRI 7.28.0
CURL_WRITEFUNC_PAUSE 7.18.0
+CURL_ZERO_TERMINATED 7.56.0
diff --git a/include/README b/include/README
index 0fc8f66d9..12516ebe6 100644
--- a/include/README
+++ b/include/README
@@ -30,4 +30,4 @@ NOTE FOR LIBCURL HACKERS
To figure out how to do good and portable checks for features, operating
systems or specific hardwarare, a very good resource is Bjorn Reese's
-collection at http://predef.sf.net/
+collection at https://sourceforge.net/p/predef/wiki/
diff --git a/include/gnurl/curl.h b/include/gnurl/curl.h
index 82fb8aeb8..7139a3311 100644
--- a/include/gnurl/curl.h
+++ b/include/gnurl/curl.h
@@ -74,6 +74,7 @@
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
+ defined(__CYGWIN__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
#include <sys/select.h>
#endif
@@ -132,6 +133,27 @@ typedef int curl_socket_t;
#define curl_socket_typedef
#endif /* curl_socket_typedef */
+/* enum for the different supported SSL backends */
+typedef enum {
+ CURLSSLBACKEND_NONE = 0,
+ CURLSSLBACKEND_OPENSSL = 1,
+ CURLSSLBACKEND_GNUTLS = 2,
+ CURLSSLBACKEND_NSS = 3,
+ CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
+ CURLSSLBACKEND_GSKIT = 5,
+ CURLSSLBACKEND_POLARSSL = 6,
+ CURLSSLBACKEND_WOLFSSL = 7,
+ CURLSSLBACKEND_SCHANNEL = 8,
+ CURLSSLBACKEND_DARWINSSL = 9,
+ CURLSSLBACKEND_AXTLS = 10,
+ CURLSSLBACKEND_MBEDTLS = 11
+} curl_sslbackend;
+
+/* aliases for library clones and renames */
+#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
+#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
+#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
+
struct curl_httppost {
struct curl_httppost *next; /* next entry in the list */
char *name; /* pointer to allocated name */
@@ -335,7 +357,7 @@ typedef size_t (*curl_read_callback)(char *buffer,
size_t nitems,
void *instream);
-typedef enum {
+typedef enum {
CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
CURLSOCKTYPE_LAST /* never use */
@@ -377,7 +399,7 @@ typedef enum {
CURLIOE_LAST /* never use */
} curlioerr;
-typedef enum {
+typedef enum {
CURLIOCMD_NOP, /* no operation */
CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
CURLIOCMD_LAST /* never use */
@@ -1788,6 +1810,12 @@ typedef enum {
/* bitmask of allowed auth methods for connections to SOCKS5 proxies */
CINIT(SOCKS5_AUTH, LONG, 267),
+ /* Enable/disable SSH compression */
+ CINIT(SSH_COMPRESSION, LONG, 268),
+
+ /* Post MIME data. */
+ CINIT(MIMEPOST, OBJECTPOINT, 269),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -1934,15 +1962,140 @@ typedef enum {
CURL_TIMECOND_LAST
} curl_TimeCond;
+/* Special size_t value signaling a zero-terminated string. */
+#define CURL_ZERO_TERMINATED ((size_t) -1)
/* curl_strequal() and curl_strnequal() are subject for removal in a future
- libcurl, see lib/README.curlx for details
+ release */
+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);
+
+/* Mime/form handling support. */
+typedef struct curl_mime_s curl_mime; /* Mime context. */
+typedef struct curl_mimepart_s curl_mimepart; /* Mime part context. */
+
+/*
+ * NAME curl_mime_init()
+ *
+ * DESCRIPTION
+ *
+ * Create a mime context and return its handle. The easy parameter is the
+ * target handle.
+ */
+CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
+
+/*
+ * NAME curl_mime_free()
+ *
+ * DESCRIPTION
+ *
+ * release a mime handle and its substructures.
+ */
+CURL_EXTERN void curl_mime_free(curl_mime *mime);
+
+/*
+ * NAME curl_mime_addpart()
+ *
+ * DESCRIPTION
+ *
+ * Append a new empty part to the given mime context and return a handle to
+ * the created part.
+ */
+CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
+
+/*
+ * NAME curl_mime_name()
+ *
+ * DESCRIPTION
+ *
+ * Set mime/form part name.
+ */
+CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name);
+
+/*
+ * NAME curl_mime_filename()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part remote file name.
+ */
+CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
+ const char *filename);
+
+/*
+ * NAME curl_mime_type()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part type.
+ */
+CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
+
+/*
+ * NAME curl_mime_encoder()
+ *
+ * DESCRIPTION
+ *
+ * Set mime data transfer encoder.
+ */
+CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part,
+ const char *encoding);
+
+/*
+ * NAME curl_mime_data()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from memory data,
+ */
+CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
+ const char *data, size_t datasize);
- !checksrc! disable SPACEBEFOREPAREN 2
-*/
-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 curl_mime_filedata()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from named file.
+ */
+CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
+ const char *filename);
+/*
+ * NAME curl_mime_data_cb()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from callback function.
+ */
+CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
+ curl_off_t datasize,
+ curl_read_callback readfunc,
+ curl_seek_callback seekfunc,
+ curl_free_callback freefunc,
+ void *arg);
+
+/*
+ * NAME curl_mime_subparts()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from subparts.
+ */
+CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
+ curl_mime *subparts);
+/*
+ * NAME curl_mime_headers()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part headers.
+ */
+CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
+ struct curl_slist *headers,
+ int take_ownership);
+
+/* Old form API. */
/* name is uppercase CURLFORM_<name> */
#ifdef CFINIT
#undef CFINIT
@@ -2185,6 +2338,47 @@ struct curl_slist {
};
/*
+ * NAME curl_global_sslset()
+ *
+ * DESCRIPTION
+ *
+ * When built with multiple SSL backends, curl_global_sslset() allows to
+ * choose one. This function can only be called once, and it must be called
+ * *before* curl_global_init().
+ *
+ * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The
+ * backend can also be specified via the name parameter (passing -1 as id).
+ * If both id and name are specified, the name will be ignored. If neither id
+ * nor name are specified, the function will fail with
+ * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the
+ * NULL-terminated list of available backends.
+ *
+ * Upon success, the function returns CURLSSLSET_OK.
+ *
+ * If the specified SSL backend is not available, the function returns
+ * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated
+ * list of available SSL backends.
+ *
+ * The SSL backend can be set only once. If it has already been set, a
+ * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
+ */
+
+typedef struct {
+ curl_sslbackend id;
+ const char *name;
+} curl_ssl_backend;
+
+typedef enum {
+ CURLSSLSET_OK = 0,
+ CURLSSLSET_UNKNOWN_BACKEND,
+ CURLSSLSET_TOO_LATE,
+ CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */
+} CURLsslset;
+
+CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail);
+
+/*
* NAME curl_slist_append()
*
* DESCRIPTION
@@ -2224,27 +2418,6 @@ struct curl_certinfo {
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_OBSOLETE4 = 4, /* Was QSOSSL. */
- CURLSSLBACKEND_GSKIT = 5,
- CURLSSLBACKEND_POLARSSL = 6,
- CURLSSLBACKEND_CYASSL = 7,
- CURLSSLBACKEND_SCHANNEL = 8,
- CURLSSLBACKEND_DARWINSSL = 9,
- CURLSSLBACKEND_AXTLS = 10,
- CURLSSLBACKEND_MBEDTLS = 11
-} curl_sslbackend;
-
-/* aliases for library clones and renames */
-#define CURLSSLBACKEND_LIBRESSL 1
-#define CURLSSLBACKEND_BORINGSSL 1
-#define CURLSSLBACKEND_WOLFSSL 6
-
/* 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_SSL_PTR or CURLINFO_TLS_SESSION. */
@@ -2484,6 +2657,7 @@ typedef struct {
#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used
for cookie domain verification */
#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */
+#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */
/*
* NAME curl_version_info()
diff --git a/include/gnurl/curlver.h b/include/gnurl/curlver.h
index 2165d55b1..8c9fb5e3a 100644
--- a/include/gnurl/curlver.h
+++ b/include/gnurl/curlver.h
@@ -30,13 +30,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.55.1-DEV"
+#define LIBCURL_VERSION "7.56.0-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 55
-#define LIBCURL_VERSION_PATCH 1
+#define LIBCURL_VERSION_MINOR 56
+#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
@@ -57,7 +57,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x073701
+#define LIBCURL_VERSION_NUM 0x073800
/*
* This is the date and time when the full source package was created. The
diff --git a/include/gnurl/multi.h b/include/gnurl/multi.h
index 46d979853..55efae0be 100644
--- a/include/gnurl/multi.h
+++ b/include/gnurl/multi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/include/gnurl/system.h b/include/gnurl/system.h
index 95c72d998..39dae754c 100644
--- a/include/gnurl/system.h
+++ b/include/gnurl/system.h
@@ -52,226 +52,171 @@
#if defined(__DJGPP__) || defined(__GO32__)
# if defined(__DJGPP__) && (__DJGPP__ > 1)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__SALFORDC__)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__BORLANDC__)
# if (__BORLANDC__ < 0x520)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__TURBOC__)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__WATCOMC__)
# if defined(__386__)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__POCC__)
# if (__POCC__ < 280)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# elif defined(_MSC_VER)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__LCC__)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__SYMBIAN32__)
# if defined(__EABI__) /* Treat all ARM compilers equally */
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__CW32__)
# pragma longlong on
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__VC32__)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__MWERKS__)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(_WIN32_WCE)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__MINGW32__)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_WS2TCPIP_H 1
#elif defined(__VMS)
# if defined(__VAX)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__OS400__)
# if defined(__ILEC400__)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
@@ -279,34 +224,28 @@
#elif defined(__MVS__)
# if defined(__IBMC__) || defined(__IBMCPP__)
# if defined(_ILP32)
-# define CURL_SIZEOF_LONG 4
# elif defined(_LP64)
-# define CURL_SIZEOF_LONG 8
# endif
# if defined(_LONG_LONG)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
@@ -314,56 +253,45 @@
#elif defined(__370__)
# if defined(__IBMC__) || defined(__IBMCPP__)
# if defined(_ILP32)
-# define CURL_SIZEOF_LONG 4
# elif defined(_LP64)
-# define CURL_SIZEOF_LONG 8
# endif
# if defined(_LONG_LONG)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
#elif defined(TPF)
-# define CURL_SIZEOF_LONG 8
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__TINYC__) /* also known as tcc */
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
@@ -373,25 +301,20 @@
#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
defined(__i386) || defined(__sparcv8))
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64) || \
defined(__amd64) || defined(__sparcv9)
-# define CURL_SIZEOF_LONG 8
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
@@ -401,62 +324,51 @@
#elif defined(_MSC_VER)
# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
-# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
/* ===================================== */
/* KEEP GENERIC GCC THE LAST ENTRY */
/* ===================================== */
#elif defined(__GNUC__)
-# if !defined(__LP64__) && (defined(__ILP32__) || \
- defined(__i386__) || defined(__powerpc__) || defined(__arm__) || \
- defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
- defined(__XTENSA__) || (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4))
-# define CURL_SIZEOF_LONG 4
+# if !defined(__LP64__) && \
+ (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
+ defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
+ defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
+ defined(__XTENSA__) || \
+ (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64__) || \
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8)
-# define CURL_SIZEOF_LONG 8
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#else
/* generic "safe guess" on old 32 bit style */
-# define CURL_SIZEOF_LONG 4
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
-# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
@@ -465,6 +377,12 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#endif
+#ifdef _AIX
+/* AIX needs <sys/poll.h> */
+#define CURL_PULL_SYS_POLL_H
+#endif
+
+
/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */
/* ws2tcpip.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_WS2TCPIP_H
@@ -485,6 +403,12 @@
# include <sys/socket.h>
#endif
+/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
+/* sys/poll.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+
/* Data type definition of curl_socklen_t. */
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
diff --git a/include/gnurl/typecheck-gcc.h b/include/gnurl/typecheck-gcc.h
index 74548241b..10c74c764 100644
--- a/include/gnurl/typecheck-gcc.h
+++ b/include/gnurl/typecheck-gcc.h
@@ -96,6 +96,9 @@ __extension__ ({ \
if((_curl_opt) == CURLOPT_HTTPPOST) \
if(!_curl_is_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
+ if((_curl_opt) == CURLOPT_MIMEPOST) \
+ if(!_curl_is_ptr((value), curl_mime)) \
+ _curl_easy_setopt_err_curl_mimepost(); \
if(_curl_is_slist_option(_curl_opt)) \
if(!_curl_is_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
@@ -200,6 +203,9 @@ _CURL_WARNING(_curl_easy_setopt_err_postfields,
_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_mimepost,
+ "curl_easy_setopt expects a 'curl_mime *' "
+ "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,
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2aa1bb030..d99e49cf9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -66,21 +66,7 @@ endif
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
-if SONAME_BUMP
-#
-# Bumping of SONAME conditionally may seem like a weird thing to do, and yeah
-# it is. The problem is that we try to avoid the bump as hard as possible, but
-# yet it is still necessary for a few rare situations. The configure script will
-# attempt to figure out these situations, and it can be forced to consider this
-# to be such a case! See README.curl_off_t for further details.
-#
-# This conditional soname bump SHOULD be removed at next "proper" bump.
-#
-VERSIONINFO=-version-info 9:0:4
-else
-VERSIONINFO=-version-info 8:0:4
-endif
-
+VERSIONINFO=-version-info 9:0:5
# This flag accepts an argument of the form current[:revision[:age]]. So,
# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
# 1.
@@ -106,6 +92,10 @@ libgnurl_la_CFLAGS_EXTRA =
libgnurl_la_LDFLAGS_EXTRA += $(CODE_COVERAGE_LDFLAGS)
libgnurl_la_CFLAGS_EXTRA += $(CODE_COVERAGE_CFLAGS)
+@CODE_COVERAGE_RULES@
+libcurl_la_LDFLAGS_EXTRA += $(CODE_COVERAGE_LDFLAGS)
+libcurl_la_CFLAGS_EXTRA += $(CODE_COVERAGE_CFLAGS)
+
if CURL_LT_SHLIB_USE_VERSION_INFO
libgnurl_la_LDFLAGS_EXTRA += $(VERSIONINFO)
endif
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 19f58000a..5c0b930cf 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -53,7 +53,8 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
- x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c
+ x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \
+ mime.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 \
@@ -72,7 +73,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
- curl_printf.h system_win32.h rand.h
+ curl_printf.h system_win32.h rand.h mime.h
LIB_RCFILES = libcurl.rc
diff --git a/lib/Makefile.m32 b/lib/Makefile.m32
index 8e4c70333..22efbdee0 100644
--- a/lib/Makefile.m32
+++ b/lib/Makefile.m32
@@ -50,9 +50,9 @@ endif
ifndef LIBRTMP_PATH
LIBRTMP_PATH = ../../librtmp-2.4
endif
-# Edit the path below to point to the base of your libidn package.
-ifndef LIBIDN_PATH
-LIBIDN_PATH = ../../libidn-1.32
+# Edit the path below to point to the base of your libidn2 package.
+ifndef LIBIDN2_PATH
+LIBIDN2_PATH = ../../libidn2-2.0.3
endif
# Edit the path below to point to the base of your MS IDN package.
# Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1
@@ -153,9 +153,7 @@ ZLIB = 1
endif
ifeq ($(findstring -ssh2,$(CFG)),-ssh2)
SSH2 = 1
-ifneq ($(findstring -winssl,$(CFG)),-winssl)
SSL = 1
-endif
ZLIB = 1
endif
ifeq ($(findstring -ssl,$(CFG)),-ssl)
@@ -167,8 +165,8 @@ endif
ifeq ($(findstring -zlib,$(CFG)),-zlib)
ZLIB = 1
endif
-ifeq ($(findstring -idn,$(CFG)),-idn)
-IDN = 1
+ifeq ($(findstring -idn2,$(CFG)),-idn2)
+IDN2 = 1
endif
ifeq ($(findstring -winidn,$(CFG)),-winidn)
WINIDN = 1
@@ -192,6 +190,11 @@ endif
INCLUDES = -I. -I../include
CFLAGS += -DBUILDING_LIBCURL
+ifdef SSL
+ ifdef WINSSL
+ CFLAGS += -DCURL_WITH_MULTI_SSL
+ endif
+endif
ifdef SYNC
CFLAGS += -DUSE_SYNC_DNS
@@ -257,20 +260,20 @@ ifdef SSL
CFLAGS += -DHAVE_OPENSSL_SRP -DUSE_TLS_SRP
endif
endif
-else
+endif
ifdef WINSSL
+ CFLAGS += -DUSE_SCHANNEL
DLL_LIBS += -lcrypt32
endif
-endif
ifdef ZLIB
INCLUDES += -I"$(ZLIB_PATH)"
CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
DLL_LIBS += -L"$(ZLIB_PATH)" -lz
endif
-ifdef IDN
- INCLUDES += -I"$(LIBIDN_PATH)/include"
- CFLAGS += -DUSE_LIBIDN
- DLL_LIBS += -L"$(LIBIDN_PATH)/lib" -lidn
+ifdef IDN2
+ INCLUDES += -I"$(LIBIDN2_PATH)/include"
+ CFLAGS += -DUSE_LIBIDN2
+ DLL_LIBS += -L"$(LIBIDN2_PATH)/lib" -lidn2
else
ifdef WINIDN
CFLAGS += -DUSE_WIN32_IDN
@@ -280,9 +283,6 @@ endif
endif
ifdef SSPI
CFLAGS += -DUSE_WINDOWS_SSPI
- ifdef WINSSL
- CFLAGS += -DUSE_SCHANNEL
- endif
endif
ifdef SPNEGO
CFLAGS += -DHAVE_SPNEGO
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 9b6515cda..87e70b4d9 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -260,7 +260,7 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
bitmask = ares_getsock((ares_channel)data->state.resolver, socks,
ARES_GETSOCK_MAXNUM);
- for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
+ for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
pfd[i].events = 0;
pfd[i].revents = 0;
if(ARES_GETSOCK_READABLE(bitmask, i)) {
@@ -289,7 +289,7 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
ARES_SOCKET_BAD);
else {
/* move through the descriptors and ask for processing on them */
- for(i=0; i < num; i++)
+ 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,
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 8936b6033..a86772965 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -210,6 +210,10 @@ int init_thread_sync_data(struct thread_data * td,
tsd->td = td;
tsd->port = port;
+ /* Treat the request as done until the thread actually starts so any early
+ * cleanup gets done properly.
+ */
+ tsd->done = 1;
#ifdef HAVE_GETADDRINFO
DEBUGASSERT(hints);
tsd->hints = *hints;
@@ -380,11 +384,11 @@ static bool init_resolve_thread(struct connectdata *conn,
const struct addrinfo *hints)
{
struct thread_data *td = calloc(1, sizeof(struct thread_data));
- int err = RESOLVER_ENOMEM;
+ int err = ENOMEM;
conn->async.os_specific = (void *)td;
if(!td)
- goto err_exit;
+ goto errno_exit;
conn->async.port = port;
conn->async.done = FALSE;
@@ -392,14 +396,20 @@ static bool init_resolve_thread(struct connectdata *conn,
conn->async.dns = NULL;
td->thread_hnd = curl_thread_t_null;
- if(!init_thread_sync_data(td, hostname, port, hints))
- goto err_exit;
+ if(!init_thread_sync_data(td, hostname, port, hints)) {
+ conn->async.os_specific = NULL;
+ free(td);
+ goto errno_exit;
+ }
free(conn->async.hostname);
conn->async.hostname = strdup(hostname);
if(!conn->async.hostname)
goto err_exit;
+ /* The thread will set this to 1 when complete. */
+ td->tsd.done = 0;
+
#ifdef HAVE_GETADDRINFO
td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
#else
@@ -407,6 +417,8 @@ static bool init_resolve_thread(struct connectdata *conn,
#endif
if(!td->thread_hnd) {
+ /* The thread never started, so mark it as done here for proper cleanup. */
+ td->tsd.done = 1;
err = errno;
goto err_exit;
}
@@ -416,6 +428,7 @@ static bool init_resolve_thread(struct connectdata *conn,
err_exit:
destroy_async_data(&conn->async);
+ errno_exit:
errno = err;
return FALSE;
}
diff --git a/lib/checksrc.pl b/lib/checksrc.pl
index 2eff3e0cf..c1f74bebf 100755
--- a/lib/checksrc.pl
+++ b/lib/checksrc.pl
@@ -58,7 +58,11 @@ my %warnings = (
'OPENCOMMENT' => 'file ended with a /* comment still "open"',
'ASTERISKSPACE' => 'pointer declared with space after asterisk',
'ASTERISKNOSPACE' => 'pointer declared without space before asterisk',
- 'ASSIGNWITHINCONDITION' => 'assignment within conditional expression'
+ 'ASSIGNWITHINCONDITION' => 'assignment within conditional expression',
+ 'EQUALSNOSPACE' => 'equals sign without following space',
+ 'NOSPACEEQUALS' => 'equals sign without preceeding space',
+ 'SEMINOSPACE' => 'semicolon without following space',
+ 'MULTISPACE' => 'multiple spaces used when not suitable',
);
sub readwhitelist {
@@ -345,6 +349,9 @@ sub scanfile {
elsif($3 eq "return") {
# return must have a space
}
+ elsif($3 eq "case") {
+ # case must have a space
+ }
elsif($4 eq "*") {
# (* beginning makes the space OK!
}
@@ -523,6 +530,52 @@ sub scanfile {
"wrongly placed open brace");
}
}
+
+ # check for equals sign without spaces next to it
+ if($nostr =~ /(.*)\=[a-z0-9]/i) {
+ checkwarn("EQUALSNOSPACE",
+ $line, length($1)+1, $file, $ol,
+ "no space after equals sign");
+ }
+ # check for equals sign without spaces before it
+ elsif($nostr =~ /(.*)[a-z0-9]\=/i) {
+ checkwarn("NOSPACEEQUALS",
+ $line, length($1)+1, $file, $ol,
+ "no space before equals sign");
+ }
+
+ # check for plus signs without spaces next to it
+ if($nostr =~ /(.*)[^+]\+[a-z0-9]/i) {
+ checkwarn("PLUSNOSPACE",
+ $line, length($1)+1, $file, $ol,
+ "no space after plus sign");
+ }
+ # check for plus sign without spaces before it
+ elsif($nostr =~ /(.*)[a-z0-9]\+[^+]/i) {
+ checkwarn("NOSPACEPLUS",
+ $line, length($1)+1, $file, $ol,
+ "no space before plus sign");
+ }
+
+ # check for semicolons without space next to it
+ if($nostr =~ /(.*)\;[a-z0-9]/i) {
+ checkwarn("SEMINOSPACE",
+ $line, length($1)+1, $file, $ol,
+ "no space after semilcolon");
+ }
+
+ # check for more than one consecutive space before open brace or
+ # question mark. Skip lines containing strings since they make it hard
+ # due to artificially getting multiple spaces
+ if(($l eq $nostr) &&
+ $nostr =~ /^(.*(\S)) + [{?]/i) {
+ checkwarn("MULTISPACE",
+ $line, length($1)+1, $file, $ol,
+ "multiple space");
+ print STDERR "L: $l\n";
+ print STDERR "nostr: $nostr\n";
+ }
+
$line++;
$prevl = $ol;
}
diff --git a/lib/config-dos.h b/lib/config-dos.h
index f2c9ff403..eec7af988 100644
--- a/lib/config-dos.h
+++ b/lib/config-dos.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,8 +40,10 @@
#define PACKAGE "curl"
#define HAVE_ARPA_INET_H 1
+#define HAVE_ASSERT_H 1
#define HAVE_ERRNO_H 1
#define HAVE_FCNTL_H 1
+#define HAVE_FREEADDRINFO 1
#define HAVE_GETADDRINFO 1
#define HAVE_GETNAMEINFO 1
#define HAVE_GETPROTOBYNAME 1
@@ -85,9 +87,11 @@
#define RETSIGTYPE void
#define SIZEOF_INT 4
+#define SIZEOF_LONG 4
#define SIZEOF_LONG_DOUBLE 16
#define SIZEOF_SHORT 2
#define SIZEOF_SIZE_T 4
+#define SIZEOF_CURL_OFF_T 4
#define STDC_HEADERS 1
#define TIME_WITH_SYS_TIME 1
diff --git a/lib/config-tpf.h b/lib/config-tpf.h
index d1714fdfc..d1eb3d906 100644
--- a/lib/config-tpf.h
+++ b/lib/config-tpf.h
@@ -618,6 +618,9 @@
/* The size of `short', as computed by sizeof. */
#define SIZEOF_SHORT 2
+/* Define to the size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 8
diff --git a/lib/config-win32.h b/lib/config-win32.h
index 4cac859cd..00191fe4c 100644
--- a/lib/config-win32.h
+++ b/lib/config-win32.h
@@ -399,6 +399,9 @@
/* Define to the size of `short', as computed by sizeof. */
#define SIZEOF_SHORT 2
+/* Define to the size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
/* Define to the size of `size_t', as computed by sizeof. */
#if defined(_WIN64)
# define SIZEOF_SIZE_T 8
@@ -406,6 +409,9 @@
# define SIZEOF_SIZE_T 4
#endif
+/* Define to the size of `curl_off_t', as computed by sizeof. */
+#define SIZEOF_CURL_OFF_T 8
+
/* ---------------------------------------------------------------- */
/* BSD-style lwIP TCP/IP stack SPECIFIC */
/* ---------------------------------------------------------------- */
diff --git a/lib/config-win32ce.h b/lib/config-win32ce.h
index eb444c585..28a15f2a1 100644
--- a/lib/config-win32ce.h
+++ b/lib/config-win32ce.h
@@ -346,6 +346,9 @@
/* The size of `short', as computed by sizeof. */
#define SIZEOF_SHORT 2
+/* Define to the size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
/* The size of `size_t', as computed by sizeof. */
#if defined(_WIN64)
# define SIZEOF_SIZE_T 8
diff --git a/lib/connect.c b/lib/connect.c
index 8d5d32ba6..b7d10af55 100644..100755
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -249,7 +249,7 @@ static CURLcode bindlocal(struct connectdata *conn,
struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
#endif
- struct Curl_dns_entry *h=NULL;
+ 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 */
@@ -319,7 +319,7 @@ static CURLcode bindlocal(struct connectdata *conn,
* as a hostname or ip address.
*/
if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
- dev, (curl_socklen_t)strlen(dev)+1) != 0) {
+ 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",
@@ -748,7 +748,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
- for(i=0; i<2; i++) {
+ for(i = 0; i<2; i++) {
const int other = i ^ 1;
if(conn->tempsock[i] == CURL_SOCKET_BAD)
continue;
@@ -900,7 +900,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
static void nosigpipe(struct connectdata *conn,
curl_socket_t sockfd)
{
- struct Curl_easy *data= conn->data;
+ struct Curl_easy *data = conn->data;
int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0)
@@ -1059,16 +1059,25 @@ static CURLcode singleipconnect(struct connectdata *conn,
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
if(conn->bits.tcp_fastopen) {
#if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
- sa_endpoints_t endpoints;
- endpoints.sae_srcif = 0;
- endpoints.sae_srcaddr = NULL;
- endpoints.sae_srcaddrlen = 0;
- endpoints.sae_dstaddr = &addr.sa_addr;
- endpoints.sae_dstaddrlen = addr.addrlen;
-
- rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
- CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
- NULL, 0, NULL, NULL);
+#ifdef HAVE_BUILTIN_AVAILABLE
+ if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
+#endif /* HAVE_BUILTIN_AVAILABLE */
+ sa_endpoints_t endpoints;
+ endpoints.sae_srcif = 0;
+ endpoints.sae_srcaddr = NULL;
+ endpoints.sae_srcaddrlen = 0;
+ endpoints.sae_dstaddr = &addr.sa_addr;
+ endpoints.sae_dstaddrlen = addr.addrlen;
+
+ rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
+ CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
+ NULL, 0, NULL, NULL);
+#ifdef HAVE_BUILTIN_AVAILABLE
+ }
+ else {
+ rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+ }
+#endif /* HAVE_BUILTIN_AVAILABLE */
#elif defined(MSG_FASTOPEN) /* Linux */
if(conn->given->flags & PROTOPT_SSL)
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
@@ -1152,7 +1161,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
conn->tempaddr[1] = NULL;
conn->tempsock[0] = CURL_SOCKET_BAD;
conn->tempsock[1] = CURL_SOCKET_BAD;
- Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
/* Max time for the next connection attempt */
conn->timeoutms_per_addr =
@@ -1173,6 +1181,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
}
data->info.numconnects++; /* to track the number of connections made */
+ Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
return CURLE_OK;
}
@@ -1324,7 +1333,7 @@ CURLcode Curl_socket(struct connectdata *conn,
addr->family = ai->ai_family;
addr->socktype = conn->socktype;
- addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
+ addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
addr->addrlen = ai->ai_addrlen;
if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index cfec87c57..b1a540f03 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -227,7 +227,7 @@ static enum {
extra_len = (data[1] << 8) | data[0];
- if(len < (extra_len+2))
+ if(len < (extra_len + 2))
return GZIP_UNDERFLOW;
len -= (extra_len + 2);
@@ -288,7 +288,7 @@ Curl_unencode_gzip_write(struct connectdata *conn,
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) {
+ if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
return process_zlib_error(conn, z);
}
k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
diff --git a/lib/cookie.c b/lib/cookie.c
index 6b678aeb8..271f6d49d 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -125,7 +125,7 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
if(hostname_len < cookie_domain_len)
return FALSE;
- if(!strcasecompare(cooke_domain, hostname+hostname_len-cookie_domain_len))
+ if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len))
return FALSE;
/* A lead char of cookie_domain is not '.'.
@@ -375,9 +375,8 @@ Curl_cookie_add(struct Curl_easy *data,
unless set */
{
struct Cookie *clist;
- char name[MAX_NAME];
struct Cookie *co;
- struct Cookie *lastc=NULL;
+ struct Cookie *lastc = NULL;
time_t now = time(NULL);
bool replace_old = FALSE;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
@@ -397,17 +396,19 @@ Curl_cookie_add(struct Curl_easy *data,
if(httpheader) {
/* This line was read off a HTTP-header */
+ char name[MAX_NAME];
+ char what[MAX_NAME];
const char *ptr;
const char *semiptr;
- char *what;
- what = malloc(MAX_COOKIE_LINE);
- if(!what) {
+ size_t linelength = strlen(lineptr);
+ if(linelength > MAX_COOKIE_LINE) {
+ /* discard overly long lines at once */
free(co);
return NULL;
}
- semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
+ semiptr = strchr(lineptr, ';'); /* first, find a semicolon */
while(*lineptr && ISBLANK(*lineptr))
lineptr++;
@@ -415,9 +416,9 @@ Curl_cookie_add(struct Curl_easy *data,
ptr = lineptr;
do {
/* we have a <what>=<this> pair or a stand-alone word here */
- name[0]=what[0]=0; /* init the buffers */
+ name[0] = what[0] = 0; /* init the buffers */
if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
- MAX_COOKIE_LINE_TXT "[^;\r\n]",
+ MAX_NAME_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,
@@ -425,10 +426,24 @@ Curl_cookie_add(struct Curl_easy *data,
const char *whatptr;
bool done = FALSE;
bool sep;
- size_t len=strlen(what);
+ size_t len = strlen(what);
size_t nlen = strlen(name);
const char *endofn = &ptr[ nlen ];
+ infof(data, "cookie size: name/val %d + %d bytes\n",
+ nlen, len);
+
+ if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
+ ((nlen + len) > MAX_NAME)) {
+ /* too long individual name or contents, or too long combination of
+ name + contents. Chrome and Firefox support 4095 or 4096 bytes
+ combo. */
+ freecookie(co);
+ infof(data, "oversized cookie dropped, name/val %d + %d bytes\n",
+ nlen, len);
+ return NULL;
+ }
+
/* name ends with a '=' ? */
sep = (*endofn == '=')?TRUE:FALSE;
@@ -440,18 +455,18 @@ Curl_cookie_add(struct Curl_easy *data,
endofn--;
nlen--;
}
- name[nlen]=0; /* new end of name */
+ name[nlen] = 0; /* new end of name */
}
}
/* Strip off trailing whitespace from the 'what' */
while(len && ISBLANK(what[len-1])) {
- what[len-1]=0;
+ what[len-1] = 0;
len--;
}
/* Skip leading whitespace from the 'what' */
- whatptr=what;
+ whatptr = what;
while(*whatptr && ISBLANK(*whatptr))
whatptr++;
@@ -484,6 +499,7 @@ Curl_cookie_add(struct Curl_easy *data,
badcookie = TRUE; /* out of memory bad */
break;
}
+ free(co->spath); /* if this is set again */
co->spath = sanitize_cookie_path(co->path);
if(!co->spath) {
badcookie = TRUE; /* out of memory bad */
@@ -510,7 +526,7 @@ Curl_cookie_add(struct Curl_easy *data,
/* check for more dots */
dotp = strchr(whatptr, '.');
if(!dotp && !strcasecompare("localhost", whatptr))
- domain=":";
+ domain = ":";
}
#endif
@@ -525,14 +541,14 @@ Curl_cookie_add(struct Curl_easy *data,
break;
}
if(!is_ip)
- co->tailmatch=TRUE; /* we always do that if the domain name was
- given */
+ 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;
+ badcookie = TRUE;
infof(data, "skipped cookie with bad tailmatch domain: %s\n",
whatptr);
}
@@ -581,26 +597,32 @@ Curl_cookie_add(struct Curl_easy *data,
continue;
}
- ptr=semiptr+1;
+ ptr = semiptr + 1;
while(*ptr && ISBLANK(*ptr))
ptr++;
- semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
+ semiptr = strchr(ptr, ';'); /* now, find the next semicolon */
if(!semiptr && *ptr)
/* There are no more semicolons, but there's a final name=value pair
coming up */
- semiptr=strchr(ptr, '\0');
+ 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 */
+ CURLofft offt;
+ offt = curlx_strtoofft((*co->maxage == '\"')?
+ &co->maxage[1]:&co->maxage[0], NULL, 10,
+ &co->expires);
+ if(offt == CURL_OFFT_FLOW)
+ /* overflow, used max value */
co->expires = CURL_OFF_T_MAX;
- else
- co->expires += now;
+ else if(!offt) {
+ if(CURL_OFF_T_MAX - now < co->expires)
+ /* would 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,
@@ -619,7 +641,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(!badcookie && !co->domain) {
if(domain) {
/* no domain was given in the header line, set the default */
- co->domain=strdup(domain);
+ co->domain = strdup(domain);
if(!co->domain)
badcookie = TRUE;
}
@@ -639,11 +661,11 @@ Curl_cookie_add(struct Curl_easy *data,
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 */
+ size_t pathlen = (size_t)(endslash-path + 1); /* include end 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->path[pathlen] = 0; /* zero terminate */
co->spath = sanitize_cookie_path(co->path);
if(!co->spath)
badcookie = TRUE; /* out of memory bad */
@@ -653,8 +675,6 @@ Curl_cookie_add(struct Curl_easy *data,
}
}
- free(what);
-
if(badcookie || !co->name) {
/* we didn't get a cookie name or a bad one,
this is an illegal line, bail out */
@@ -668,7 +688,7 @@ Curl_cookie_add(struct Curl_easy *data,
reading the odd netscape cookies-file format here */
char *ptr;
char *firstptr;
- char *tok_buf=NULL;
+ char *tok_buf = NULL;
int fields;
/* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
@@ -689,19 +709,19 @@ Curl_cookie_add(struct Curl_easy *data,
return NULL;
}
/* strip off the possible end-of-line characters */
- ptr=strchr(lineptr, '\r');
+ ptr = strchr(lineptr, '\r');
if(ptr)
- *ptr=0; /* clear it */
- ptr=strchr(lineptr, '\n');
+ *ptr = 0; /* clear it */
+ ptr = strchr(lineptr, '\n');
if(ptr)
- *ptr=0; /* clear it */
+ *ptr = 0; /* clear it */
- firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
+ 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++) {
+ 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 */
@@ -753,7 +773,8 @@ Curl_cookie_add(struct Curl_easy *data,
co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
break;
case 4:
- co->expires = curlx_strtoofft(ptr, NULL, 10);
+ if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
+ badcookie = TRUE;
break;
case 5:
co->name = strdup(ptr);
@@ -828,7 +849,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(strcasecompare(clist->domain, co->domain) &&
(clist->tailmatch == co->tailmatch))
/* The domains are identical */
- replace_old=TRUE;
+ replace_old = TRUE;
}
else if(!clist->domain && !co->domain)
replace_old = TRUE;
@@ -957,7 +978,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
{
struct CookieInfo *c;
FILE *fp = NULL;
- bool fromfile=TRUE;
+ bool fromfile = TRUE;
char *line = NULL;
if(NULL == inc) {
@@ -977,7 +998,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
if(file && !strcmp(file, "-")) {
fp = stdin;
- fromfile=FALSE;
+ fromfile = FALSE;
}
else if(file && !*file) {
/* points to a "" string */
@@ -998,12 +1019,12 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
while(get_line(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
- lineptr=&line[11];
- headerline=TRUE;
+ lineptr = &line[11];
+ headerline = TRUE;
}
else {
- lineptr=line;
- headerline=FALSE;
+ lineptr = line;
+ headerline = FALSE;
}
while(*lineptr && ISBLANK(*lineptr))
lineptr++;
@@ -1113,7 +1134,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
struct Cookie *newco;
struct Cookie *co;
time_t now = time(NULL);
- struct Cookie *mainco=NULL;
+ struct Cookie *mainco = NULL;
size_t matches = 0;
bool is_ip;
@@ -1185,7 +1206,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
co = mainco;
- for(i=0; co; co = co->next)
+ for(i = 0; co; co = co->next)
array[i++] = co;
/* now sort the cookie pointers in path length order */
@@ -1194,8 +1215,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* 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];
+ 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 */
@@ -1335,7 +1356,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
{
struct Cookie *co;
FILE *out;
- bool use_stdout=FALSE;
+ bool use_stdout = FALSE;
char *format_ptr;
if((NULL == c) || (0 == c->numcookies))
@@ -1349,7 +1370,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
- use_stdout=TRUE;
+ use_stdout = TRUE;
}
else {
out = fopen(dumphere, FOPEN_WRITETEXT);
@@ -1382,7 +1403,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
return 0;
}
-struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
+static struct curl_slist *cookie_list(struct Curl_easy *data)
{
struct curl_slist *list = NULL;
struct curl_slist *beg;
@@ -1413,6 +1434,15 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
return list;
}
+struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
+{
+ struct curl_slist *list;
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ list = cookie_list(data);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ return list;
+}
+
void Curl_flush_cookies(struct Curl_easy *data, int cleanup)
{
if(data->set.str[STRING_COOKIEJAR]) {
diff --git a/lib/cookie.h b/lib/cookie.h
index 41c315a82..bb13dacea 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -62,13 +62,16 @@ struct CookieInfo {
that comprise the cookie non-terminal in the syntax description of the
Set-Cookie header)"
+ We allow max 5000 bytes cookie header. Max 4095 bytes length per cookie
+ name and value. Name + value may not exceed 4096 bytes.
+
*/
#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"
+/* This is the maximum length of a cookie name or content we deal with: */
+#define MAX_NAME 4096
+#define MAX_NAME_TXT "4095"
struct Curl_easy;
/*
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index 3da23fda9..1f0ebb813 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -286,7 +286,7 @@ Curl_he2ai(const struct hostent *he, int port)
DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
- for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) {
+ for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
size_t ss_size;
#ifdef ENABLE_IPV6
@@ -570,9 +570,9 @@ curl_dogetaddrinfo(const char *hostname,
int line, const char *source)
{
#ifdef USE_LWIPSOCK
- int res=lwip_getaddrinfo(hostname, service, hints, result);
+ int res = lwip_getaddrinfo(hostname, service, hints, result);
#else
- int res=(getaddrinfo)(hostname, service, hints, result);
+ int res = (getaddrinfo)(hostname, service, hints, result);
#endif
if(0 == res)
/* success */
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index c1452b3e7..c80484f65 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -51,9 +51,6 @@
/* to disable RTSP */
#cmakedefine CURL_DISABLE_RTSP 1
-/* to disable RTMP */
-#cmakedefine CURL_DISABLE_RTMP 1
-
/* to disable SMB */
#cmakedefine CURL_DISABLE_SMB 1
@@ -82,9 +79,6 @@
/* when not building a shared library */
#cmakedefine CURL_STATICLIB 1
-/* Set to explicitly specify we don't want to use thread-safe functions */
-#cmakedefine DISABLED_THREADSAFE 1
-
/* your Entropy Gathering Daemon socket pathname */
#cmakedefine EGD_SOCKET ${EGD_SOCKET}
@@ -894,6 +888,9 @@
/* The size of `off_t', as computed by sizeof. */
#cmakedefine SIZEOF_OFF_T ${SIZEOF_OFF_T}
+/* The size of `curl_off_t', as computed by sizeof. */
+#cmakedefine SIZEOF_CURL_OFF_T ${SIZEOF_CURL_OFF_T}
+
/* The size of `size_t', as computed by sizeof. */
#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T}
diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c
index e9224ada5..6a7267d07 100644
--- a/lib/curl_fnmatch.c
+++ b/lib/curl_fnmatch.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -151,7 +151,7 @@ static int setcharset(unsigned char **p, unsigned char *charset)
(*p)++;
}
else if(c == '[') {
- char c2 = *((*p)+1);
+ char c2 = *((*p) + 1);
if(c2 == ':') { /* there has to be a keyword */
(*p) += 2;
if(parsekeyword(p, charset)) {
@@ -319,9 +319,9 @@ static int loop(const unsigned char *pattern, const unsigned char *string)
switch(state) {
case CURLFNM_LOOP_DEFAULT:
if(*p == '*') {
- while(*(p+1) == '*') /* eliminate multiple stars */
+ while(*(p + 1) == '*') /* eliminate multiple stars */
p++;
- if(*s == '\0' && *(p+1) == '\0')
+ 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)
@@ -351,7 +351,7 @@ static int loop(const unsigned char *pattern, const unsigned char *string)
p++;
}
else if(*p == '[') {
- unsigned char *pp = p+1; /* cannot handle with pointer to register */
+ unsigned char *pp = p + 1; /* cannot handle with pointer to register */
if(setcharset(&pp, charset)) {
int found = FALSE;
if(charset[(unsigned int)*s])
@@ -381,7 +381,7 @@ static int loop(const unsigned char *pattern, const unsigned char *string)
found = !found;
if(found) {
- p = pp+1;
+ p = pp + 1;
s++;
memset(charset, 0, CURLFNM_CHSET_SIZE);
}
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index aea545295..5154949e6 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,6 +31,25 @@
* https://www.innovation.ch/java/ntlm.html
*/
+/* Please keep the SSL backend-specific #if branches in this order:
+
+ 1. USE_OPENSSL
+ 2. USE_GNUTLS_NETTLE
+ 3. USE_GNUTLS
+ 4. USE_NSS
+ 5. USE_MBEDTLS
+ 6. USE_DARWINSSL
+ 7. USE_OS400CRYPTO
+ 8. USE_WIN32_CRYPTO
+
+ This ensures that:
+ - the same SSL branch gets activated throughout this source
+ file even if multiple backends are enabled at the same time.
+ - OpenSSL and NSS have higher priority than Windows Crypt, due
+ to issues with the latter supporting NTLM2Session responses
+ in NTLM type-3 messages.
+ */
+
#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
#ifdef USE_OPENSSL
@@ -76,14 +95,6 @@
# define MD5_DIGEST_LENGTH 16
# define MD4_DIGEST_LENGTH 16
-#elif defined(USE_MBEDTLS)
-
-# include <mbedtls/des.h>
-# include <mbedtls/md4.h>
-# if !defined(MBEDTLS_MD4_C)
-# include "curl_md4.h"
-# endif
-
#elif defined(USE_NSS)
# include <nss.h>
@@ -92,6 +103,14 @@
# include "curl_md4.h"
# define MD5_DIGEST_LENGTH MD5_LENGTH
+#elif defined(USE_MBEDTLS)
+
+# include <mbedtls/des.h>
+# include <mbedtls/md4.h>
+# if !defined(MBEDTLS_MD4_C)
+# include "curl_md4.h"
+# endif
+
#elif defined(USE_DARWINSSL)
# include <CommonCrypto/CommonCryptor.h>
@@ -196,26 +215,6 @@ static void setup_des_key(const unsigned char *key_56,
gcry_cipher_setkey(*des, key, sizeof(key));
}
-#elif defined(USE_MBEDTLS)
-
-static bool encrypt_des(const unsigned char *in, unsigned char *out,
- const unsigned char *key_56)
-{
- mbedtls_des_context ctx;
- char key[8];
-
- /* Expand the 56-bit key to 64-bits */
- extend_key_56_to_64(key_56, key);
-
- /* Set the key parity to odd */
- mbedtls_des_key_set_parity((unsigned char *) key);
-
- /* Perform the encryption */
- mbedtls_des_init(&ctx);
- mbedtls_des_setkey_enc(&ctx, (unsigned char *) key);
- return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
-}
-
#elif defined(USE_NSS)
/*
@@ -281,6 +280,26 @@ fail:
return rv;
}
+#elif defined(USE_MBEDTLS)
+
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+ const unsigned char *key_56)
+{
+ mbedtls_des_context ctx;
+ char key[8];
+
+ /* Expand the 56-bit key to 64-bits */
+ extend_key_56_to_64(key_56, key);
+
+ /* Set the key parity to odd */
+ mbedtls_des_key_set_parity((unsigned char *) key);
+
+ /* Perform the encryption */
+ mbedtls_des_init(&ctx);
+ mbedtls_des_setkey_enc(&ctx, (unsigned char *) key);
+ return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
+}
+
#elif defined(USE_DARWINSSL)
static bool encrypt_des(const unsigned char *in, unsigned char *out,
@@ -428,7 +447,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
setup_des_key(keys + 14, &des);
gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
gcry_cipher_close(des);
-#elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
@@ -492,7 +511,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
setup_des_key(pw + 7, &des);
gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
gcry_cipher_close(des);
-#elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw);
encrypt_des(magic, lmbuffer + 8, pw + 7);
@@ -571,13 +590,18 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
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) || defined(USE_OS400CRYPTO) || \
- (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
+#elif defined(USE_NSS)
Curl_md4it(ntbuffer, pw, 2 * len);
#elif defined(USE_MBEDTLS)
+#if defined(MBEDTLS_MD4_C)
mbedtls_md4(pw, 2 * len, ntbuffer);
+#else
+ Curl_md4it(ntbuffer, pw, 2 * len);
+#endif
#elif defined(USE_DARWINSSL)
(void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
+#elif defined(USE_OS400CRYPTO)
+ Curl_md4it(ntbuffer, pw, 2 * len);
#elif defined(USE_WIN32_CRYPTO)
HCRYPTPROV hprov;
if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
@@ -780,7 +804,7 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
/* Concatenate the HMAC MD5 output with the client nonce */
memcpy(lmresp, hmac_output, 16);
- memcpy(lmresp+16, challenge_client, 8);
+ memcpy(lmresp + 16, challenge_client, 8);
return result;
}
diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h
index 4a83d40bc..07ef5deae 100644
--- a/lib/curl_ntlm_core.h
+++ b/lib/curl_ntlm_core.h
@@ -26,13 +26,19 @@
#if defined(USE_NTLM)
+/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
+ then it must be initialized to be used by NTLM. */
+#if !defined(USE_OPENSSL) && \
+ !defined(USE_GNUTLS_NETTLE) && \
+ !defined(USE_GNUTLS) && \
+ defined(USE_NSS)
+#define NTLM_NEEDS_NSS_INIT
+#endif
+
#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
#ifdef USE_OPENSSL
-# 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
+# include <openssl/ssl.h>
#endif
/* Define USE_NTRESPONSES in order to make the type-3 message include
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index 9e9586cc3..03f47a3a5 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,6 +48,7 @@
#include "sendf.h"
#include "select.h"
#include "vauth/ntlm.h"
+#include "curl_ntlm_core.h"
#include "curl_ntlm_wb.h"
#include "url.h"
#include "strerror.h"
@@ -357,7 +358,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
/* not set means empty */
if(!userp)
- userp="";
+ userp = "";
switch(ntlm->state) {
case NTLMSTATE_TYPE1:
@@ -413,7 +414,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
/* connection is already authenticated,
* don't send a header in future requests */
free(*allocuserpwd);
- *allocuserpwd=NULL;
+ *allocuserpwd = NULL;
authp->done = TRUE;
break;
}
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index bd3b2be9e..10a59aa5f 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -331,7 +331,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
sasl->authused = SASL_MECH_NTLM;
if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_ntlm_type1_message(conn->user, conn->passwd,
+ result = Curl_auth_create_ntlm_type1_message(data,
+ conn->user, conn->passwd,
&conn->ntlm, &resp, &len);
}
else
@@ -493,7 +494,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
#ifdef USE_NTLM
case SASL_NTLM:
/* Create the type-1 message */
- result = Curl_auth_create_ntlm_type1_message(conn->user, conn->passwd,
+ result = Curl_auth_create_ntlm_type1_message(data,
+ conn->user, conn->passwd,
&conn->ntlm, &resp, &len);
newstate = SASL_NTLM_TYPE2MSG;
break;
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 519d8e5c4..1034b5a78 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -141,14 +141,7 @@
#include <gnurl/curl.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
+#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T
/*
* Disable other protocols when http is the only one desired.
@@ -185,9 +178,6 @@
# ifndef CURL_DISABLE_SMTP
# define CURL_DISABLE_SMTP
# endif
-# ifndef CURL_DISABLE_RTMP
-# define CURL_DISABLE_RTMP
-# endif
# ifndef CURL_DISABLE_GOPHER
# define CURL_DISABLE_GOPHER
# endif
@@ -206,7 +196,7 @@
/* ================================================================ */
/* No system header file shall be included in this file before this */
-/* point. The only allowed ones are those included from gnurl/system.h */
+/* point. The only allowed ones are those included from curl/system.h */
/* ================================================================ */
/*
@@ -727,6 +717,7 @@ Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
#if defined(WIN32) || defined(MSDOS)
#define FOPEN_READTEXT "rt"
#define FOPEN_WRITETEXT "wt"
+#define FOPEN_APPENDTEXT "at"
#elif defined(__CYGWIN__)
/* Cygwin has specific behavior we need to address when WIN32 is not defined.
https://cygwin.com/cygwin-ug-net/using-textbinary.html
@@ -736,9 +727,11 @@ endings either CRLF or LF so 't' is appropriate.
*/
#define FOPEN_READTEXT "rt"
#define FOPEN_WRITETEXT "w"
+#define FOPEN_APPENDTEXT "a"
#else
#define FOPEN_READTEXT "r"
#define FOPEN_WRITETEXT "w"
+#define FOPEN_APPENDTEXT "a"
#endif
/* WinSock destroys recv() buffer when send() failed.
diff --git a/lib/dict.c b/lib/dict.c
index af0954855..e801cf704 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -98,7 +98,7 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
char *ptr;
size_t len;
char ch;
- int olen=0;
+ int olen = 0;
CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
if(!newp || result)
@@ -117,7 +117,7 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
}
dictp[olen++] = ch;
}
- dictp[olen]=0;
+ dictp[olen] = 0;
}
free(newp);
return dictp;
@@ -132,8 +132,8 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
char *strategy = NULL;
char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */
- CURLcode result=CURLE_OK;
- struct Curl_easy *data=conn->data;
+ CURLcode result = CURLE_OK;
+ struct Curl_easy *data = conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = data->state.path;
@@ -168,7 +168,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if((word == NULL) || (*word == (char)0)) {
infof(data, "lookup word is missing\n");
- word=(char *)"default";
+ word = (char *)"default";
}
if((database == NULL) || (*database == (char)0)) {
database = (char *)"!";
@@ -222,7 +222,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if((word == NULL) || (*word == (char)0)) {
infof(data, "lookup word is missing\n");
- word=(char *)"default";
+ word = (char *)"default";
}
if((database == NULL) || (*database == (char)0)) {
database = (char *)"!";
diff --git a/lib/dotdot.c b/lib/dotdot.c
index 818061d9f..936f1cdbd 100644
--- a/lib/dotdot.c
+++ b/lib/dotdot.c
@@ -55,7 +55,7 @@ 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 *out = malloc(inlen + 1);
char *outptr;
char *orgclone;
char *queryp;
@@ -92,25 +92,25 @@ char *Curl_dedotdotify(const char *input)
remove that prefix from the input buffer; otherwise, */
if(!strncmp("./", clone, 2)) {
- clone+=2;
- clen-=2;
+ clone += 2;
+ clen -= 2;
}
else if(!strncmp("../", clone, 3)) {
- clone+=3;
- clen-=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;
+ clone += 2;
+ clen -= 2;
}
else if(!strcmp("/.", clone)) {
clone[1]='/';
clone++;
- clen-=1;
+ clen -= 1;
}
/* C. if the input buffer begins with a prefix of "/../" or "/..", where
@@ -119,8 +119,8 @@ char *Curl_dedotdotify(const char *input)
any) from the output buffer; otherwise, */
else if(!strncmp("/../", clone, 4)) {
- clone+=3;
- clen-=3;
+ clone += 3;
+ clen -= 3;
/* remove the last segment from the output buffer */
while(outptr > out) {
outptr--;
@@ -131,8 +131,8 @@ char *Curl_dedotdotify(const char *input)
}
else if(!strcmp("/..", clone)) {
clone[2]='/';
- clone+=2;
- clen-=2;
+ clone += 2;
+ clen -= 2;
/* remove the last segment from the output buffer */
while(outptr > out) {
outptr--;
@@ -146,8 +146,8 @@ char *Curl_dedotdotify(const char *input)
that from the input buffer; otherwise, */
else if(!strcmp(".", clone) || !strcmp("..", clone)) {
- *clone=0;
- *out=0;
+ *clone = 0;
+ *out = 0;
}
else {
@@ -172,7 +172,7 @@ char *Curl_dedotdotify(const char *input)
from the correct index. */
size_t oindex = queryp - orgclone;
qlen = strlen(&input[oindex]);
- memcpy(outptr, &input[oindex], qlen+1); /* include the ending zero byte */
+ memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */
}
free(orgclone);
diff --git a/lib/easy.c b/lib/easy.c
index a1fd22b0d..894787191 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -433,7 +433,7 @@ static int events_timer(struct Curl_multi *multi, /* multi handle */
*/
static int poll2cselect(int pollmask)
{
- int omask=0;
+ int omask = 0;
if(pollmask & POLLIN)
omask |= CURL_CSELECT_IN;
if(pollmask & POLLOUT)
@@ -450,7 +450,7 @@ static int poll2cselect(int pollmask)
*/
static short socketcb2poll(int pollmask)
{
- short omask=0;
+ short omask = 0;
if(pollmask & CURL_POLL_IN)
omask |= POLLIN;
if(pollmask & CURL_POLL_OUT)
@@ -473,7 +473,7 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
{
struct events *ev = userp;
struct socketmonitor *m;
- struct socketmonitor *prev=NULL;
+ struct socketmonitor *prev = NULL;
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
(void) easy;
@@ -569,14 +569,14 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
struct socketmonitor *m;
struct pollfd *f;
struct pollfd fds[4];
- int numfds=0;
+ int numfds = 0;
int pollrc;
int i;
struct curltime before;
struct curltime after;
/* populate the fds[] array */
- for(m = ev->list, f=&fds[0]; m; m = m->next) {
+ for(m = ev->list, f = &fds[0]; m; m = m->next) {
f->fd = m->socket.fd;
f->events = m->socket.events;
f->revents = 0;
@@ -655,7 +655,7 @@ static CURLcode easy_events(struct Curl_multi *multi)
{
/* this struct is made static to allow it to be used after this function
returns and curl_multi_remove_handle() is called */
- static struct events evs= {2, FALSE, 0, NULL, 0};
+ static struct events evs = {2, FALSE, 0, NULL, 0};
/* if running event-based, do some further multi inits */
events_setup(multi, &evs);
@@ -1027,13 +1027,13 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
struct tempbuf writebuf[3]; /* there can only be three */
/* copy the structs to allow for immediate re-pausing */
- for(i=0; i < data->state.tempcount; i++) {
+ for(i = 0; i < data->state.tempcount; i++) {
writebuf[i] = data->state.tempwrite[i];
data->state.tempwrite[i].buf = NULL;
}
data->state.tempcount = 0;
- for(i=0; i < count; i++) {
+ for(i = 0; i < count; i++) {
/* even if one function returns error, this loops through and frees all
buffers */
if(!result)
diff --git a/lib/escape.c b/lib/escape.c
index 0b8b5317f..8c9449fd7 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -84,14 +84,14 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
char *testing_ptr = NULL;
unsigned char in; /* we need to treat the characters unsigned */
size_t newlen;
- size_t strindex=0;
+ size_t strindex = 0;
size_t length;
CURLcode result;
if(inlength < 0)
return NULL;
- alloc = (inlength?(size_t)inlength:strlen(string))+1;
+ alloc = (inlength?(size_t)inlength:strlen(string)) + 1;
newlen = alloc;
ns = malloc(alloc);
@@ -104,7 +104,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
if(Curl_isunreserved(in))
/* just copy this */
- ns[strindex++]=in;
+ ns[strindex++] = in;
else {
/* encode it */
newlen += 2; /* the size grows with two, since this'll become a %XX */
@@ -116,7 +116,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
ns = testing_ptr;
}
- result = Curl_convert_to_network(data, &in, 1);
+ result = Curl_convert_to_network(data, (char *)&in, 1);
if(result) {
/* Curl_convert_to_network calls failf if unsuccessful */
free(ns);
@@ -125,11 +125,11 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
snprintf(&ns[strindex], 4, "%%%02X", in);
- strindex+=3;
+ strindex += 3;
}
string++;
}
- ns[strindex]=0; /* terminate it */
+ ns[strindex] = 0; /* terminate it */
return ns;
}
@@ -148,10 +148,10 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
char **ostring, size_t *olen,
bool reject_ctrl)
{
- size_t alloc = (length?length:strlen(string))+1;
+ size_t alloc = (length?length:strlen(string)) + 1;
char *ns = malloc(alloc);
unsigned char in;
- size_t strindex=0;
+ size_t strindex = 0;
unsigned long hex;
CURLcode result;
@@ -173,15 +173,15 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
- result = Curl_convert_from_network(data, &in, 1);
+ result = Curl_convert_from_network(data, (char *)&in, 1);
if(result) {
/* Curl_convert_from_network calls failf if unsuccessful */
free(ns);
return result;
}
- string+=2;
- alloc-=2;
+ string += 2;
+ alloc -= 2;
}
if(reject_ctrl && (in < 0x20)) {
@@ -192,7 +192,7 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
ns[strindex++] = in;
string++;
}
- ns[strindex]=0; /* terminate it */
+ ns[strindex] = 0; /* terminate it */
if(olen)
/* store output size */
diff --git a/lib/file.c b/lib/file.c
index acca6ec08..25f8005af 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -133,37 +133,42 @@ static CURLcode file_setup_connection(struct connectdata *conn)
static CURLcode file_range(struct connectdata *conn)
{
curl_off_t from, to;
- curl_off_t totalsize=-1;
+ curl_off_t totalsize = -1;
char *ptr;
char *ptr2;
struct Curl_easy *data = conn->data;
if(data->state.use_range && data->state.range) {
- from=curlx_strtoofft(data->state.range, &ptr, 0);
- while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+ CURLofft from_t;
+ CURLofft to_t;
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+ if(from_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ 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)) {
+ to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+ if(to_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ if((to_t == CURL_OFFT_INVAL) && !from_t) {
/* 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) {
+ else if((from_t == CURL_OFFT_INVAL) && !to_t) {
/* -Y */
- data->req.maxdownload = -from;
- data->state.resume_from = from;
+ data->req.maxdownload = to;
+ data->state.resume_from = -to;
DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- -from));
+ to));
}
else {
/* X-Y */
totalsize = to-from;
- data->req.maxdownload = totalsize+1; /* include last byte */
+ if(totalsize == CURL_OFF_T_MAX)
+ /* this is too big to increase, so bail out */
+ return CURLE_RANGE_ERROR;
+ 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",
@@ -226,7 +231,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
}
/* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
- for(i=0; i < real_path_len; ++i)
+ for(i = 0; i < real_path_len; ++i)
if(actual_path[i] == '/')
actual_path[i] = '\\';
else if(!actual_path[i]) { /* binary zero */
@@ -428,9 +433,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
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;
+ curl_off_t expected_size = 0;
bool size_known;
- bool fstated=FALSE;
+ bool fstated = FALSE;
ssize_t nread;
struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
diff --git a/lib/formdata.c b/lib/formdata.c
index 2d7b6b627..1037d0ec8 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -32,6 +32,8 @@
#include "urldata.h" /* for struct Curl_easy */
#include "formdata.h"
+#include "mime.h"
+#include "non-ascii.h"
#include "vtls/vtls.h"
#include "strcase.h"
#include "sendf.h"
@@ -42,14 +44,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-#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 CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len);
-
/* What kind of Content-Type to use on un-specified files with unrecognized
extensions. */
#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
@@ -197,7 +191,7 @@ static const char *ContentTypeForFilename(const char *filename,
contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
if(filename) { /* in case a NULL was passed in */
- for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
+ for(i = 0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
if(strlen(filename) >= strlen(ctts[i].extension)) {
if(strcasecompare(filename +
strlen(filename) - strlen(ctts[i].extension),
@@ -272,7 +266,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
struct curl_httppost *post = NULL;
CURLformoption option;
struct curl_forms *forms = NULL;
- char *array_value=NULL; /* value read from an array */
+ 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
@@ -641,15 +635,26 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
}
form->contenttype_alloc = TRUE;
}
+ if(form->name && form->namelength) {
+ /* Name should not contain nul bytes. */
+ size_t i;
+ for(i = 0; i < form->namelength; i++)
+ if(!form->name[i]) {
+ return_value = CURL_FORMADD_NULL;
+ break;
+ }
+ if(return_value != CURL_FORMADD_OK)
+ break;
+ }
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) */
+ /* copy name (without strdup; possibly not nul-terminated) */
form->name = Curl_memdup(form->name, form->namelength?
form->namelength:
- strlen(form->name)+1);
+ strlen(form->name) + 1);
}
if(!form->name) {
return_value = CURL_FORMADD_MEMORY;
@@ -663,7 +668,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
/* copy value (without strdup; possibly contains null characters) */
size_t clen = (size_t) form->contentslength;
if(!clen)
- clen = strlen(form->value)+1;
+ clen = strlen(form->value) + 1;
form->value = Curl_memdup(form->value, clen);
@@ -746,211 +751,6 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
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, FOPEN_READTEXT); /* VMS */
- 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,
- curl_off_t length,
- curl_off_t *size)
-{
- struct FormData *newform;
- char *alloc2 = NULL;
- CURLcode result = CURLE_OK;
- if(length < 0 || (size && *size < 0))
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- 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);
-#if (SIZEOF_SIZE_T < CURL_SIZEOF_CURL_OFF_T)
- else if(length >= (curl_off_t)(size_t)-1) {
- result = CURLE_BAD_FUNCTION_ARGUMENT;
- goto error;
- }
-#endif
- if(type != FORM_DATAMEM) {
- newform->line = malloc((size_t)length+1);
- if(!newform->line) {
- result = CURLE_OUT_OF_MEMORY;
- goto error;
- }
- alloc2 = newform->line;
- memcpy(newform->line, line, (size_t)length);
-
- /* zero terminate for easier debugging */
- newform->line[(size_t)length]=0;
- }
- else {
- newform->line = (char *)line;
- type = FORM_DATA; /* in all other aspects this is just FORM_DATA */
- }
- newform->length = (size_t)length;
- }
- 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(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(strcmp("-", newform->line)) {
- struct_stat file;
- if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
- *size += filesize(newform->line, file);
- else {
- result = CURLE_BAD_FUNCTION_ARGUMENT;
- goto error;
- }
- }
- }
- }
-
- if(*formp) {
- (*formp)->next = newform;
- *formp = newform;
- }
- else
- *formp = newform;
-
- return CURLE_OK;
- error:
- if(newform)
- free(newform);
- if(alloc2)
- free(alloc2);
- return result;
-}
-
-/*
- * 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;
- CURLcode result;
- va_list ap;
- va_start(ap, fmt);
- s = curl_mvaprintf(fmt, ap);
- va_end(ap);
-
- if(!s)
- return CURLE_OUT_OF_MEMORY;
-
- result = AddFormData(formp, FORM_DATAMEM, s, 0, size);
- if(result)
- free(s);
-
- return result;
-}
-
-/*
- * 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 */
- form = next;
- } while(form); /* continue */
-
- *form_ptr = NULL;
-}
-
/*
* curl_formget()
* Serialize a curl_httppost struct.
@@ -962,42 +762,34 @@ int curl_formget(struct curl_httppost *form, void *arg,
curl_formget_callback append)
{
CURLcode result;
- curl_off_t size;
- struct FormData *data, *ptr;
+ curl_mimepart toppart;
- result = Curl_getformdata(NULL, &data, form, NULL, &size);
- if(result)
- return (int)result;
-
- 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_mime_initpart(&toppart, NULL); /* default form is empty */
+ result = Curl_getformdata(NULL, &toppart, form, NULL);
+ if(!result)
+ result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
+ NULL, MIMESTRATEGY_FORM);
+
+ while(!result) {
+ char buffer[8192];
+ size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
+
+ if(!nread)
+ break;
+
+ switch(nread) {
+ default:
+ if(append(arg, buffer, nread) != nread)
+ result = CURLE_READ_ERROR;
+ break;
+ case CURL_READFUNC_ABORT:
+ case CURL_READFUNC_PAUSE:
+ break;
}
}
- Curl_formclean(&data);
- return 0;
+
+ Curl_mime_cleanpart(&toppart);
+ return (int) result;
}
/*
@@ -1013,7 +805,7 @@ void curl_formfree(struct curl_httppost *form)
return;
do {
- next=form->next; /* the following form line */
+ next = form->next; /* the following form line */
/* recurse to sub-contents */
curl_formfree(form->more);
@@ -1031,118 +823,29 @@ void curl_formfree(struct curl_httppost *form)
} while(form); /* 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)
+/* Set mime part name, taking care of non nul-terminated name string. */
+static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
{
- /* Ignore all the details above for now and make a quick and simple
- implementaion here */
- char *s1;
- char *s2;
+ char *zname;
+ CURLcode res;
- 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) {
- free(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);
- free(filename_escaped);
- free(filebasename);
- return result;
+ if(!name || !len)
+ return curl_mime_name(part, name);
+ zname = malloc(len + 1);
+ if(!zname)
+ return CURLE_OUT_OF_MEMORY;
+ memcpy(zname, name, len);
+ zname[len] = '\0';
+ res = curl_mime_name(part, zname);
+ free(zname);
+ return res;
}
/*
- * 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'.
+ * Curl_getformdata() converts a linked list of "meta data" into a mime
+ * structure. The input list is in 'post', while the output is stored in
+ * mime part at '*finalform'.
*
* 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
@@ -1150,422 +853,123 @@ static CURLcode formdata_add_filename(const struct curl_httppost *file,
*/
CURLcode Curl_getformdata(struct Curl_easy *data,
- struct FormData **finalform,
+ curl_mimepart *finalform,
struct curl_httppost *post,
- const char *custom_content_type,
- curl_off_t *sizep)
+ curl_read_callback fread_func)
{
- 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 fileboundary[42];
- struct curl_slist *curList;
- char boundary[42];
+ curl_mime *form = NULL;
+ curl_mime *multipart;
+ curl_mimepart *part;
+ struct curl_httppost *file;
- *finalform = NULL; /* default form is empty */
+ Curl_mime_cleanpart(finalform); /* default form is empty */
if(!post)
return result; /* no input => no output! */
- result = formboundary(data, boundary, sizeof(boundary));
- if(result)
- return result;
-
- /* 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) {
- 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;
+ form = curl_mime_init(data);
+ if(!form)
+ result = CURLE_OUT_OF_MEMORY;
- result = AddFormDataf(&form, &size, "\"");
- if(result)
- break;
+ if(!result)
+ result = curl_mime_subparts(finalform, form);
+ /* Process each top part. */
+ for(; !result && post; post = post->next) {
+ /* If we have more than a file here, create a mime subpart and fill it. */
+ multipart = form;
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 */
-
- result = formboundary(data, fileboundary, sizeof(fileboundary));
- if(result) {
- break;
+ part = curl_mime_addpart(form);
+ if(!part)
+ result = CURLE_OUT_OF_MEMORY;
+ if(!result)
+ result = setname(part, post->name, post->namelength);
+ if(!result) {
+ multipart = curl_mime_init(data);
+ if(!multipart)
+ result = CURLE_OUT_OF_MEMORY;
}
-
- result = AddFormDataf(&form, &size,
- "\r\nContent-Type: multipart/mixed;"
- " boundary=%s\r\n",
- fileboundary);
- if(result)
- break;
+ if(!result)
+ result = curl_mime_subparts(part, multipart);
}
- 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);
- }
+ /* Generate all the part contents. */
+ for(file = post; !result && file; file = file->more) {
+ /* Create the part. */
+ part = curl_mime_addpart(multipart);
+ if(!part)
+ result = CURLE_OUT_OF_MEMORY;
- if(result)
- break;
- }
+ /* Set the headers. */
+ if(!result)
+ result = curl_mime_headers(part, file->contentheader, 0);
- if(file->contenttype) {
- /* we have a specified type */
- result = AddFormDataf(&form, &size,
- "\r\nContent-Type: %s",
- file->contenttype);
- if(result)
- break;
- }
+ /* Set the content type. */
+ if(!result &&file->contenttype)
+ result = curl_mime_type(part, file->contenttype);
- 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;
+ /* Set field name. */
+ if(!result && !post->more)
+ result = setname(part, post->name, post->namelength);
- result = AddFormDataf(&form, &size, "\r\n\r\n");
- if(result)
- break;
+ /* Process contents. */
+ if(!result) {
+ curl_off_t clen = post->contentslength;
- if((post->flags & HTTPPOST_FILENAME) ||
- (post->flags & HTTPPOST_READFILE)) {
- /* we should include the contents from the specified file */
- FILE *fileread;
-
- fileread = !strcmp("-", 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 || feof(fileread) || ferror(fileread))
- break;
- }
+ if(post->flags & CURL_HTTPPOST_LARGE)
+ clen = post->contentlen;
+ if(!clen)
+ clen = -1;
+
+ if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
+ if(!strcmp(file->contents, "-")) {
+ /* There are a few cases where the code below won't work; in
+ particular, freopen(stdin) by the caller is not guaranteed
+ to result as expected. This feature has been kept for backward
+ compatibility: use of "-" pseudo file name should be avoided. */
+ result = curl_mime_data_cb(part, (curl_off_t) -1,
+ (curl_read_callback) fread,
+ (curl_seek_callback) fseek,
+ NULL, (void *) stdin);
}
+ else
+ result = curl_mime_filedata(part, file->contents);
+ if(!result && (post->flags & HTTPPOST_READFILE))
+ result = curl_mime_filename(part, NULL);
}
+ else if(post->flags & HTTPPOST_BUFFER)
+ result = curl_mime_data(part, post->buffer,
+ post->bufferlength? post->bufferlength: -1);
+ else if(post->flags & HTTPPOST_CALLBACK)
+ /* the contents should be read with the callback and the size is set
+ with the contentslength */
+ result = curl_mime_data_cb(part, clen,
+ fread_func, NULL, NULL, post->userp);
else {
- if(data)
- failf(data, "couldn't open file \"%s\"", file->contents);
- *finalform = NULL;
- result = CURLE_READ_ERROR;
+ result = curl_mime_data(part, post->contents, (ssize_t) clen);
+#ifdef CURL_DOES_CONVERSIONS
+ /* Convert textual contents now. */
+ if(!result && data && part->datasize)
+ result = Curl_convert_to_network(data, part->data, part->datasize);
+#endif
}
}
- 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->flags&CURL_HTTPPOST_LARGE?
- post->contentlen:post->contentslength, &size);
- else
- /* include the contents we got */
- result = AddFormData(&form, FORM_CONTENT, post->contents,
- post->flags&CURL_HTTPPOST_LARGE?
- post->contentlen: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;
+ /* Set fake file name. */
+ if(!result && post->showfilename)
+ if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
+ HTTPPOST_CALLBACK)))
+ result = curl_mime_filename(part, post->showfilename);
}
- post = post->next;
- } while(post); /* for each field */
-
- /* end-boundary for everything */
- if(!result)
- result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary);
-
- if(result) {
- Curl_formclean(&firstform);
- return result;
}
- *sizep = size;
- *finalform = firstform;
+ if(result)
+ Curl_mime_cleanpart(finalform);
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, FOPEN_READTEXT); /* VMS */
- break;
- default:
- return fopen(file, FOPEN_READTEXT, "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;
- 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 NULL; /* 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 CURLcode formboundary(struct Curl_easy *data,
- char *buffer, size_t buflen)
-{
- /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
- combinations */
- if(buflen < 41)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- memset(buffer, '-', 24);
- Curl_rand_hex(data, (unsigned char *)&buffer[24], 17);
-
- return CURLE_OK;
-}
-
#else /* CURL_DISABLE_HTTP */
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
diff --git a/lib/formdata.h b/lib/formdata.h
index 69629f628..1246c2bc8 100644
--- a/lib/formdata.h
+++ b/lib/formdata.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,32 +22,6 @@
*
***************************************************************************/
-enum formtype {
- FORM_DATAMEM, /* already allocated FORM_DATA memory */
- 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;
@@ -69,31 +43,9 @@ typedef struct FormInfo {
struct FormInfo *more;
} FormInfo;
-int Curl_FormInit(struct Form *form, struct FormData *formdata);
-
CURLcode Curl_getformdata(struct Curl_easy *data,
- struct FormData **,
+ curl_mimepart *,
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 Curl_easy *, struct FormData *);
+ curl_read_callback fread_func);
#endif /* HEADER_CURL_FORMDATA_H */
diff --git a/lib/ftp.c b/lib/ftp.c
index eebcade49..8590576f0 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -239,9 +239,9 @@ static void freedirs(struct ftp_conn *ftpc)
{
int i;
if(ftpc->dirs) {
- for(i=0; i < ftpc->dirdepth; i++) {
+ for(i = 0; i < ftpc->dirdepth; i++) {
free(ftpc->dirs[i]);
- ftpc->dirs[i]=NULL;
+ ftpc->dirs[i] = NULL;
}
free(ftpc->dirs);
ftpc->dirs = NULL;
@@ -288,7 +288,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
size = sizeof(add);
- s=accept(sock, (struct sockaddr *) &add, &size);
+ s = accept(sock, (struct sockaddr *) &add, &size);
}
Curl_closesocket(conn, sock); /* close the first socket */
@@ -457,7 +457,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
}
if(conn->proto.ftpc.state_saved == FTP_STOR) {
- *(ftp->bytecountp)=0;
+ *(ftp->bytecountp) = 0;
/* When we know we're uploading a specified file, we can get the file
size prior to the actual upload. */
@@ -592,7 +592,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
#endif
/* store the latest code for later retrieval */
- data->info.httpcode=code;
+ data->info.httpcode = code;
if(ftpcode)
*ftpcode = code;
@@ -640,8 +640,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
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;
+ int cache_skip = 0;
+ int value_to_be_ignored = 0;
if(ftpcode)
*ftpcode = 0; /* 0 for errors */
@@ -649,13 +649,13 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
/* make the pointer point to something for the rest of this function */
ftpcode = &value_to_be_ignored;
- *nreadp=0;
+ *nreadp = 0;
while(!*ftpcode && !result) {
/* check and reset timeout value every lap */
timeout = Curl_pp_state_timeout(pp);
- if(timeout <=0) {
+ if(timeout <= 0) {
failf(data, "FTP response timeout");
return CURLE_OPERATION_TIMEDOUT; /* already too little time */
}
@@ -713,7 +713,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
else
/* when we got data or there is no cache left, we reset the cache skip
counter */
- cache_skip=0;
+ cache_skip = 0;
*nreadp += nread;
@@ -848,7 +848,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
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++) {
+ for(s = 1, i = 0; i<2; i++) {
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
socks[s] = conn->tempsock[i];
bits |= GETSOCK_WRITESOCK(s++);
@@ -885,7 +885,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
/* 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;
+ ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0;
if((conn->data->set.ftp_filemethod == FTPFILE_NOCWD) && !ftpc->cwdcount)
/* No CWD necessary */
@@ -928,15 +928,15 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct Curl_easy *data=conn->data;
- curl_socket_t portsock= CURL_SOCKET_BAD;
+ struct Curl_easy *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 *sa = (struct sockaddr *)&ss;
struct sockaddr_in * const sa4 = (void *)sa;
#ifdef ENABLE_IPV6
struct sockaddr_in6 * const sa6 = (void *)sa;
@@ -947,7 +947,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
int error;
char *host = NULL;
char *string_ftpport = data->set.str[STRING_FTPPORT];
- struct Curl_dns_entry *h=NULL;
+ struct Curl_dns_entry *h = NULL;
unsigned short port_min = 0;
unsigned short port_max = 0;
unsigned short port;
@@ -975,7 +975,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
char *port_start = NULL;
char *port_sep = NULL;
- addr = calloc(addrlen+1, 1);
+ addr = calloc(addrlen + 1, 1);
if(!addr)
return CURLE_OUT_OF_MEMORY;
@@ -1018,7 +1018,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(ip_end != NULL) {
port_start = strchr(ip_end, ':');
if(port_start) {
- port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
+ port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10));
port_sep = strchr(port_start, '-');
if(port_sep) {
port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
@@ -1262,7 +1262,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
/* translate x.x.x.x to x,x,x,x */
while(source && *source) {
if(*source == '.')
- *dest=',';
+ *dest = ',';
else
*dest = *source;
dest++;
@@ -1469,12 +1469,12 @@ static CURLcode ftp_state_list(struct connectdata *conn)
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] != '/') {
+ if(lstArg[strlen(lstArg) - 1] != '/') {
/* chop off the file part if format is dir/dir/file */
slashPos = strrchr(lstArg, '/');
if(slashPos)
- *(slashPos+1) = '\0';
+ *(slashPos + 1) = '\0';
}
}
@@ -1622,7 +1622,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
}
if(seekerr != CURL_SEEKFUNC_OK) {
- curl_off_t passed=0;
+ curl_off_t passed = 0;
if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
failf(data, "Could not seek stream");
return CURLE_FTP_COULDNT_USE_REST;
@@ -1684,7 +1684,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- bool quote=FALSE;
+ bool quote = FALSE;
struct curl_slist *item;
switch(instate) {
@@ -1821,11 +1821,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result;
- struct Curl_easy *data=conn->data;
- struct Curl_dns_entry *addr=NULL;
+ struct Curl_easy *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 */
+ char *str = &data->state.buffer[4]; /* start on the first letter */
/* if we come here again, make sure the former name is cleared */
Curl_safefree(ftpc->newhost);
@@ -1849,9 +1849,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
/* 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++) {
+ for(i = 1; i<4; i++) {
if(separator[i] != sep1) {
- ptr=NULL; /* set to NULL to signal error */
+ ptr = NULL; /* set to NULL to signal error */
break;
}
}
@@ -1867,7 +1867,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
}
}
else
- ptr=NULL;
+ ptr = NULL;
}
if(!ptr) {
failf(data, "Weirdly formatted EPSV reply");
@@ -2041,7 +2041,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
int ftpcode)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -2055,7 +2055,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
&year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
char timebuf[24];
- time_t secs=time(NULL);
+ time_t secs = time(NULL);
snprintf(timebuf, sizeof(timebuf),
"%04d%02d%02d %02d:%02d:%02d GMT",
@@ -2071,7 +2071,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
if(data->set.opt_no_body &&
ftpc->file &&
data->set.get_filetime &&
- (data->info.filetime>=0) ) {
+ (data->info.filetime >= 0) ) {
char headerbuf[128];
time_t filetime = (time_t)data->info.filetime;
struct tm buffer;
@@ -2147,7 +2147,7 @@ static CURLcode ftp_state_type_resp(struct connectdata *conn,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
if(ftpcode/100 != 2) {
/* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
@@ -2176,7 +2176,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
curl_off_t filesize)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -2259,12 +2259,14 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data=conn->data;
- curl_off_t filesize;
+ struct Curl_easy *data = conn->data;
+ curl_off_t filesize = -1;
char *buf = data->state.buffer;
/* get the size from the ascii string: */
- filesize = (ftpcode == 213)?curlx_strtoofft(buf+4, NULL, 0):-1;
+ if(ftpcode == 213)
+ /* ignores parsing errors, which will make the size remain unknown */
+ (void)curlx_strtoofft(buf + 4, NULL, 0, &filesize);
if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2334,7 +2336,7 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
- if(ftpcode>=400) {
+ if(ftpcode >= 400) {
failf(data, "Failed FTP upload: %0d", ftpcode);
state(conn, FTP_STOP);
/* oops, we never close the sockets! */
@@ -2392,7 +2394,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
E:
125 Data connection already open; Transfer starting. */
- curl_off_t size=-1; /* default unknown size */
+ curl_off_t size = -1; /* default unknown size */
/*
@@ -2416,9 +2418,9 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
* Example D above makes this parsing a little tricky */
char *bytes;
char *buf = data->state.buffer;
- bytes=strstr(buf, " bytes");
+ bytes = strstr(buf, " bytes");
if(bytes--) {
- long in=(long)(bytes-buf);
+ 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 */
@@ -2426,7 +2428,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
break;
/* skip only digits */
if(!ISDIGIT(*bytes)) {
- bytes=NULL;
+ bytes = NULL;
break;
}
/* one more estep backwards */
@@ -2435,7 +2437,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
/* if we have nothing but digits: */
if(bytes++) {
/* get the number! */
- size = curlx_strtoofft(bytes, NULL, 0);
+ (void)curlx_strtoofft(bytes, NULL, 0, &size);
}
}
}
@@ -2598,7 +2600,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
{
CURLcode result;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
int ftpcode;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@@ -2650,7 +2652,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* We don't have a SSL/TLS connection yet, but FTPS is
requested. Try a FTPS connection now */
- ftpc->count3=0;
+ ftpc->count3 = 0;
switch(data->set.ftpsslauth) {
case CURLFTPAUTH_DEFAULT:
case CURLFTPAUTH_SSL:
@@ -2773,10 +2775,11 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_PWD:
if(ftpcode == 257) {
- char *ptr=&data->state.buffer[4]; /* start on the first letter */
+ char *ptr = &data->state.buffer[4]; /* start on the first letter */
const size_t buf_size = data->set.buffer_size;
char *dir;
char *store;
+ bool entry_extracted = FALSE;
dir = malloc(nread + 1);
if(!dir)
@@ -2808,7 +2811,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
}
else {
/* end of path */
- *store = '\0'; /* zero terminate */
+ entry_extracted = TRUE;
break; /* get out of this loop */
}
}
@@ -2817,7 +2820,9 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
store++;
ptr++;
}
-
+ *store = '\0'; /* zero terminate */
+ }
+ if(entry_extracted) {
/* 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
@@ -2864,7 +2869,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_SYST:
if(ftpcode == 215) {
- char *ptr=&data->state.buffer[4]; /* start on the first letter */
+ char *ptr = &data->state.buffer[4]; /* start on the first letter */
char *os;
char *store;
@@ -2955,7 +2960,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
}
else {
/* success */
- ftpc->count2=0;
+ ftpc->count2 = 0;
if(++ftpc->cwdcount <= ftpc->dirdepth) {
/* send next CWD */
PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
@@ -3195,15 +3200,16 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */
size_t dlen = strlen(path)-flen;
if(!ftpc->cwdfail) {
+ ftpc->prevmethod = data->set.ftp_filemethod;
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 */
+ ftpc->prevpath[dlen] = 0; /* terminate */
}
else {
/* we never changed dir */
- ftpc->prevpath=strdup("");
+ ftpc->prevpath = strdup("");
free(path);
}
if(ftpc->prevpath)
@@ -3466,35 +3472,36 @@ static CURLcode ftp_range(struct connectdata *conn)
{
curl_off_t from, to;
char *ptr;
- char *ptr2;
struct Curl_easy *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=='-')))
+ CURLofft from_t;
+ CURLofft to_t;
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+ if(from_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ 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)) {
+ to_t = curlx_strtoofft(ptr, NULL, 0, &to);
+ if(to_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ if((to_t == CURL_OFFT_INVAL) && !from_t) {
/* 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) {
+ else if(!to_t && (from_t == CURL_OFFT_INVAL)) {
/* -Y */
- data->req.maxdownload = -from;
- data->state.resume_from = from;
+ data->req.maxdownload = to;
+ data->state.resume_from = -to;
DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
- " bytes\n", -from));
+ " bytes\n", to));
}
else {
/* X-Y */
- data->req.maxdownload = (to-from)+1; /* include last byte */
+ 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",
@@ -3525,7 +3532,7 @@ static CURLcode ftp_range(struct connectdata *conn)
static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
{
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = CURLE_OK;
bool connected = FALSE;
@@ -3692,7 +3699,7 @@ CURLcode ftp_perform(struct connectdata *conn,
bool *dophase_done)
{
/* this is FTP and no proxy */
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
DEBUGF(infof(conn->data, "DO phase starts\n"));
@@ -3985,7 +3992,7 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
#define SBUF_SIZE 1024
char s[SBUF_SIZE];
size_t write_len;
- char *sptr=s;
+ char *sptr = s;
CURLcode result = CURLE_OK;
#ifdef HAVE_GSSAPI
enum protection_level data_sec = conn->data_prot;
@@ -3996,9 +4003,8 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
return CURLE_BAD_FUNCTION_ARGUMENT;
strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
- write_len +=2;
-
- bytes_written=0;
+ write_len += 2;
+ bytes_written = 0;
result = Curl_convert_to_network(conn->data, s, write_len);
/* Curl_convert_to_network calls failf if unsuccessful */
@@ -4076,7 +4082,7 @@ static CURLcode ftp_quit(struct connectdata *conn)
*/
static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
{
- struct ftp_conn *ftpc= &conn->proto.ftpc;
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
/* We cannot send quit unconditionally. If this connection is stale or
@@ -4172,7 +4178,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
ftpc->dirdepth = 0;
break;
}
- slash_pos=strrchr(cur_pos, '/');
+ slash_pos = strrchr(cur_pos, '/');
if(slash_pos || !*cur_pos) {
size_t dirlen = slash_pos-cur_pos;
CURLcode result;
@@ -4193,7 +4199,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
return result;
}
ftpc->dirdepth = 1; /* we consider it to be a single dir */
- filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
+ filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */
}
else
filename = cur_pos; /* this is a file name only */
@@ -4277,8 +4283,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
}
}
else
- ftpc->file=NULL; /* instead of point to a zero byte, we make it a NULL
- pointer */
+ 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! */
@@ -4302,7 +4308,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
dlen -= ftpc->file?strlen(ftpc->file):0;
if((dlen == strlen(ftpc->prevpath)) &&
- !strncmp(path, ftpc->prevpath, dlen)) {
+ !strncmp(path, ftpc->prevpath, dlen) &&
+ (ftpc->prevmethod == data->set.ftp_filemethod)) {
infof(data, "Request has same path as previous transfer\n");
ftpc->cwddone = TRUE;
}
@@ -4373,8 +4380,8 @@ static
CURLcode ftp_regular_transfer(struct connectdata *conn,
bool *dophase_done)
{
- CURLcode result=CURLE_OK;
- bool connected=FALSE;
+ CURLcode result = CURLE_OK;
+ bool connected = FALSE;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
data->req.size = -1; /* make sure this is unknown at this point */
diff --git a/lib/ftp.h b/lib/ftp.h
index 9c6c2c8de..e4aa63f17 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -135,6 +135,7 @@ struct ftp_conn {
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 */
+ curl_ftpfile prevmethod; /* ftp method in 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 */
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index 6063cee6e..ab6c50e82 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -421,7 +421,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
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;
+ 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))
@@ -609,16 +609,18 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
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->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
- parser->file_data->info.size = fsize;
+ if(!curlx_strtoofft(finfo->b_data + parser->item_offset,
+ &p, 10, &fsize)) {
+ if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
+ fsize != CURL_OFF_T_MIN) {
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->file_data->info.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;
}
- 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);
@@ -935,19 +937,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
}
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 {
+ if(curlx_strtoofft(finfo->b_data +
+ parser->item_offset,
+ &endptr, 10, &finfo->size)) {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 99ba587af..b235f54ca 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -54,6 +54,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
pro->t_starttransfer = 0;
pro->timespent = 0;
pro->t_redirect = 0;
+ pro->is_t_startransfer_set = false;
info->httpcode = 0;
info->httpproxycode = 0;
@@ -279,6 +280,39 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
return CURLE_OK;
}
+#define DOUBLE_SECS(x) (double)(x)/1000000
+
+static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
+ curl_off_t *param_offt)
+{
+ switch(info) {
+ case CURLINFO_SIZE_UPLOAD_T:
+ *param_offt = data->progress.uploaded;
+ break;
+ case CURLINFO_SIZE_DOWNLOAD_T:
+ *param_offt = data->progress.downloaded;
+ break;
+ case CURLINFO_SPEED_DOWNLOAD_T:
+ *param_offt = data->progress.dlspeed;
+ break;
+ case CURLINFO_SPEED_UPLOAD_T:
+ *param_offt = data->progress.ulspeed;
+ break;
+ case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
+ *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
+ data->progress.size_dl:-1;
+ break;
+ case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
+ *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
+ data->progress.size_ul:-1;
+ break;
+ default:
+ return CURLE_UNKNOWN_OPTION;
+ }
+
+ return CURLE_OK;
+}
+
static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
double *param_doublep)
{
@@ -359,46 +393,25 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
param_slistp;
struct curl_tlssessioninfo *tsi = &data->tsi;
+#ifdef USE_SSL
struct connectdata *conn = data->easy_conn;
+#endif
*tsip = tsi;
tsi->backend = Curl_ssl_backend();
tsi->internals = NULL;
+#ifdef USE_SSL
if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
unsigned int i;
for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
if(conn->ssl[i].use) {
-#if defined(USE_AXTLS)
- tsi->internals = (void *)conn->ssl[i].ssl;
-#elif defined(USE_CYASSL)
- tsi->internals = (void *)conn->ssl[i].handle;
-#elif defined(USE_DARWINSSL)
- tsi->internals = (void *)conn->ssl[i].ssl_ctx;
-#elif defined(USE_GNUTLS)
- tsi->internals = (void *)conn->ssl[i].session;
-#elif defined(USE_GSKIT)
- tsi->internals = (void *)conn->ssl[i].handle;
-#elif defined(USE_MBEDTLS)
- tsi->internals = (void *)&conn->ssl[i].ssl;
-#elif defined(USE_NSS)
- tsi->internals = (void *)conn->ssl[i].handle;
-#elif defined(USE_OPENSSL)
- /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
- tsi->internals = ((info == CURLINFO_TLS_SESSION) ?
- (void *)conn->ssl[i].ctx :
- (void *)conn->ssl[i].handle);
-#elif defined(USE_POLARSSL)
- tsi->internals = (void *)&conn->ssl[i].ssl;
-#elif defined(USE_SCHANNEL)
- tsi->internals = (void *)&conn->ssl[i].ctxt->ctxt_handle;
-#elif defined(USE_SSL)
-#error "SSL backend specific information missing for CURLINFO_TLS_SSL_PTR"
-#endif
+ tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info);
break;
}
}
}
+#endif
}
break;
default:
diff --git a/lib/gopher.c b/lib/gopher.c
index 19b6d36e2..0ee3ffe00 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,8 +73,8 @@ const struct Curl_handler Curl_handler_gopher = {
static CURLcode gopher_do(struct connectdata *conn, bool *done)
{
- CURLcode result=CURLE_OK;
- struct Curl_easy *data=conn->data;
+ CURLcode result = CURLE_OK;
+ struct Curl_easy *data = conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
curl_off_t *bytecount = &data->req.bytecount;
@@ -97,11 +97,11 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
/* Otherwise, drop / and the first character (i.e., item type) ... */
newp = path;
- newp+=2;
+ newp += 2;
/* ... then turn ? into TAB for search servers, Veronica, etc. ... */
j = strlen(newp);
- for(i=0; i<j; i++)
+ for(i = 0; i<j; i++)
if(newp[i] == '?')
newp[i] = '\x09';
diff --git a/lib/hash.c b/lib/hash.c
index 552022443..5733d975b 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -300,10 +300,10 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
/* 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++) {
+ 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;
+ iter->slot_index = i + 1;
break;
}
}
diff --git a/lib/hostcheck.c b/lib/hostcheck.c
index 156091ca8..23dc3d2a7 100644
--- a/lib/hostcheck.c
+++ b/lib/hostcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,10 +73,10 @@ static int hostmatch(char *hostname, char *pattern)
/* normalize pattern and hostname by stripping off trailing dots */
size_t len = strlen(hostname);
if(hostname[len-1]=='.')
- hostname[len-1]=0;
+ hostname[len-1] = 0;
len = strlen(pattern);
if(pattern[len-1]=='.')
- pattern[len-1]=0;
+ pattern[len-1] = 0;
pattern_wildcard = strchr(pattern, '*');
if(pattern_wildcard == NULL)
@@ -95,7 +95,7 @@ static int hostmatch(char *hostname, char *pattern)
match. */
wildcard_enabled = 1;
pattern_label_end = strchr(pattern, '.');
- if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
+ if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL ||
pattern_wildcard > pattern_label_end ||
strncasecompare(pattern, "xn--", 4)) {
wildcard_enabled = 0;
@@ -116,9 +116,9 @@ static int hostmatch(char *hostname, char *pattern)
return CURL_HOST_NOMATCH;
prefixlen = pattern_wildcard - pattern;
- suffixlen = pattern_label_end - (pattern_wildcard+1);
+ suffixlen = pattern_label_end - (pattern_wildcard + 1);
return strncasecompare(pattern, hostname, prefixlen) &&
- strncasecompare(pattern_wildcard+1, hostname_label_end - suffixlen,
+ strncasecompare(pattern_wildcard + 1, hostname_label_end - suffixlen,
suffixlen) ?
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
}
@@ -137,7 +137,7 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
hostp = strdup(hostname);
if(hostp) {
if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
- res= 1;
+ res = 1;
free(hostp);
}
free(matchp);
diff --git a/lib/hostip.c b/lib/hostip.c
index 619ec84b5..1a18a3ed7 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -304,9 +304,9 @@ fetch_addr(struct connectdata *conn,
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);
+ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
- if(dns && (data->set.dns_cache_timeout != -1)) {
+ if(dns && (data->set.dns_cache_timeout != -1)) {
/* See whether the returned entry is stale. Done before we release lock */
struct hostcache_prune_data user;
@@ -316,7 +316,7 @@ fetch_addr(struct connectdata *conn,
if(hostcache_timestamp_remove(&user, dns)) {
infof(data, "Hostname in DNS cache was stale, zapped\n");
dns = NULL; /* the memory deallocation is being handled by the hash */
- Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1);
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
}
}
@@ -403,7 +403,7 @@ Curl_cache_addr(struct Curl_easy *data,
dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */
/* Store the resolved data in our DNS cache. */
- dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1,
+ dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
(void *)dns);
if(!dns2) {
free(dns);
@@ -807,7 +807,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* delete entry, ignore if it didn't exist */
- Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1);
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -848,7 +848,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
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);
+ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
/* free the allocated entry_id again */
free(entry_id);
diff --git a/lib/hostip4.c b/lib/hostip4.c
index e459328ac..6a7c6e576 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -249,7 +249,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
*/
if(CURL_HOSTENT_SIZE >=
- (sizeof(struct hostent)+sizeof(struct hostent_data))) {
+ (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
diff --git a/lib/hostip6.c b/lib/hostip6.c
index 4ebfc2dcf..edeebec9e 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -212,7 +212,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
if(port) {
snprintf(sbuf, sizeof(sbuf), "%d", port);
- sbufptr=sbuf;
+ sbufptr = sbuf;
}
error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
diff --git a/lib/http.c b/lib/http.c
index 741098e84..b5164f758 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -50,6 +50,7 @@
#include "transfer.h"
#include "sendf.h"
#include "formdata.h"
+#include "mime.h"
#include "progress.h"
#include "curl_base64.h"
#include "cookie.h"
@@ -162,6 +163,7 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
if(!http)
return CURLE_OUT_OF_MEMORY;
+ Curl_mime_initpart(&http->form, conn->data);
conn->data->req.protop = http;
Curl_http2_setup_conn(conn);
@@ -170,26 +172,6 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
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 Curl_easy *data = conn->data;
-
- for(head = data->set.headers;head; head=head->next) {
- if(strncasecompare(head->data, thisheader, thislen))
- return head->data;
- }
-
- return NULL;
-}
/*
* checkProxyHeaders() checks the linked list of custom proxy headers
@@ -209,7 +191,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers;
- head; head=head->next) {
+ head; head = head->next) {
if(strncasecompare(head->data, thisheader, thislen))
return head->data;
}
@@ -427,6 +409,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
expectsend = data->state.infilesize;
break;
case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
expectsend = http->postsize;
break;
default:
@@ -610,7 +593,7 @@ output_auth_headers(struct connectdata *conn,
#endif
#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
if(authstatus->picked == CURLAUTH_NTLM_WB) {
- auth="NTLM_WB";
+ auth = "NTLM_WB";
result = Curl_output_ntlm_wb(conn, proxy);
if(result)
return result;
@@ -1022,7 +1005,7 @@ static size_t readmoredata(char *buffer,
http->sending++; /* move one step up */
- http->backup.postsize=0;
+ http->backup.postsize = 0;
}
else
http->postsize = 0;
@@ -1150,7 +1133,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
/* 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);
+ ptr + headlen, bodylen, conn);
}
}
@@ -1262,7 +1245,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
(~(size * 2) < (in->size_used * 2)))
new_size = (size_t)-1;
else
- new_size = (in->size_used+size) * 2;
+ new_size = (in->size_used + size) * 2;
if(in->buffer)
/* we have a buffer, enlarge the existing one */
@@ -1339,7 +1322,7 @@ Curl_compareheader(const char *headerline, /* line to check */
clen = strlen(content); /* length of the word to find */
/* find the content string in the rest of the line */
- for(;len>=clen;len--, start++) {
+ for(; len >= clen; len--, start++) {
if(strncasecompare(start, content, clen))
return TRUE; /* match! */
}
@@ -1371,7 +1354,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
- if(!Curl_connect_complete(conn))
+ if(Curl_connect_ongoing(conn))
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
@@ -1470,18 +1453,17 @@ CURLcode Curl_http_done(struct connectdata *conn,
Curl_http2_done(conn, premature);
- if(HTTPREQ_POST_FORM == data->set.httpreq) {
- data->req.bytecount = http->readbytecount + http->writebytecount;
+ Curl_mime_cleanpart(&http->form);
- 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)
+ switch(data->set.httpreq) {
+ case HTTPREQ_PUT:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
data->req.bytecount = http->readbytecount + http->writebytecount;
+ break;
+ default:
+ break;
+ }
if(status)
return status;
@@ -1581,7 +1563,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
char *ptr;
struct curl_slist *h[2];
struct curl_slist *headers;
- int numlists=1; /* by default */
+ int numlists = 1; /* by default */
struct Curl_easy *data = conn->data;
int i;
@@ -1613,7 +1595,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
}
/* loop through one or two lists */
- for(i=0; i < numlists; i++) {
+ for(i = 0; i < numlists; i++) {
headers = h[i];
while(headers) {
@@ -1637,15 +1619,23 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
/* this header (extended by formdata.c) is sent later */
checkprefix("Content-Type:", headers->data))
;
+ else if(data->set.httpreq == HTTPREQ_POST_MIME &&
+ /* this header 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))
+ 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))
+ checkprefix("Connection:", headers->data))
+ ;
+ else if((conn->httpversion == 20) &&
+ checkprefix("Transfer-Encoding:", headers->data))
+ /* HTTP/2 doesn't support chunked requests */
;
else if((conn->httpversion == 20) &&
checkprefix("Transfer-Encoding:", headers->data))
@@ -1678,6 +1668,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
*ptr = ':';
result = Curl_add_bufferf(req_buffer, "%s\r\n",
headers->data);
+
+ /* restore the previous value */
+ *ptr = ';';
+
if(result)
return result;
}
@@ -1775,7 +1769,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
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;
+ int seekerr = CURL_SEEKFUNC_CANTSEEK;
/* 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
@@ -1848,6 +1842,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
switch(httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
request = "POST";
break;
case HTTPREQ_PUT:
@@ -1873,7 +1868,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
here. */
if(Curl_checkheaders(conn, "User-Agent:")) {
free(conn->allocptr.uagent);
- conn->allocptr.uagent=NULL;
+ conn->allocptr.uagent = NULL;
}
/* setup the authentication headers */
@@ -1942,6 +1937,48 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#endif
+ switch(httpreq) {
+ case HTTPREQ_POST_MIME:
+ http->sendit = &data->set.mimepost;
+ break;
+ case HTTPREQ_POST_FORM:
+ /* Convert the form structure into a mime structure. */
+ Curl_mime_cleanpart(&http->form);
+ result = Curl_getformdata(data, &http->form, data->set.httppost,
+ data->state.fread_func);
+ if(result)
+ return result;
+ http->sendit = &http->form;
+ break;
+ default:
+ http->sendit = NULL;
+ }
+
+ if(http->sendit) {
+ const char *cthdr = Curl_checkheaders(conn, "Content-Type:");
+
+ /* Read and seek body only. */
+ http->sendit->flags |= MIME_BODY_ONLY;
+
+ /* Prepare the mime structure headers & set content type. */
+
+ if(cthdr)
+ for(cthdr += 13; *cthdr == ' '; cthdr++)
+ ;
+ else if(http->sendit->kind == MIMEKIND_MULTIPART)
+ cthdr = "multipart/form-data";
+
+ curl_mime_headers(http->sendit, data->set.headers, 0);
+ result = Curl_mime_prepare_headers(http->sendit, cthdr,
+ NULL, MIMESTRATEGY_FORM);
+ curl_mime_headers(http->sendit, NULL, 0);
+ if(!result)
+ result = Curl_mime_rewind(http->sendit);
+ if(result)
+ return result;
+ http->postsize = Curl_mime_size(http->sendit);
+ }
+
ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
@@ -1949,9 +1986,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
}
else {
- if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
- data->set.upload &&
- (data->state.infilesize == -1)) {
+ if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
+ http->postsize < 0) ||
+ (data->set.upload && data->state.infilesize == -1))) {
if(conn->bits.authneg)
/* don't enable chunked during auth neg */
;
@@ -2049,7 +2087,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#ifndef CURL_DISABLE_PROXY
- if(conn->bits.httpproxy && !conn->bits.tunnel_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
@@ -2123,21 +2161,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#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) ) &&
+ if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
data->state.resume_from) {
/**********************************************************************
* Resuming upload in HTTP means that we PUT or POST and that we have
@@ -2145,6 +2171,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* 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.
+ * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
*********************************************************************/
if(data->state.resume_from < 0) {
@@ -2166,7 +2193,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
if(seekerr != CURL_SEEKFUNC_OK) {
- curl_off_t passed=0;
+ curl_off_t passed = 0;
if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
failf(data, "Could not seek stream");
@@ -2219,7 +2246,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
data->state.range);
}
- else if((httpreq != HTTPREQ_GET) &&
+ else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
!Curl_checkheaders(conn, "Content-Range:")) {
/* if a line like this was already allocated, free the previous one */
@@ -2237,7 +2264,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
else if(data->state.resume_from) {
/* This is because "resume" was selected */
- curl_off_t total_expected_size=
+ 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
@@ -2347,8 +2374,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#if !defined(CURL_DISABLE_COOKIES)
if(data->cookies || addcookies) {
- struct Cookie *co=NULL; /* no cookies from start */
- int count=0;
+ 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);
@@ -2361,7 +2388,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
if(co) {
- struct Cookie *store=co;
+ struct Cookie *store = co;
/* now loop through all cookies that matched */
while(co) {
if(co->value) {
@@ -2415,117 +2442,79 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
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 data->set.fread_func pointer itself will be changed for the
- multipart case to the function that returns a multipart formatted
- stream. */
- http->form.fread_func = data->state.fread_func;
-
- /* Set the read function to read from the generated form data */
- data->state.fread_func = (curl_read_callback)Curl_FormReader;
- data->state.in = &http->form;
+ case HTTPREQ_PUT: /* Let's PUT the data to the server! */
- http->sending = HTTPSEND_BODY;
+ if(conn->bits.authneg)
+ postsize = 0;
+ else
+ postsize = data->state.infilesize;
- if(!data->req.upload_chunky &&
- !Curl_checkheaders(conn, "Content-Length:")) {
+ if((postsize != -1) && !data->req.upload_chunky &&
+ (conn->bits.authneg || !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);
+ "\r\n", 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(postsize != 0) {
+ result = expect100(data, conn, req_buffer);
if(result)
return result;
}
- /* make the request end in a true CRLF */
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
if(result)
return result;
- /* set upload size to the progress meter */
- Curl_pgrsSetUploadSize(data, http->postsize);
+ /* set the upload size to the progress meter */
+ Curl_pgrsSetUploadSize(data, postsize);
- /* fire away the whole request to the server */
+ /* 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 POST request");
+ failf(data, "Failed sending PUT request");
else
- /* setup variables for the upcoming transfer */
+ /* prepare for 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 */
+ &http->readbytecount, postsize?FIRSTSOCKET:-1,
+ postsize?&http->writebytecount:NULL);
+ if(result)
return result;
- }
-
break;
- case HTTPREQ_PUT: /* Let's PUT the data to the server! */
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
+ /* This is form posting using mime data. */
+ if(conn->bits.authneg) {
+ /* nothing to post! */
+ result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
+ if(result)
+ return result;
- if(conn->bits.authneg)
- postsize = 0;
- else
- postsize = data->state.infilesize;
+ 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((postsize != -1) && !data->req.upload_chunky &&
+ postsize = http->postsize;
+
+ /* 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 &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
- /* only add Content-Length if not uploading chunked */
+ /* 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);
@@ -2533,24 +2522,52 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
- if(postsize != 0) {
+ /* Output mime-generated headers. */
+ {
+ struct curl_slist *hdr;
+
+ for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
+ result = Curl_add_bufferf(req_buffer, "%s\r\n", hdr->data);
+ 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 > EXPECT_100_THRESHOLD || postsize < 0) {
result = expect100(data, conn, req_buffer);
if(result)
return result;
}
+ else
+ data->state.expect100header = FALSE;
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
+ /* make the request end in a true CRLF */
+ result = Curl_add_buffer(req_buffer, "\r\n", 2);
if(result)
return result;
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, postsize);
+ /* Read from mime structure. */
+ data->state.fread_func = (curl_read_callback) Curl_mime_read;
+ data->state.in = (void *) http->sendit;
+ http->sending = HTTPSEND_BODY;
+
/* 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");
+ failf(data, "Failed sending POST request");
else
/* prepare for transfer */
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
@@ -2558,6 +2575,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
postsize?&http->writebytecount:NULL);
if(result)
return result;
+
break;
case HTTPREQ_POST:
@@ -2614,7 +2632,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
its size. */
if(conn->httpversion != 20 &&
!data->state.expect100header &&
- (postsize < MAX_INITIAL_POST_SIZE)) {
+ (postsize < MAX_INITIAL_POST_SIZE)) {
/* if we don't use expect: 100 AND
postsize is less than MAX_INITIAL_POST_SIZE
@@ -2779,7 +2797,7 @@ checkhttpprefix(struct Curl_easy *data,
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)) {
+ 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 */
@@ -2809,6 +2827,7 @@ static bool
checkrtspprefix(struct Curl_easy *data,
const char *s)
{
+ bool result = FALSE;
#ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding using a scratch area */
@@ -2817,18 +2836,19 @@ checkrtspprefix(struct Curl_easy *data,
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)) {
+ 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 */
+ result = FALSE; /* can't return CURLE_foobar so return FALSE */
}
- s = scratch;
+ else
+ result = checkprefix("RTSP/", scratch)? TRUE: FALSE;
+ free(scratch);
#else
(void)data; /* unused */
+ result = checkprefix("RTSP/", s)? TRUE: FALSE;
#endif /* CURL_DOES_CONVERSIONS */
- if(checkprefix("RTSP/", s))
- return TRUE;
- return FALSE;
+
+ return result;
}
#endif /* CURL_DISABLE_RTSP */
@@ -2870,14 +2890,14 @@ static CURLcode header_append(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
- newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
+ 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.headersize = newsize;
data->state.headerbuff = newbuff;
k->hbufp = data->state.headerbuff + hbufp_index;
}
@@ -2970,7 +2990,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
/* decrease the size of the remaining (supposed) header line */
- rest_length = (k->end_ptr - k->str)+1;
+ rest_length = (k->end_ptr - k->str) + 1;
*nread -= (ssize_t)rest_length;
k->str = k->end_ptr + 1; /* move past new line */
@@ -3169,6 +3189,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
case HTTPREQ_PUT:
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
/* 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.
@@ -3296,7 +3317,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
#define HEADER1 scratch
#define SCRATCHSIZE 21
CURLcode res;
- char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
+ 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,
@@ -3337,7 +3358,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
separator = ' ';
}
- if((nc==4) && (' ' == separator)) {
+ if((nc == 4) && (' ' == separator)) {
conn->httpversion += 10 * httpversion_major;
if(k->upgr101 == UPGR101_RECEIVED) {
@@ -3350,7 +3371,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* 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);
+ nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode);
conn->httpversion = 10;
/* If user has set option HTTP200ALIASES,
@@ -3375,7 +3396,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
&rtspversion_major,
&conn->rtspversion,
&k->httpcode);
- if(nc==3) {
+ if(nc == 3) {
conn->rtspversion += 10 * rtspversion_major;
conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
}
@@ -3407,7 +3428,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
if(data->state.resume_from &&
- (data->set.httpreq==HTTPREQ_GET) &&
+ (data->set.httpreq == HTTPREQ_GET) &&
(k->httpcode == 416)) {
/* "Requested Range Not Satisfiable", just proceed and
pretend this is no error */
@@ -3463,8 +3484,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* fields. */
if(data->set.timecondition)
data->info.timecond = TRUE;
- k->size=0;
- k->maxdownload=0;
+ k->size = 0;
+ k->maxdownload = 0;
k->ignorecl = TRUE; /* ignore Content-Length headers */
break;
default:
@@ -3486,28 +3507,32 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* 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 */
- streamclose(conn, "negative content-length");
- infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
- ", closing after transfer\n", contentlength);
+ curl_off_t contentlength;
+ if(!curlx_strtoofft(k->p + 15, NULL, 10, &contentlength)) {
+ 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 */
+ streamclose(conn, "negative content-length");
+ infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
+ ", closing after transfer\n", contentlength);
+ }
}
+ else
+ infof(data, "Illegal Content-Length: header\n");
}
/* check for Content-Type: header lines to get the MIME-type */
else if(checkprefix("Content-Type:", k->p)) {
@@ -3682,11 +3707,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* 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;
+ if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
+ 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 */
@@ -3697,7 +3722,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_add(data,
- data->cookies, TRUE, k->p+11,
+ 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?
@@ -3708,8 +3733,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
#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:"),
+ 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;
diff --git a/lib/http.h b/lib/http.h
index c5c7a125d..0252f63db 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -40,8 +40,6 @@ 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,
@@ -130,7 +128,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
* HTTP unique setup
***************************************************************************/
struct HTTP {
- struct FormData *sendit;
+ curl_mimepart *sendit;
curl_off_t postsize; /* off_t to handle large file sizes */
const char *postdata;
@@ -140,7 +138,7 @@ struct HTTP {
curl_off_t writebytecount;
/* For FORM posting */
- struct Form form;
+ curl_mimepart form;
struct back {
curl_read_callback fread_func; /* backup storage for fread pointer */
diff --git a/lib/http2.c b/lib/http2.c
index 6b52171f6..4c8d2e529 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -384,12 +384,12 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
struct HTTP *stream = h->data->req.protop;
size_t len = strlen(header);
size_t i;
- for(i=0; i<stream->push_headers_used; i++) {
+ for(i = 0; i<stream->push_headers_used; i++) {
if(!strncmp(header, stream->push_headers[i], len)) {
/* sub-match, make sure that it is followed by a colon */
if(stream->push_headers[i][len] != ':')
continue;
- return &stream->push_headers[i][len+1];
+ return &stream->push_headers[i][len + 1];
}
}
}
@@ -464,7 +464,7 @@ static int push_promise(struct Curl_easy *data,
data->multi->push_userp);
/* free the headers again */
- for(i=0; i<stream->push_headers_used; i++)
+ for(i = 0; i<stream->push_headers_used; i++)
free(stream->push_headers[i]);
free(stream->push_headers);
stream->push_headers = NULL;
@@ -1582,7 +1582,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
failf(data, "nghttp2_session_mem_recv() returned %d:%s\n",
rv, nghttp2_strerror((int)rv));
*err = CURLE_RECV_ERROR;
- return 0;
+ return -1;
}
DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
if(nread == rv) {
@@ -1600,7 +1600,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
rv = h2_session_send(data, httpc->h2);
if(rv != 0) {
*err = CURLE_SEND_ERROR;
- return 0;
+ return -1;
}
if(should_close_session(httpc)) {
@@ -1955,6 +1955,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
switch(conn->data->set.httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
case HTTPREQ_PUT:
if(conn->data->state.infilesize != -1)
stream->upload_left = conn->data->state.infilesize;
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index 1bdf6974c..92d773112 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -86,8 +86,8 @@ static bool Curl_isxdigit(char digit)
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->hexindex = 0; /* start at 0 */
+ chunk->dataleft = 0; /* no data left yet! */
chunk->state = CHUNK_HEX; /* we get hex first! */
}
@@ -107,7 +107,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
ssize_t datalen,
ssize_t *wrotep)
{
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct Curl_chunker *ch = &conn->chunk;
struct SingleRequest *k = &data->req;
@@ -147,7 +147,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
return CHUNKE_ILLEGAL_HEX;
/* length and datap are unmodified */
- ch->hexbuffer[ch->hexindex]=0;
+ ch->hexbuffer[ch->hexindex] = 0;
/* convert to host encoding before calling strtoul */
result = Curl_convert_from_network(conn->data, ch->hexbuffer,
@@ -158,9 +158,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
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 */
+ if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))
return CHUNKE_ILLEGAL_HEX;
ch->state = CHUNK_LF; /* now wait for the CRLF */
}
@@ -172,7 +170,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* 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;
+ conn->trlPos = 0;
}
else
ch->state = CHUNK_DATA;
@@ -259,9 +257,9 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
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;
+ 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,
@@ -277,7 +275,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
if(result)
return CHUNKE_WRITE_ERROR;
}
- conn->trlPos=0;
+ conn->trlPos = 0;
ch->state = CHUNK_TRAILER_CR;
if(*datap == 0x0a)
/* already on the LF */
@@ -301,7 +299,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
ptr = realloc(conn->trailer, conn->trlMax + 3);
}
else {
- conn->trlMax=128;
+ conn->trlMax = 128;
ptr = malloc(conn->trlMax + 3);
}
if(!ptr)
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index 8a78bd293..0f1edcf65 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,11 +37,14 @@
#include "sendf.h"
#include "strcase.h"
#include "http_ntlm.h"
+#include "curl_ntlm_core.h"
#include "curl_ntlm_wb.h"
#include "vauth/vauth.h"
#include "url.h"
-#if defined(USE_NSS)
+/* SSL backend-specific #if branches in this file must be kept in the order
+ documented in curl_ntlm_core. */
+#if defined(NTLM_NEEDS_NSS_INIT)
#include "vtls/nssg.h"
#elif defined(USE_WINDOWS_SSPI)
#include "curl_sspi.h"
@@ -129,7 +132,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
DEBUGASSERT(conn);
DEBUGASSERT(conn->data);
-#ifdef USE_NSS
+#if defined(NTLM_NEEDS_NSS_INIT)
if(CURLE_OK != Curl_nss_force_init(conn->data))
return CURLE_OUT_OF_MEMORY;
#endif
@@ -170,8 +173,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
case NTLMSTATE_TYPE1:
default: /* for the weird cases we (re)start here */
/* Create a type-1 message */
- result = Curl_auth_create_ntlm_type1_message(userp, passwdp, ntlm, &base64,
- &len);
+ result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
+ ntlm, &base64, &len);
if(result)
return result;
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 834733960..26da33788 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -137,7 +137,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
bool Curl_connect_complete(struct connectdata *conn)
{
- return conn->connect_state &&
+ return !conn->connect_state ||
(conn->connect_state->tunnel_state == TUNNEL_COMPLETE);
}
@@ -163,10 +163,10 @@ static CURLcode connect_init(struct connectdata *conn, bool reinit)
s = conn->connect_state;
}
s->tunnel_state = TUNNEL_INIT;
- s->keepon=TRUE;
+ s->keepon = TRUE;
s->line_start = s->connect_buffer;
s->ptr = s->line_start;
- s->cl=0;
+ s->cl = 0;
return CURLE_OK;
}
@@ -182,8 +182,8 @@ static CURLcode CONNECT(struct connectdata *conn,
const char *hostname,
int remote_port)
{
- int subversion=0;
- struct Curl_easy *data=conn->data;
+ int subversion = 0;
+ struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
CURLcode result;
curl_socket_t tunnelsocket = conn->sock[sockindex];
@@ -234,8 +234,8 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!result) {
char *host = NULL;
- const char *proxyconn="";
- const char *useragent="";
+ const char *proxyconn = "";
+ const char *useragent = "";
const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
"1.0" : "1.1";
bool ipv6_ip = conn->bits.ipv6_ip;
@@ -244,7 +244,7 @@ static CURLcode CONNECT(struct connectdata *conn,
/* the hostname may be different */
if(hostname != conn->host.name)
ipv6_ip = (strchr(hostname, ':') != NULL);
- hostheader= /* host:port with IPv6 support */
+ hostheader = /* host:port with IPv6 support */
aprintf("%s%s%s:%hu", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
remote_port);
if(!hostheader) {
@@ -410,7 +410,8 @@ static CURLcode CONNECT(struct connectdata *conn,
}
/* convert from the network encoding */
- result = Curl_convert_from_network(data, line_start, perline);
+ result = Curl_convert_from_network(data, s->line_start,
+ (size_t)s->perline);
/* Curl_convert_from_network calls failf if unsuccessful */
if(result)
return result;
@@ -523,8 +524,8 @@ static CURLcode CONNECT(struct connectdata *conn,
k->httpcode);
}
else {
- s->cl = curlx_strtoofft(s->line_start +
- strlen("Content-Length:"), NULL, 10);
+ (void)curlx_strtoofft(s->line_start +
+ strlen("Content-Length:"), NULL, 10, &s->cl);
}
}
else if(Curl_compareheader(s->line_start, "Connection:", "close"))
@@ -566,7 +567,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(error)
return CURLE_RECV_ERROR;
- if(data->info.httpproxycode != 200) {
+ if(data->info.httpproxycode/100 != 2) {
/* 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);
@@ -597,7 +598,7 @@ static CURLcode CONNECT(struct connectdata *conn,
} while(data->req.newurl);
- if(200 != data->req.httpcode) {
+ if(data->info.httpproxycode/100 != 2) {
if(closeConnection && data->req.newurl) {
conn->bits.proxy_connect_closed = TRUE;
infof(data, "Connect me again please\n");
@@ -633,7 +634,8 @@ static CURLcode CONNECT(struct connectdata *conn,
data->state.authproxy.done = TRUE;
- infof(data, "Proxy replied OK to CONNECT request\n");
+ infof(data, "Proxy replied %d to CONNECT request\n",
+ data->info.httpproxycode);
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 */
diff --git a/lib/if2ip.c b/lib/if2ip.c
index a91b6d2ab..ce38ea117 100644
--- a/lib/if2ip.c
+++ b/lib/if2ip.c
@@ -103,7 +103,7 @@ bool Curl_if_is_interface_name(const char *interf)
struct ifaddrs *iface, *head;
if(getifaddrs(&head) >= 0) {
- for(iface=head; iface != NULL; iface=iface->ifa_next) {
+ for(iface = head; iface != NULL; iface = iface->ifa_next) {
if(strcasecompare(iface->ifa_name, interf)) {
result = TRUE;
break;
@@ -131,7 +131,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
#endif
if(getifaddrs(&head) >= 0) {
- for(iface = head; iface != NULL; iface=iface->ifa_next) {
+ for(iface = head; iface != NULL; iface = iface->ifa_next) {
if(iface->ifa_addr != NULL) {
if(iface->ifa_addr->sa_family == af) {
if(strcasecompare(iface->ifa_name, interf)) {
@@ -230,7 +230,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
return IF2IP_NOT_FOUND;
memset(&req, 0, sizeof(req));
- memcpy(req.ifr_name, interf, len+1);
+ memcpy(req.ifr_name, interf, len + 1);
req.ifr_addr.sa_family = AF_INET;
if(ioctl(dummy, SIOCGIFADDR, &req) < 0) {
diff --git a/lib/imap.c b/lib/imap.c
index 8fa598f88..9cf2bf86a 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -68,6 +68,7 @@
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "imap.h"
+#include "mime.h"
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
@@ -162,11 +163,15 @@ const struct Curl_handler Curl_handler_imaps = {
};
#endif
+#define IMAP_RESP_OK 1
+#define IMAP_RESP_NOT_OK 2
+#define IMAP_RESP_PREAUTH 3
+
/* SASL parameters for the imap protocol */
static const struct SASLproto saslimap = {
"imap", /* The service name */
'+', /* Code received when continuation is expected */
- 'O', /* Code to receive upon authentication success */
+ IMAP_RESP_OK, /* Code to receive upon authentication success */
0, /* Maximum initial response length (no max) */
imap_perform_authenticate, /* Send authentication command */
imap_continue_authenticate, /* Send authentication continuation */
@@ -249,15 +254,11 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
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;
- }
+ *resp = IMAP_RESP_OK;
+ else if(len >= 7 && !memcmp(line, "PREAUTH", 7))
+ *resp = IMAP_RESP_PREAUTH;
+ else
+ *resp = IMAP_RESP_NOT_OK;
return TRUE;
}
@@ -563,9 +564,10 @@ static CURLcode imap_perform_authentication(struct connectdata *conn)
struct imap_conn *imapc = &conn->proto.imapc;
saslprogress progress;
- /* Check we have enough data to authenticate with and end the
- connect phase if we don't */
- if(!Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
+ /* Check if already authenticated OR if there is enough data to authenticate
+ with and end the connect phase if we don't */
+ if(imapc->preauth ||
+ !Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
state(conn, IMAP_STOP);
return result;
}
@@ -707,18 +709,48 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
static CURLcode imap_perform_append(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = conn->data->req.protop;
+ struct Curl_easy *data = conn->data;
+ struct IMAP *imap = data->req.protop;
char *mailbox;
/* Check we have a mailbox */
if(!imap->mailbox) {
- failf(conn->data, "Cannot APPEND without a mailbox.");
+ failf(data, "Cannot APPEND without a mailbox.");
return CURLE_URL_MALFORMAT;
}
+ /* Prepare the mime data if some. */
+ if(data->set.mimepost.kind != MIMEKIND_NONE) {
+ /* Use the whole structure as data. */
+ data->set.mimepost.flags &= ~MIME_BODY_ONLY;
+
+ /* Add external headers and mime version. */
+ curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
+ result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+ NULL, MIMESTRATEGY_MAIL);
+
+ if(!result)
+ if(!Curl_checkheaders(conn, "Mime-Version"))
+ result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
+ "Mime-Version: 1.0");
+
+ /* Make sure we will read the entire mime structure. */
+ if(!result)
+ result = Curl_mime_rewind(&data->set.mimepost);
+
+ if(result)
+ return result;
+
+ data->state.infilesize = Curl_mime_size(&data->set.mimepost);
+
+ /* Read from mime structure. */
+ data->state.fread_func = (curl_read_callback) Curl_mime_read;
+ data->state.in = (void *) &data->set.mimepost;
+ }
+
/* 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");
+ if(data->state.infilesize < 0) {
+ failf(data, "Cannot APPEND with unknown input file size\n");
return CURLE_UPLOAD_FAILED;
}
@@ -729,7 +761,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
/* Send the APPEND command */
result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
- mailbox, conn->data->state.infilesize);
+ mailbox, data->state.infilesize);
free(mailbox);
@@ -789,19 +821,21 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
int imapcode,
imapstate instate)
{
- CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
- if(imapcode != 'O') {
+ if(imapcode == IMAP_RESP_PREAUTH) {
+ /* PREAUTH */
+ struct imap_conn *imapc = &conn->proto.imapc;
+ imapc->preauth = TRUE;
+ infof(data, "PREAUTH connection, already authenticated!\n");
+ }
+ else if(imapcode != IMAP_RESP_OK) {
failf(data, "Got unexpected imap-server response");
- result = CURLE_WEIRD_SERVER_REPLY;
+ return CURLE_WEIRD_SERVER_REPLY;
}
- else
- result = imap_perform_capability(conn);
- return result;
+ return imap_perform_capability(conn);
}
/* For CAPABILITY responses */
@@ -868,7 +902,7 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
line += wordlen;
}
}
- else if(imapcode == 'O') {
+ else if(imapcode == IMAP_RESP_OK) {
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)
@@ -901,7 +935,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
- if(imapcode != 'O') {
+ if(imapcode != IMAP_RESP_OK) {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied");
result = CURLE_USE_SSL_FAILED;
@@ -959,7 +993,7 @@ static CURLcode imap_state_login_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
- if(imapcode != 'O') {
+ if(imapcode != IMAP_RESP_OK) {
failf(data, "Access denied. %c", imapcode);
result = CURLE_LOGIN_DENIED;
}
@@ -987,7 +1021,7 @@ static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
}
- else if(imapcode != 'O')
+ else if(imapcode != IMAP_RESP_OK)
result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
else
/* End of DO phase */
@@ -1016,7 +1050,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
imapc->mailbox_uidvalidity = strdup(tmp);
}
}
- else if(imapcode == 'O') {
+ else if(imapcode == IMAP_RESP_OK) {
/* Check if the UIDVALIDITY has been specified and matches */
if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
@@ -1070,10 +1104,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
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(!curlx_strtoofft(ptr + 1, &endptr, 10, &size)) {
+ if(endptr - ptr > 1 && endptr[0] == '}' &&
+ endptr[1] == '\r' && endptr[2] == '\0')
+ parsed = TRUE;
+ }
}
if(parsed) {
@@ -1147,7 +1182,7 @@ static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
(void)instate; /* No use for this yet */
- if(imapcode != 'O')
+ if(imapcode != IMAP_RESP_OK)
result = CURLE_WEIRD_SERVER_REPLY;
else
/* End of DONE phase */
@@ -1191,7 +1226,7 @@ static CURLcode imap_state_append_final_resp(struct connectdata *conn,
(void)instate; /* No use for this yet */
- if(imapcode != 'O')
+ if(imapcode != IMAP_RESP_OK)
result = CURLE_UPLOAD_FAILED;
else
/* End of DONE phase */
@@ -1419,9 +1454,10 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
result = status; /* use the already set error code */
}
else if(!data->set.connect_only && !imap->custom &&
- (imap->uid || data->set.upload)) {
+ (imap->uid || data->set.upload ||
+ data->set.mimepost.kind != MIMEKIND_NONE)) {
/* Handle responses after FETCH or APPEND transfer has finished */
- if(!data->set.upload)
+ if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
state(conn, IMAP_FETCH_FINAL);
else {
/* End the APPEND command first by sending an empty line */
@@ -1491,7 +1527,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
selected = TRUE;
/* Start the first command in the DO phase */
- if(conn->data->set.upload)
+ if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
/* APPEND can be executed directly */
result = imap_perform_append(conn);
else if(imap->custom && (selected || !imap->mailbox))
@@ -1761,7 +1797,7 @@ static char *imap_atom(const char *str, bool escape_only)
return strdup(str);
/* Calculate the new string length */
- newlen = strlen(str) + backsp_count + quote_count + (others_exists ? 2 : 0);
+ newlen = strlen(str) + backsp_count + quote_count + (escape_only ? 0 : 2);
/* Allocate the new string */
newstr = (char *) malloc((newlen + 1) * sizeof(char));
@@ -1770,7 +1806,7 @@ static char *imap_atom(const char *str, bool escape_only)
/* Surround the string in quotes if necessary */
p2 = newstr;
- if(others_exists) {
+ if(!escape_only) {
newstr[0] = '"';
newstr[newlen - 1] = '"';
p2++;
diff --git a/lib/imap.h b/lib/imap.h
index 5e0e228f5..9fc4ff5a3 100644
--- a/lib/imap.h
+++ b/lib/imap.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -71,6 +71,7 @@ struct imap_conn {
struct pingpong pp;
imapstate state; /* Always use imap.c:state() to change state! */
bool ssldone; /* Is connect() over SSL done? */
+ bool preauth; /* Is this connection PREAUTH? */
struct SASL sasl; /* SASL-related parameters */
unsigned int preftype; /* Preferred authentication type */
int cmdid; /* Last used command ID */
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index 22f08e84d..fb91a505d 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -141,7 +141,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
*/
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))) {
+ if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) {
errno = ENOSPC;
return (NULL);
}
diff --git a/lib/ldap.c b/lib/ldap.c
index 9b85a4815..4059d5d87 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -267,7 +267,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
LDAPMessage *ldapmsg = NULL;
LDAPMessage *entryIterator;
int num = 0;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
int ldap_proto = LDAP_VERSION3;
int ldap_ssl = 0;
char *val_b64 = NULL;
diff --git a/lib/memdebug.c b/lib/memdebug.c
index 65b20e5d0..c12910ef6 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -170,7 +170,7 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
return NULL;
/* alloc at least 64 bytes */
- size = sizeof(struct memdebug)+wantedsize;
+ size = sizeof(struct memdebug) + wantedsize;
mem = (Curl_cmalloc)(size);
if(mem) {
@@ -225,9 +225,9 @@ char *curl_dostrdup(const char *str, int line, const char *source)
if(countcheck("strdup", line, source))
return NULL;
- len=strlen(str)+1;
+ len = strlen(str) + 1;
- mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
+ mem = curl_domalloc(len, 0, NULL); /* NULL prevents logging */
if(mem)
memcpy(mem, str, len);
@@ -269,9 +269,9 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
void *curl_dorealloc(void *ptr, size_t wantedsize,
int line, const char *source)
{
- struct memdebug *mem=NULL;
+ struct memdebug *mem = NULL;
- size_t size = sizeof(struct memdebug)+wantedsize;
+ size_t size = sizeof(struct memdebug) + wantedsize;
DEBUGASSERT(wantedsize != 0);
@@ -407,7 +407,7 @@ void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
/* 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);
+ int res = sclose(sockfd);
curl_mark_sclose(sockfd, line, source);
return res;
}
@@ -415,7 +415,7 @@ int curl_sclose(curl_socket_t sockfd, int line, const char *source)
FILE *curl_fopen(const char *file, const char *mode,
int line, const char *source)
{
- FILE *res=fopen(file, mode);
+ FILE *res = fopen(file, mode);
if(source)
curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
@@ -428,7 +428,7 @@ FILE *curl_fopen(const char *file, const char *mode,
FILE *curl_fdopen(int filedes, const char *mode,
int line, const char *source)
{
- FILE *res=fdopen(filedes, mode);
+ FILE *res = fdopen(filedes, mode);
if(source)
curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
@@ -444,7 +444,7 @@ int curl_fclose(FILE *file, int line, const char *source)
DEBUGASSERT(file != NULL);
- res=fclose(file);
+ res = fclose(file);
if(source)
curl_memlog("FILE %s:%d fclose(%p)\n",
diff --git a/lib/mime.c b/lib/mime.c
new file mode 100644
index 000000000..0aa12d1eb
--- /dev/null
+++ b/lib/mime.c
@@ -0,0 +1,1860 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under 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 <gnurl/curl.h>
+
+#include "mime.h"
+#include "non-ascii.h"
+
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP)
+
+#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
+#include <libgen.h>
+#endif
+
+#include "rand.h"
+#include "slist.h"
+#include "strcase.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef WIN32
+# ifndef R_OK
+# define R_OK 4
+# endif
+#endif
+
+
+#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream"
+#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed"
+#define DISPOSITION_DEFAULT "attachment"
+
+#define READ_ERROR ((size_t) -1)
+
+/* Encoders. */
+static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part);
+static curl_off_t encoder_nop_size(curl_mimepart *part);
+static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part);
+static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part);
+static curl_off_t encoder_base64_size(curl_mimepart *part);
+static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part);
+static curl_off_t encoder_qp_size(curl_mimepart *part);
+
+static const mime_encoder encoders[] = {
+ {"binary", encoder_nop_read, encoder_nop_size},
+ {"8bit", encoder_nop_read, encoder_nop_size},
+ {"7bit", encoder_7bit_read, encoder_nop_size},
+ {"base64", encoder_base64_read, encoder_base64_size},
+ {"quoted-printable", encoder_qp_read, encoder_qp_size},
+ {ZERO_NULL, ZERO_NULL, ZERO_NULL}
+};
+
+/* Base64 encoding table */
+static const char base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* Quoted-printable character class table.
+ *
+ * We cannot rely on ctype functions since quoted-printable input data
+ * is assumed to be ascii-compatible, even on non-ascii platforms. */
+#define QP_OK 1 /* Can be represented by itself. */
+#define QP_SP 2 /* Space or tab. */
+#define QP_CR 3 /* Carriage return. */
+#define QP_LF 4 /* Line-feed. */
+static const unsigned char qp_class[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */
+ 0, QP_SP, QP_LF, 0, 0, QP_CR, 0, 0, /* 08 - 0F */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 17 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 18 - 1F */
+ QP_SP, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 20 - 27 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 28 - 2F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 30 - 37 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0 , QP_OK, QP_OK, /* 38 - 3F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 40 - 47 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 48 - 4F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 50 - 57 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 58 - 5F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 60 - 67 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 68 - 6F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, /* 70 - 77 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0, /* 78 - 7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */
+};
+
+
+/* Binary --> hexadecimal ASCII table. */
+static const char aschex[] =
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x41\x42\x43\x44\x45\x46";
+
+
+
+#ifndef __VMS
+#define filesize(name, stat_data) (stat_data.st_size)
+#define fopen_read fopen
+
+#else
+
+#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, FOPEN_READTEXT); /* VMS */
+ 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;
+ }
+}
+
+#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
+
+/*
+ * 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.
+ *
+ */
+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, FOPEN_READTEXT); /* VMS */
+ break;
+ default:
+ return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
+ }
+}
+
+#define fopen_read vmsfopenread
+#endif
+
+
+#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;
+}
+
+#define basename(x) Curl_basename((x))
+#endif
+
+
+/* Set readback state. */
+static void mimesetstate(mime_state *state, enum mimestate tok, void *ptr)
+{
+ state->state = tok;
+ state->ptr = ptr;
+ state->offset = 0;
+}
+
+
+/* Escape header string into allocated memory. */
+static char *escape_string(const char *src)
+{
+ size_t bytecount = 0;
+ size_t i;
+ char *dst;
+
+ for(i = 0; src[i]; i++)
+ if(src[i] == '"' || src[i] == '\\')
+ bytecount++;
+
+ bytecount += i;
+ dst = malloc(bytecount + 1);
+ if(!dst)
+ return NULL;
+
+ for(i = 0; *src; src++) {
+ if(*src == '"' || *src == '\\')
+ dst[i++] = '\\';
+ dst[i++] = *src;
+ }
+
+ dst[i] = '\0';
+ return dst;
+}
+
+/* Check if header matches. */
+static char *match_header(struct curl_slist *hdr, const char *lbl, size_t len)
+{
+ char *value = NULL;
+
+ if(strncasecompare(hdr->data, lbl, len) && hdr->data[len] == ':')
+ for(value = hdr->data + len + 1; *value == ' '; value++)
+ ;
+ return value;
+}
+
+/* Get a header from an slist. */
+static char *search_header(struct curl_slist *hdrlist, const char *hdr)
+{
+ size_t len = strlen(hdr);
+ char *value = NULL;
+
+ for(; !value && hdrlist; hdrlist = hdrlist->next)
+ value = match_header(hdrlist, hdr, len);
+
+ return value;
+}
+
+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 ! */
+}
+
+/* Initialize data encoder state. */
+static void cleanup_encoder_state(mime_encoder_state *p)
+{
+ p->pos = 0;
+ p->bufbeg = 0;
+ p->bufend = 0;
+}
+
+
+/* Dummy encoder. This is used for 8bit and binary content encodings. */
+static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part)
+{
+ mime_encoder_state *st = &part->encstate;
+ size_t insize = st->bufend - st->bufbeg;
+
+ (void) ateof;
+
+ if(size > insize)
+ size = insize;
+ if(size)
+ memcpy(buffer, st->buf, size);
+ st->bufbeg += size;
+ return size;
+}
+
+static curl_off_t encoder_nop_size(curl_mimepart *part)
+{
+ return part->datasize;
+}
+
+
+/* 7bit encoder: the encoder is just a data validity check. */
+static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part)
+{
+ mime_encoder_state *st = &part->encstate;
+ size_t cursize = st->bufend - st->bufbeg;
+
+ (void) ateof;
+
+ if(size > cursize)
+ size = cursize;
+
+ for(cursize = 0; cursize < size; cursize++) {
+ *buffer = st->buf[st->bufbeg];
+ if(*buffer++ & 0x80)
+ return cursize? cursize: READ_ERROR;
+ st->bufbeg++;
+ }
+
+ return cursize;
+}
+
+
+/* Base64 content encoder. */
+static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part)
+{
+ mime_encoder_state *st = &part->encstate;
+ size_t cursize = 0;
+ int i;
+ char *ptr = buffer;
+
+ while(st->bufbeg < st->bufend) {
+ /* Line full ? */
+ if(st->pos >= MAX_ENCODED_LINE_LENGTH - 4) {
+ /* Yes, we need 2 characters for CRLF. */
+ if(size < 2)
+ break;
+ *ptr++ = '\r';
+ *ptr++ = '\n';
+ st->pos = 0;
+ cursize += 2;
+ size -= 2;
+ }
+
+ /* Be sure there is enough space and input data for a base64 group. */
+ if(size < 4 || st->bufend - st->bufbeg < 3)
+ break;
+
+ /* Encode three bytes a four characters. */
+ i = st->buf[st->bufbeg++] & 0xFF;
+ i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
+ i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
+ *ptr++ = base64[(i >> 18) & 0x3F];
+ *ptr++ = base64[(i >> 12) & 0x3F];
+ *ptr++ = base64[(i >> 6) & 0x3F];
+ *ptr++ = base64[i & 0x3F];
+ cursize += 4;
+ st->pos += 4;
+ size -= 4;
+ }
+
+ /* If at eof, we have to flush the buffered data. */
+ if(ateof && size >= 4) {
+ /* Buffered data size can only be 0, 1 or 2. */
+ ptr[2] = ptr[3] = '=';
+ i = 0;
+ switch(st->bufend - st->bufbeg) {
+ case 2:
+ i = (st->buf[st->bufbeg + 1] & 0xFF) << 8;
+ /* FALLTHROUGH */
+ case 1:
+ i |= (st->buf[st->bufbeg] & 0xFF) << 16;
+ ptr[0] = base64[(i >> 18) & 0x3F];
+ ptr[1] = base64[(i >> 12) & 0x3F];
+ if(++st->bufbeg != st->bufend) {
+ ptr[2] = base64[(i >> 6) & 0x3F];
+ st->bufbeg++;
+ }
+ cursize += 4;
+ st->pos += 4;
+ break;
+ }
+ }
+
+#ifdef CURL_DOES_CONVERSIONS
+ /* This is now textual data, Convert character codes. */
+ if(part->easy && cursize) {
+ CURLcode result = Curl_convert_to_network(part->easy, buffer, cursize);
+ if(result)
+ return READ_ERROR;
+ }
+#endif
+
+ return cursize;
+}
+
+static curl_off_t encoder_base64_size(curl_mimepart *part)
+{
+ curl_off_t size = part->datasize;
+
+ if(size <= 0)
+ return size; /* Unknown size or no data. */
+
+ /* Compute base64 character count. */
+ size = 4 * (1 + (size - 1) / 3);
+
+ /* Effective character count must include CRLFs. */
+ return size + 2 * ((size - 1) / MAX_ENCODED_LINE_LENGTH);
+}
+
+
+/* Quoted-printable lookahead.
+ *
+ * Check if a CRLF or end of data is in input buffer at current position + n.
+ * Return -1 if more data needed, 1 if CRLF or end of data, else 0.
+ */
+static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n)
+{
+ n += st->bufbeg;
+ if(n >= st->bufend && ateof)
+ return 1;
+ if(n + 2 > st->bufend)
+ return ateof? 0: -1;
+ if(qp_class[st->buf[n] & 0xFF] == QP_CR &&
+ qp_class[st->buf[n + 1] & 0xFF] == QP_LF)
+ return 1;
+ return 0;
+}
+
+/* Quoted-printable encoder. */
+static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part)
+{
+ mime_encoder_state *st = &part->encstate;
+ char *ptr = buffer;
+ size_t cursize = 0;
+ int i;
+ size_t len;
+ size_t consumed;
+ int softlinebreak;
+ char buf[4];
+
+ /* On all platforms, input is supposed to be ASCII compatible: for this
+ reason, we use hexadecimal ASCII codes in this function rather than
+ character constants that can be interpreted as non-ascii on some
+ platforms. Preserve ASCII encoding on output too. */
+ while(st->bufbeg < st->bufend) {
+ len = 1;
+ consumed = 1;
+ i = st->buf[st->bufbeg];
+ buf[0] = (char) i;
+ buf[1] = aschex[(i >> 4) & 0xF];
+ buf[2] = aschex[i & 0xF];
+
+ switch(qp_class[st->buf[st->bufbeg] & 0xFF]) {
+ case QP_OK: /* Not a special character. */
+ break;
+ case QP_SP: /* Space or tab. */
+ /* Spacing must be escaped if followed by CRLF. */
+ switch(qp_lookahead_eol(st, ateof, 1)) {
+ case -1: /* More input data needed. */
+ return cursize;
+ case 0: /* No encoding needed. */
+ break;
+ default: /* CRLF after space or tab. */
+ buf[0] = '\x3D'; /* '=' */
+ len = 3;
+ break;
+ }
+ break;
+ case QP_CR: /* Carriage return. */
+ /* If followed by a line-feed, output the CRLF pair.
+ Else escape it. */
+ switch(qp_lookahead_eol(st, ateof, 0)) {
+ case -1: /* Need more data. */
+ return cursize;
+ case 1: /* CRLF found. */
+ buf[len++] = '\x0A'; /* Append '\n'. */
+ consumed = 2;
+ break;
+ default: /* Not followed by LF: escape. */
+ buf[0] = '\x3D'; /* '=' */
+ len = 3;
+ break;
+ }
+ break;
+ default: /* Character must be escaped. */
+ buf[0] = '\x3D'; /* '=' */
+ len = 3;
+ break;
+ }
+
+ /* Be sure the encoded character fits within maximum line length. */
+ if(buf[len - 1] != '\x0A') { /* '\n' */
+ softlinebreak = st->pos + len > MAX_ENCODED_LINE_LENGTH;
+ if(!softlinebreak && st->pos + len == MAX_ENCODED_LINE_LENGTH) {
+ /* We may use the current line only if end of data or followed by
+ a CRLF. */
+ switch(qp_lookahead_eol(st, ateof, consumed)) {
+ case -1: /* Need more data. */
+ return cursize;
+ break;
+ case 0: /* Not followed by a CRLF. */
+ softlinebreak = 1;
+ break;
+ }
+ }
+ if(softlinebreak) {
+ strcpy(buf, "\x3D\x0D\x0A"); /* "=\r\n" */
+ len = 3;
+ consumed = 0;
+ }
+ }
+
+ /* If the output buffer would overflow, do not store. */
+ if(len > size)
+ break;
+
+ /* Append to output buffer. */
+ memcpy(ptr, buf, len);
+ cursize += len;
+ ptr += len;
+ size -= len;
+ st->pos += len;
+ if(buf[len - 1] == '\x0A') /* '\n' */
+ st->pos = 0;
+ st->bufbeg += consumed;
+ }
+
+ return cursize;
+}
+
+static curl_off_t encoder_qp_size(curl_mimepart *part)
+{
+ /* Determining the size can only be done by reading the data: unless the
+ data size is 0, we return it as unknown (-1). */
+ return part->datasize? -1: 0;
+}
+
+
+/* In-memory data callbacks. */
+/* Argument is a pointer to the mime part. */
+static size_t mime_mem_read(char *buffer, size_t size, size_t nitems,
+ void *instream)
+{
+ curl_mimepart *part = (curl_mimepart *) instream;
+ size_t sz = (size_t) part->datasize - part->state.offset;
+
+ (void) size; /* Always 1.*/
+
+ if(sz > nitems)
+ sz = nitems;
+
+ if(sz)
+ memcpy(buffer, (char *) part->data, sz);
+
+ part->state.offset += sz;
+ return sz;
+}
+
+static int mime_mem_seek(void *instream, curl_off_t offset, int whence)
+{
+ curl_mimepart *part = (curl_mimepart *) instream;
+
+ switch(whence) {
+ case SEEK_CUR:
+ offset += part->state.offset;
+ break;
+ case SEEK_END:
+ offset += part->datasize;
+ break;
+ }
+
+ if(offset < 0 || offset > part->datasize)
+ return CURL_SEEKFUNC_FAIL;
+
+ part->state.offset = (size_t) offset;
+ return CURL_SEEKFUNC_OK;
+}
+
+static void mime_mem_free(void *ptr)
+{
+ Curl_safefree(((curl_mimepart *) ptr)->data);
+}
+
+
+/* Named file callbacks. */
+/* Argument is a pointer to the mime part. */
+static int mime_open_file(curl_mimepart * part)
+{
+ /* Open a MIMEKIND_FILE part. */
+
+ if(part->fp)
+ return 0;
+ part->fp = fopen_read(part->data, "rb");
+ return part->fp? 0: -1;
+}
+
+static size_t mime_file_read(char *buffer, size_t size, size_t nitems,
+ void *instream)
+{
+ curl_mimepart *part = (curl_mimepart *) instream;
+
+ if(mime_open_file(part))
+ return READ_ERROR;
+
+ return fread(buffer, size, nitems, part->fp);
+}
+
+static int mime_file_seek(void *instream, curl_off_t offset, int whence)
+{
+ curl_mimepart *part = (curl_mimepart *) instream;
+
+ if(whence == SEEK_SET && !offset && !part->fp)
+ return CURL_SEEKFUNC_OK; /* Not open: implicitly already at BOF. */
+
+ if(mime_open_file(part))
+ return CURL_SEEKFUNC_FAIL;
+
+ return fseek(part->fp, (long) offset, whence)?
+ CURL_SEEKFUNC_CANTSEEK: CURL_SEEKFUNC_OK;
+}
+
+static void mime_file_free(void *ptr)
+{
+ curl_mimepart *part = (curl_mimepart *) ptr;
+
+ if(part->fp) {
+ fclose(part->fp);
+ part->fp = NULL;
+ }
+ Curl_safefree(part->data);
+ part->data = NULL;
+}
+
+
+/* Subparts callbacks. */
+/* Argument is a pointer to the mime structure. */
+
+/* Readback a byte string segment. */
+static size_t readback_bytes(mime_state *state,
+ char *buffer, size_t bufsize,
+ const char *bytes, size_t numbytes,
+ const char *trail)
+{
+ size_t sz;
+
+ sz = numbytes - state->offset;
+
+ if(numbytes > state->offset) {
+ sz = numbytes - state->offset;
+ bytes += state->offset;
+ }
+ else {
+ size_t tsz = strlen(trail);
+
+ sz = state->offset - numbytes;
+ if(sz >= tsz)
+ return 0;
+ bytes = trail + sz;
+ sz = tsz - sz;
+ }
+
+ if(sz > bufsize)
+ sz = bufsize;
+
+ memcpy(buffer, bytes, sz);
+ state->offset += sz;
+ return sz;
+}
+
+/* Read a non-encoded part content. */
+static size_t read_part_content(curl_mimepart *part,
+ char *buffer, size_t bufsize)
+{
+ size_t sz = 0;
+
+ if(part->readfunc)
+ sz = part->readfunc(buffer, 1, bufsize, part->arg);
+ return sz;
+}
+
+/* Read and encode part content. */
+static size_t read_encoded_part_content(curl_mimepart *part,
+ char *buffer, size_t bufsize)
+{
+ mime_encoder_state *st = &part->encstate;
+ size_t cursize = 0;
+ size_t sz;
+ bool ateof = FALSE;
+
+ while(bufsize) {
+ if(st->bufbeg < st->bufend || ateof) {
+ /* Encode buffered data. */
+ sz = part->encoder->encodefunc(buffer, bufsize, ateof, part);
+ switch(sz) {
+ case 0:
+ if(ateof)
+ return cursize;
+ break;
+ case CURL_READFUNC_ABORT:
+ case CURL_READFUNC_PAUSE:
+ case READ_ERROR:
+ return cursize? cursize: sz;
+ default:
+ cursize += sz;
+ buffer += sz;
+ bufsize -= sz;
+ continue;
+ }
+ }
+
+ /* We need more data in input buffer. */
+ if(st->bufbeg) {
+ size_t len = st->bufend - st->bufbeg;
+
+ if(len)
+ memmove(st->buf, st->buf + st->bufbeg, len);
+ st->bufbeg = 0;
+ st->bufend = len;
+ }
+ if(st->bufend >= sizeof st->buf)
+ return cursize? cursize: READ_ERROR; /* Buffer full. */
+ sz = read_part_content(part, st->buf + st->bufend,
+ sizeof st->buf - st->bufend);
+ switch(sz) {
+ case 0:
+ ateof = TRUE;
+ break;
+ case CURL_READFUNC_ABORT:
+ case CURL_READFUNC_PAUSE:
+ case READ_ERROR:
+ return cursize? cursize: sz;
+ default:
+ st->bufend += sz;
+ break;
+ }
+ }
+
+ return cursize;
+}
+
+/* Readback a mime part. */
+static size_t readback_part(curl_mimepart *part,
+ char *buffer, size_t bufsize)
+{
+ size_t cursize = 0;
+ size_t sz;
+ struct curl_slist *hdr;
+#ifdef CURL_DOES_CONVERSIONS
+ char *convbuf = buffer;
+#endif
+
+ /* Readback from part. */
+
+ while(bufsize) {
+ sz = 0;
+ hdr = (struct curl_slist *) part->state.ptr;
+ switch(part->state.state) {
+ case MIMESTATE_BEGIN:
+ mimesetstate(&part->state, part->flags & MIME_BODY_ONLY? MIMESTATE_BODY:
+ MIMESTATE_CURLHEADERS, part->curlheaders);
+ break;
+ case MIMESTATE_USERHEADERS:
+ if(!hdr) {
+ mimesetstate(&part->state, MIMESTATE_EOH, NULL);
+ break;
+ }
+ if(match_header(hdr, "Content-Type", 12)) {
+ mimesetstate(&part->state, MIMESTATE_USERHEADERS, hdr->next);
+ break;
+ }
+ /* FALLTHROUGH */
+ case MIMESTATE_CURLHEADERS:
+ if(!hdr)
+ mimesetstate(&part->state, MIMESTATE_USERHEADERS, part->userheaders);
+ else {
+ sz = readback_bytes(&part->state, buffer, bufsize,
+ hdr->data, strlen(hdr->data), "\r\n");
+ if(!sz)
+ mimesetstate(&part->state, part->state.state, hdr->next);
+ }
+ break;
+ case MIMESTATE_EOH:
+ sz = readback_bytes(&part->state, buffer, bufsize, "\r\n", 2, "");
+ if(!sz)
+ mimesetstate(&part->state, MIMESTATE_BODY, NULL);
+ break;
+ case MIMESTATE_BODY:
+#ifdef CURL_DOES_CONVERSIONS
+ if(part->easy && convbuf < buffer) {
+ CURLcode result = Curl_convert_to_network(part->easy, convbuf,
+ buffer - convbuf);
+ if(result)
+ return READ_ERROR;
+ convbuf = buffer;
+ }
+#endif
+ cleanup_encoder_state(&part->encstate);
+ mimesetstate(&part->state, MIMESTATE_CONTENT, NULL);
+ break;
+ case MIMESTATE_CONTENT:
+ if(part->encoder)
+ sz = read_encoded_part_content(part, buffer, bufsize);
+ else
+ sz = read_part_content(part, buffer, bufsize);
+ switch(sz) {
+ case 0:
+ mimesetstate(&part->state, MIMESTATE_END, NULL);
+ /* Try sparing open file descriptors. */
+ if(part->kind == MIMEKIND_FILE && part->fp) {
+ fclose(part->fp);
+ part->fp = NULL;
+ }
+ /* FALLTHROUGH */
+ case CURL_READFUNC_ABORT:
+ case CURL_READFUNC_PAUSE:
+ case READ_ERROR:
+ return cursize? cursize: sz;
+ }
+ break;
+ case MIMESTATE_END:
+ return cursize;
+ default:
+ break; /* Other values not in part state. */
+ }
+
+ /* Bump buffer and counters according to read size. */
+ cursize += sz;
+ buffer += sz;
+ bufsize -= sz;
+ }
+
+#ifdef CURL_DOES_CONVERSIONS
+ if(part->easy && convbuf < buffer &&
+ part->state.state < MIMESTATE_BODY) {
+ CURLcode result = Curl_convert_to_network(part->easy, convbuf,
+ buffer - convbuf);
+ if(result)
+ return READ_ERROR;
+ }
+#endif
+
+ return cursize;
+}
+
+/* Readback from mime. */
+static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
+ void *instream)
+{
+ curl_mime *mime = (curl_mime *) instream;
+ size_t cursize = 0;
+ size_t sz;
+ curl_mimepart *part;
+#ifdef CURL_DOES_CONVERSIONS
+ char *convbuf = buffer;
+#endif
+
+ (void) size; /* Always 1. */
+
+ while(nitems) {
+ sz = 0;
+ part = mime->state.ptr;
+ switch(mime->state.state) {
+ case MIMESTATE_BEGIN:
+ case MIMESTATE_BODY:
+#ifdef CURL_DOES_CONVERSIONS
+ convbuf = buffer;
+#endif
+ mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart);
+ /* The first boundary always follows the header termination empty line,
+ so is always preceded by a CRLK. We can then spare 2 characters
+ by skipping the leading CRLF in boundary. */
+ mime->state.offset += 2;
+ break;
+ case MIMESTATE_BOUNDARY1:
+ sz = readback_bytes(&mime->state, buffer, nitems, "\r\n--", 4, "");
+ if(!sz)
+ mimesetstate(&mime->state, MIMESTATE_BOUNDARY2, part);
+ break;
+ case MIMESTATE_BOUNDARY2:
+ sz = readback_bytes(&mime->state, buffer, nitems, mime->boundary,
+ strlen(mime->boundary), part? "\r\n": "--\r\n");
+ if(!sz) {
+#ifdef CURL_DOES_CONVERSIONS
+ if(mime->easy && convbuf < buffer) {
+ CURLcode result = Curl_convert_to_network(mime->easy, convbuf,
+ buffer - convbuf);
+ if(result)
+ return READ_ERROR;
+ convbuf = buffer;
+ }
+#endif
+ mimesetstate(&mime->state, MIMESTATE_CONTENT, part);
+ }
+ break;
+ case MIMESTATE_CONTENT:
+ if(!part) {
+ mimesetstate(&mime->state, MIMESTATE_END, NULL);
+ break;
+ }
+ sz = readback_part(part, buffer, nitems);
+ switch(sz) {
+ case CURL_READFUNC_ABORT:
+ case CURL_READFUNC_PAUSE:
+ case READ_ERROR:
+ return cursize? cursize: sz;
+ case 0:
+#ifdef CURL_DOES_CONVERSIONS
+ convbuf = buffer;
+#endif
+ mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, part->nextpart);
+ break;
+ }
+ break;
+ case MIMESTATE_END:
+ return cursize;
+ default:
+ break; /* other values not used in mime state. */
+ }
+
+ /* Bump buffer and counters according to read size. */
+ cursize += sz;
+ buffer += sz;
+ nitems -= sz;
+ }
+
+#ifdef CURL_DOES_CONVERSIONS
+ if(mime->easy && convbuf < buffer &&
+ mime->state.state <= MIMESTATE_CONTENT) {
+ CURLcode result = Curl_convert_to_network(mime->easy, convbuf,
+ buffer - convbuf);
+ if(result)
+ return READ_ERROR;
+ }
+#endif
+
+ return cursize;
+}
+
+static int mime_part_rewind(curl_mimepart *part)
+{
+ int res = CURL_SEEKFUNC_OK;
+ enum mimestate targetstate = MIMESTATE_BEGIN;
+
+ if(part->flags & MIME_BODY_ONLY)
+ targetstate = MIMESTATE_BODY;
+ cleanup_encoder_state(&part->encstate);
+ if(part->state.state > targetstate) {
+ res = CURL_SEEKFUNC_CANTSEEK;
+ if(part->seekfunc) {
+ res = part->seekfunc(part->arg, (curl_off_t) 0, SEEK_SET);
+ switch(res) {
+ case CURL_SEEKFUNC_OK:
+ case CURL_SEEKFUNC_FAIL:
+ case CURL_SEEKFUNC_CANTSEEK:
+ break;
+ case -1: /* For fseek() error. */
+ res = CURL_SEEKFUNC_CANTSEEK;
+ break;
+ default:
+ res = CURL_SEEKFUNC_FAIL;
+ break;
+ }
+ }
+ }
+
+ if(res == CURL_SEEKFUNC_OK)
+ mimesetstate(&part->state, targetstate, NULL);
+
+ return res;
+}
+
+static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
+{
+ curl_mime *mime = (curl_mime *) instream;
+ curl_mimepart *part;
+ int result = CURL_SEEKFUNC_OK;
+ int res;
+
+ if(whence != SEEK_SET || offset)
+ return CURL_SEEKFUNC_CANTSEEK; /* Only support full rewind. */
+
+ if(mime->state.state == MIMESTATE_BEGIN)
+ return CURL_SEEKFUNC_OK; /* Already rewound. */
+
+ for(part = mime->firstpart; part; part = part->nextpart) {
+ res = mime_part_rewind(part);
+ if(res != CURL_SEEKFUNC_OK)
+ result = res;
+ }
+
+ if(result == CURL_SEEKFUNC_OK)
+ mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
+
+ return result;
+}
+
+static void mime_subparts_free(void *ptr)
+{
+ curl_mime *mime = (curl_mime *) ptr;
+ curl_mime_free(mime);
+}
+
+
+/* Release part content. */
+static void cleanup_part_content(curl_mimepart *part)
+{
+ if(part->freefunc)
+ part->freefunc(part->arg);
+
+ part->readfunc = NULL;
+ part->seekfunc = NULL;
+ part->freefunc = NULL;
+ part->arg = (void *) part; /* Defaults to part itself. */
+ part->data = NULL;
+ part->fp = NULL;
+ part->datasize = (curl_off_t) 0; /* No size yet. */
+ part->encoder = NULL;
+ cleanup_encoder_state(&part->encstate);
+ part->kind = MIMEKIND_NONE;
+}
+
+void Curl_mime_cleanpart(curl_mimepart *part)
+{
+ cleanup_part_content(part);
+ curl_slist_free_all(part->curlheaders);
+ if(part->flags & MIME_USERHEADERS_OWNER)
+ curl_slist_free_all(part->userheaders);
+ Curl_safefree(part->mimetype);
+ Curl_safefree(part->name);
+ Curl_safefree(part->filename);
+ Curl_mime_initpart(part, part->easy);
+}
+
+/* Recursively delete a mime handle and its parts. */
+void curl_mime_free(curl_mime *mime)
+{
+ curl_mimepart *part;
+
+ if(mime) {
+ while(mime->firstpart) {
+ part = mime->firstpart;
+ mime->firstpart = part->nextpart;
+ Curl_mime_cleanpart(part);
+ free(part);
+ }
+
+ free(mime->boundary);
+ free(mime);
+ }
+}
+
+/*
+ * Mime build functions.
+ */
+
+/* Create a mime handle. */
+curl_mime *curl_mime_init(struct Curl_easy *easy)
+{
+ curl_mime *mime;
+
+ mime = (curl_mime *) malloc(sizeof *mime);
+
+ if(mime) {
+ mime->easy = easy;
+ mime->parent = NULL;
+ mime->firstpart = NULL;
+ mime->lastpart = NULL;
+
+ /* Get a part boundary. */
+ mime->boundary = malloc(24 + MIME_RAND_BOUNDARY_CHARS + 1);
+ if(!mime->boundary) {
+ free(mime);
+ return NULL;
+ }
+
+ memset(mime->boundary, '-', 24);
+ Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
+ MIME_RAND_BOUNDARY_CHARS + 1);
+ mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
+ }
+
+ return mime;
+}
+
+/* Initialize a mime part. */
+void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
+{
+ memset((char *) part, 0, sizeof *part);
+ part->easy = easy;
+ mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
+}
+
+/* Create a mime part and append it to a mime handle's part list. */
+curl_mimepart *curl_mime_addpart(curl_mime *mime)
+{
+ curl_mimepart *part;
+
+ if(!mime)
+ return NULL;
+
+ part = (curl_mimepart *) malloc(sizeof *part);
+
+ if(part) {
+ Curl_mime_initpart(part, mime->easy);
+ part->parent = mime;
+
+ if(mime->lastpart)
+ mime->lastpart->nextpart = part;
+ else
+ mime->firstpart = part;
+
+ mime->lastpart = part;
+ }
+
+ return part;
+}
+
+/* Set mime part name. */
+CURLcode curl_mime_name(curl_mimepart *part, const char *name)
+{
+ if(!part)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ Curl_safefree(part->name);
+ part->name = NULL;
+
+ if(name) {
+ part->name = strdup(name);
+ if(!part->name)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ return CURLE_OK;
+}
+
+/* Set mime part remote file name. */
+CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
+{
+ if(!part)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ Curl_safefree(part->filename);
+ part->filename = NULL;
+
+ if(filename) {
+ part->filename = strdup(filename);
+ if(!part->filename)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ return CURLE_OK;
+}
+
+/* Set mime part content from memory data. */
+CURLcode curl_mime_data(curl_mimepart *part,
+ const char *data, size_t datasize)
+{
+ if(!part)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ cleanup_part_content(part);
+
+ if(data) {
+ if(datasize == CURL_ZERO_TERMINATED)
+ datasize = strlen(data);
+
+ part->data = malloc(datasize + 1);
+ if(!part->data)
+ return CURLE_OUT_OF_MEMORY;
+
+ part->datasize = datasize;
+
+ if(datasize)
+ memcpy(part->data, data, datasize);
+ part->data[datasize] = '\0'; /* Set a nul terminator as sentinel. */
+
+ part->readfunc = mime_mem_read;
+ part->seekfunc = mime_mem_seek;
+ part->freefunc = mime_mem_free;
+ part->kind = MIMEKIND_DATA;
+ }
+
+ return CURLE_OK;
+}
+
+/* Set mime part content from named local file. */
+CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
+{
+ CURLcode result = CURLE_OK;
+ char *base;
+
+ if(!part)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ cleanup_part_content(part);
+
+ if(filename) {
+ struct_stat sbuf;
+
+ if(stat(filename, &sbuf) || access(filename, R_OK))
+ result = CURLE_READ_ERROR;
+
+ part->data = strdup(filename);
+ if(!part->data)
+ result = CURLE_OUT_OF_MEMORY;
+
+ part->datasize = -1;
+ if(!result && S_ISREG(sbuf.st_mode)) {
+ part->datasize = filesize(filename, sbuf);
+ part->seekfunc = mime_file_seek;
+ }
+
+ part->readfunc = mime_file_read;
+ part->freefunc = mime_file_free;
+ part->kind = MIMEKIND_FILE;
+
+ /* As a side effect, set the filename to the current file's base name.
+ It is possible to withdraw this by explicitly calling
+ curl_mime_filename() with a NULL filename argument after the current
+ call. */
+ base = strippath(filename);
+ if(!base)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ CURLcode res = curl_mime_filename(part, base);
+
+ if(res)
+ result = res;
+ free(base);
+ }
+ }
+ return result;
+}
+
+/* Set mime part type. */
+CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
+{
+ if(!part)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ Curl_safefree(part->mimetype);
+ part->mimetype = NULL;
+
+ if(mimetype) {
+ part->mimetype = strdup(mimetype);
+ if(!part->mimetype)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ return CURLE_OK;
+}
+
+/* Set mime data transfer encoder. */
+CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
+{
+ CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+ const mime_encoder *mep;
+
+ if(!part)
+ return result;
+
+ part->encoder = NULL;
+
+ if(!encoding)
+ return CURLE_OK; /* Removing current encoder. */
+
+ for(mep = encoders; mep->name; mep++)
+ if(strcasecompare(encoding, mep->name)) {
+ part->encoder = mep;
+ result = CURLE_OK;
+ }
+
+ return result;
+}
+
+/* Set mime part headers. */
+CURLcode curl_mime_headers(curl_mimepart *part,
+ struct curl_slist *headers, int take_ownership)
+{
+ if(!part)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(part->flags & MIME_USERHEADERS_OWNER) {
+ curl_slist_free_all(part->userheaders);
+ part->flags &= ~MIME_USERHEADERS_OWNER;
+ }
+ part->userheaders = headers;
+ if(headers && take_ownership)
+ part->flags |= MIME_USERHEADERS_OWNER;
+ return CURLE_OK;
+}
+
+/* Set mime part content from callback. */
+CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize,
+ curl_read_callback readfunc,
+ curl_seek_callback seekfunc,
+ curl_free_callback freefunc, void *arg)
+{
+ if(!part)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ cleanup_part_content(part);
+
+ if(readfunc) {
+ part->readfunc = readfunc;
+ part->seekfunc = seekfunc;
+ part->freefunc = freefunc;
+ part->arg = arg;
+ part->datasize = datasize;
+ part->kind = MIMEKIND_CALLBACK;
+ }
+
+ return CURLE_OK;
+}
+
+/* Set mime part content from subparts. */
+CURLcode curl_mime_subparts(curl_mimepart *part,
+ curl_mime *subparts)
+{
+ if(!part)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ /* Accept setting twice the same subparts. */
+ if(part->kind == MIMEKIND_MULTIPART && part->arg == subparts)
+ return CURLE_OK;
+
+ cleanup_part_content(part);
+
+ if(subparts) {
+ /* Must belong to the same data handle. */
+ if(part->easy && subparts->easy && part->easy != subparts->easy)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ /* Should not have been attached already. */
+ if(subparts->parent)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ subparts->parent = part;
+ part->readfunc = mime_subparts_read;
+ part->seekfunc = mime_subparts_seek;
+ part->freefunc = mime_subparts_free;
+ part->arg = subparts;
+ part->datasize = -1;
+ part->kind = MIMEKIND_MULTIPART;
+ }
+
+ return CURLE_OK;
+}
+
+
+/* Readback from top mime. */
+/* Argument is the dummy top part. */
+size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
+{
+ curl_mimepart *part = (curl_mimepart *) instream;
+
+ (void) size; /* Always 1. */
+ return readback_part(part, buffer, nitems);
+}
+
+/* Rewind mime stream. */
+CURLcode Curl_mime_rewind(curl_mimepart *part)
+{
+ return mime_part_rewind(part) == CURL_SEEKFUNC_OK?
+ CURLE_OK: CURLE_SEND_FAIL_REWIND;
+}
+
+/* Compute header list size. */
+static size_t slist_size(struct curl_slist *s,
+ size_t overhead, const char *skip)
+{
+ size_t size = 0;
+ size_t skiplen = skip? strlen(skip): 0;
+
+ for(; s; s = s->next)
+ if(!skip || !match_header(s, skip, skiplen))
+ size += strlen(s->data) + overhead;
+ return size;
+}
+
+/* Get/compute multipart size. */
+static curl_off_t multipart_size(curl_mime *mime)
+{
+ curl_off_t size;
+ curl_off_t sz;
+ size_t boundarysize;
+ curl_mimepart *part;
+
+ if(!mime)
+ return 0; /* Not present -> empty. */
+
+ boundarysize = 4 + strlen(mime->boundary) + 2;
+ size = boundarysize; /* Final boundary - CRLF after headers. */
+
+ for(part = mime->firstpart; part; part = part->nextpart) {
+ sz = Curl_mime_size(part);
+
+ if(sz < 0)
+ size = sz;
+
+ if(size >= 0)
+ size += boundarysize + sz;
+ }
+
+ return size;
+}
+
+/* Get/compute mime size. */
+curl_off_t Curl_mime_size(curl_mimepart *part)
+{
+ curl_off_t size;
+
+ if(part->datasize < 0 && part->kind == MIMEKIND_MULTIPART)
+ part->datasize = multipart_size(part->arg);
+
+ size = part->datasize;
+
+ if(part->encoder)
+ size = part->encoder->sizefunc(part);
+
+ if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) {
+ /* Compute total part size. */
+ size += slist_size(part->curlheaders, 2, NULL);
+ size += slist_size(part->userheaders, 2, "Content-Type");
+ size += 2; /* CRLF after headers. */
+ }
+ return size;
+}
+
+/* Add a header. */
+/* VARARGS2 */
+CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
+{
+ struct curl_slist *hdr = NULL;
+ char *s = NULL;
+ va_list ap;
+
+ va_start(ap, fmt);
+ s = curl_mvaprintf(fmt, ap);
+ va_end(ap);
+
+ if(s) {
+ hdr = Curl_slist_append_nodup(*slp, s);
+ if(hdr)
+ *slp = hdr;
+ else
+ free(s);
+ }
+
+ return hdr? CURLE_OK: CURLE_OUT_OF_MEMORY;
+}
+
+/* Add a content type header. */
+static CURLcode add_content_type(struct curl_slist **slp,
+ const char *type, const char *boundary)
+{
+ return Curl_mime_add_header(slp, "Content-Type: %s%s%s", type,
+ boundary? "; boundary=": "",
+ boundary? boundary: "");
+}
+
+
+static const char *ContentTypeForFilename(const char *filename)
+{
+ unsigned int i;
+
+ /*
+ * If no content 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"},
+ {".png", "image/png"},
+ {".svg", "image/svg+xml"},
+ {".txt", "text/plain"},
+ {".htm", "text/html"},
+ {".html", "text/html"},
+ {".pdf", "application/pdf"},
+ {".xml", "application/xml"}
+ };
+
+ if(filename) {
+ size_t len1 = strlen(filename);
+ const char *nameend = filename + len1;
+
+ for(i = 0; i < sizeof ctts / sizeof ctts[0]; i++) {
+ size_t len2 = strlen(ctts[i].extension);
+
+ if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
+ return ctts[i].type;
+ }
+ }
+ return NULL;
+}
+
+CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+ const char *contenttype,
+ const char *disposition,
+ enum mimestrategy strategy)
+{
+ curl_mime *mime = NULL;
+ const char *boundary = NULL;
+ char *s;
+ const char *cte = NULL;
+ CURLcode ret = CURLE_OK;
+
+ /* Get rid of previously prepared headers. */
+ curl_slist_free_all(part->curlheaders);
+ part->curlheaders = NULL;
+
+ /* Be sure we won't access old headers later. */
+ if(part->state.state == MIMESTATE_CURLHEADERS)
+ mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL);
+
+ /* Build the content-type header. */
+ s = search_header(part->userheaders, "Content-Type");
+ if(s)
+ contenttype = s;
+ if(part->mimetype)
+ contenttype = part->mimetype;
+ if(!contenttype) {
+ switch(part->kind) {
+ case MIMEKIND_MULTIPART:
+ contenttype = MULTIPART_CONTENTTYPE_DEFAULT;
+ break;
+ case MIMEKIND_FILE:
+ contenttype = ContentTypeForFilename(part->filename);
+ if(!contenttype)
+ contenttype = ContentTypeForFilename(part->data);
+ if(!contenttype && part->filename)
+ contenttype = FILE_CONTENTTYPE_DEFAULT;
+ break;
+ default:
+ contenttype = ContentTypeForFilename(part->filename);
+ break;
+ }
+ }
+
+ if(part->kind == MIMEKIND_MULTIPART) {
+ mime = (curl_mime *) part->arg;
+ if(mime)
+ boundary = mime->boundary;
+ }
+ else if(contenttype && strcasecompare(contenttype, "text/plain"))
+ if(strategy == MIMESTRATEGY_MAIL || !part->filename)
+ contenttype = NULL;
+
+ /* Issue content-disposition header only if not already set by caller. */
+ if(!search_header(part->userheaders, "Content-Disposition")) {
+ if(!disposition)
+ if(part->filename || part->name ||
+ (contenttype && !strncasecompare(contenttype, "multipart/", 10)))
+ disposition = DISPOSITION_DEFAULT;
+ if(disposition && curl_strequal(disposition, "attachment") &&
+ !part->name && !part->filename)
+ disposition = NULL;
+ if(disposition) {
+ char *name = NULL;
+ char *filename = NULL;
+
+ if(part->name) {
+ name = escape_string(part->name);
+ if(!name)
+ ret = CURLE_OUT_OF_MEMORY;
+ }
+ if(!ret && part->filename) {
+ filename = escape_string(part->filename);
+ if(!filename)
+ ret = CURLE_OUT_OF_MEMORY;
+ }
+ if(!ret)
+ ret = Curl_mime_add_header(&part->curlheaders,
+ "Content-Disposition: %s%s%s%s%s%s%s",
+ disposition,
+ name? "; name=\"": "",
+ name? name: "",
+ name? "\"": "",
+ filename? "; filename=\"": "",
+ filename? filename: "",
+ filename? "\"": "");
+ Curl_safefree(name);
+ Curl_safefree(filename);
+ if(ret)
+ return ret;
+ }
+ }
+
+ /* Issue Content-Type header. */
+ if(contenttype) {
+ ret = add_content_type(&part->curlheaders, contenttype, boundary);
+ if(ret)
+ return ret;
+ }
+
+ /* Content-Transfer-Encoding header. */
+ if(!search_header(part->userheaders, "Content-Transfer-Encoding")) {
+ if(part->encoder)
+ cte = part->encoder->name;
+ else if(contenttype && strategy == MIMESTRATEGY_MAIL &&
+ part->kind != MIMEKIND_MULTIPART)
+ cte = "8bit";
+ if(cte) {
+ ret = Curl_mime_add_header(&part->curlheaders,
+ "Content-Transfer-Encoding: %s", cte);
+ if(ret)
+ return ret;
+ }
+ }
+
+ /* If we were reading curl-generated headers, restart with new ones (this
+ should not occur). */
+ if(part->state.state == MIMESTATE_CURLHEADERS)
+ mimesetstate(&part->state, MIMESTATE_CURLHEADERS, part->curlheaders);
+
+ /* Process subparts. */
+ if(part->kind == MIMEKIND_MULTIPART && mime) {
+ curl_mimepart *subpart;
+
+ disposition = NULL;
+ if(strcasecompare(contenttype, "multipart/form-data"))
+ disposition = "form-data";
+ for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
+ ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy);
+ if(ret)
+ return ret;
+ }
+ }
+ return ret;
+}
+
+#else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
+
+/* Mime not compiled in: define stubs for externally-referenced functions. */
+curl_mime *curl_mime_init(CURL *easy)
+{
+ (void) easy;
+ return NULL;
+}
+
+void curl_mime_free(curl_mime *mime)
+{
+ (void) mime;
+}
+
+curl_mimepart *curl_mime_addpart(curl_mime *mime)
+{
+ (void) mime;
+ return NULL;
+}
+
+CURLcode curl_mime_name(curl_mimepart *part, const char *name)
+{
+ (void) part;
+ (void) name;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
+{
+ (void) part;
+ (void) filename;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
+{
+ (void) part;
+ (void) mimetype;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
+{
+ (void) part;
+ (void) encoding;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_data(curl_mimepart *part,
+ const char *data, size_t datasize)
+{
+ (void) part;
+ (void) data;
+ (void) datasize;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
+{
+ (void) part;
+ (void) filename;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_data_cb(curl_mimepart *part,
+ curl_off_t datasize,
+ curl_read_callback readfunc,
+ curl_seek_callback seekfunc,
+ curl_free_callback freefunc,
+ void *arg)
+{
+ (void) part;
+ (void) datasize;
+ (void) readfunc;
+ (void) seekfunc;
+ (void) freefunc;
+ (void) arg;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
+{
+ (void) part;
+ (void) subparts;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_headers(curl_mimepart *part,
+ struct curl_slist *headers, int take_ownership)
+{
+ (void) part;
+ (void) headers;
+ (void) take_ownership;
+ return CURLE_NOT_BUILT_IN;
+}
+
+void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
+{
+ (void) part;
+ (void) easy;
+}
+
+void Curl_mime_cleanpart(curl_mimepart *part)
+{
+ (void) part;
+}
+
+CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+ const char *contenttype,
+ const char *disposition,
+ enum mimestrategy strategy)
+{
+ (void) part;
+ (void) contenttype;
+ (void) disposition;
+ (void) strategy;
+ return CURLE_NOT_BUILT_IN;
+}
+
+curl_off_t Curl_mime_size(curl_mimepart *part)
+{
+ (void) part;
+ return (curl_off_t) -1;
+}
+
+size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
+{
+ (void) buffer;
+ (void) size;
+ (void) nitems;
+ (void) instream;
+ return 0;
+}
+
+CURLcode Curl_mime_rewind(curl_mimepart *part)
+{
+ (void) part;
+ return CURLE_NOT_BUILT_IN;
+}
+
+/* VARARGS2 */
+CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
+{
+ (void) slp;
+ (void) fmt;
+ return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
diff --git a/lib/mime.h b/lib/mime.h
new file mode 100644
index 000000000..a14485707
--- /dev/null
+++ b/lib/mime.h
@@ -0,0 +1,135 @@
+#ifndef HEADER_CURL_MIME_H
+#define HEADER_CURL_MIME_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under 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 MIME_RAND_BOUNDARY_CHARS 16 /* Nb. of random boundary chars. */
+#define MAX_ENCODED_LINE_LENGTH 76 /* Maximum encoded line length. */
+#define ENCODING_BUFFER_SIZE 256 /* Encoding temp buffers size. */
+
+/* Part flags. */
+#define MIME_USERHEADERS_OWNER (1 << 0)
+#define MIME_BODY_ONLY (1 << 1)
+
+/* Part source kinds. */
+enum mimekind {
+ MIMEKIND_NONE = 0, /* Part not set. */
+ MIMEKIND_DATA, /* Allocated mime data. */
+ MIMEKIND_FILE, /* Data from file. */
+ MIMEKIND_CALLBACK, /* Data from `read' callback. */
+ MIMEKIND_MULTIPART, /* Data is a mime subpart. */
+ MIMEKIND_LAST
+};
+
+/* Readback state tokens. */
+enum mimestate {
+ MIMESTATE_BEGIN, /* Readback has not yet started. */
+ MIMESTATE_CURLHEADERS, /* In curl-generated headers. */
+ MIMESTATE_USERHEADERS, /* In caller's supplied headers. */
+ MIMESTATE_EOH, /* End of headers. */
+ MIMESTATE_BODY, /* Placeholder. */
+ MIMESTATE_BOUNDARY1, /* In boundary prefix. */
+ MIMESTATE_BOUNDARY2, /* In boundary. */
+ MIMESTATE_CONTENT, /* In content. */
+ MIMESTATE_END, /* End of part reached. */
+ MIMESTATE_LAST
+};
+
+/* Mime headers strategies. */
+enum mimestrategy {
+ MIMESTRATEGY_MAIL, /* Mime mail. */
+ MIMESTRATEGY_FORM, /* HTTP post form. */
+ MIMESTRATEGY_LAST
+};
+
+/* Content transfer encoder. */
+typedef struct {
+ const char * name; /* Encoding name. */
+ size_t (*encodefunc)(char *buffer, size_t size, bool ateof,
+ curl_mimepart *part); /* Encoded read. */
+ curl_off_t (*sizefunc)(curl_mimepart *part); /* Encoded size. */
+} mime_encoder;
+
+/* Content transfer encoder state. */
+typedef struct {
+ size_t pos; /* Position on output line. */
+ size_t bufbeg; /* Next data index in input buffer. */
+ size_t bufend; /* First unused byte index in input buffer. */
+ char buf[ENCODING_BUFFER_SIZE]; /* Input buffer. */
+} mime_encoder_state;
+
+/* Mime readback state. */
+typedef struct {
+ enum mimestate state; /* Current state token. */
+ void *ptr; /* State-dependent pointer. */
+ size_t offset; /* State-dependent offset. */
+} mime_state;
+
+/* A mime multipart. */
+struct curl_mime_s {
+ struct Curl_easy *easy; /* The associated easy handle. */
+ curl_mimepart *parent; /* Parent part. */
+ curl_mimepart *firstpart; /* First part. */
+ curl_mimepart *lastpart; /* Last part. */
+ char *boundary; /* The part boundary. */
+ mime_state state; /* Current readback state. */
+};
+
+/* A mime part. */
+struct curl_mimepart_s {
+ struct Curl_easy *easy; /* The associated easy handle. */
+ curl_mime *parent; /* Parent mime structure. */
+ curl_mimepart *nextpart; /* Forward linked list. */
+ enum mimekind kind; /* The part kind. */
+ char *data; /* Memory data or file name. */
+ curl_read_callback readfunc; /* Read function. */
+ curl_seek_callback seekfunc; /* Seek function. */
+ curl_free_callback freefunc; /* Argument free function. */
+ void *arg; /* Argument to callback functions. */
+ FILE *fp; /* File pointer. */
+ struct curl_slist *curlheaders; /* Part headers. */
+ struct curl_slist *userheaders; /* Part headers. */
+ char *mimetype; /* Part mime type. */
+ char *filename; /* Remote file name. */
+ char *name; /* Data name. */
+ curl_off_t datasize; /* Expected data size. */
+ unsigned int flags; /* Flags. */
+ mime_state state; /* Current readback state. */
+ const mime_encoder *encoder; /* Content data encoder. */
+ mime_encoder_state encstate; /* Data encoder state. */
+};
+
+
+/* Prototypes. */
+void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
+void Curl_mime_cleanpart(curl_mimepart *part);
+CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+ const char *contenttype,
+ const char *disposition,
+ enum mimestrategy strategy);
+curl_off_t Curl_mime_size(curl_mimepart *part);
+size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
+ void *instream);
+CURLcode Curl_mime_rewind(curl_mimepart *part);
+CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
+
+#endif /* HEADER_CURL_MIME_H */
diff --git a/lib/mprintf.c b/lib/mprintf.c
index 68545bfac..0def1b0a5 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -46,10 +46,6 @@
* 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
@@ -111,7 +107,7 @@ static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
} WHILE_FALSE
/* Data type to read from the arglist */
-typedef enum {
+typedef enum {
FORMAT_UNKNOWN = 0,
FORMAT_STRING,
FORMAT_PTR,
@@ -181,7 +177,7 @@ struct asprintf {
static long dprintf_DollarString(char *input, char **end)
{
- int number=0;
+ int number = 0;
while(ISDIGIT(*input)) {
number *= 10;
number += *input-'0';
@@ -237,7 +233,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
long width;
long precision;
int flags;
- long max_param=0;
+ long max_param = 0;
long i;
while(*fmt) {
@@ -326,7 +322,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
break;
#if defined(MP_HAVE_INT_EXTENSIONS)
case 'I':
-#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
flags |= FLAGS_LONGLONG;
#else
flags |= FLAGS_LONG;
@@ -348,14 +344,14 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
case 'z':
/* the code below generates a warning if -Wunreachable-code is
used */
-#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG)
+#if (SIZEOF_SIZE_T > SIZEOF_LONG)
flags |= FLAGS_LONGLONG;
#else
flags |= FLAGS_LONG;
#endif
break;
case 'O':
-#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
flags |= FLAGS_LONGLONG;
#else
flags |= FLAGS_LONG;
@@ -380,7 +376,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
else
width = param_num;
if(width > max_param)
- max_param=width;
+ max_param = width;
break;
default:
break;
@@ -486,7 +482,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
}
/* Read the arg list parameters into our data list */
- for(i=0; i<max_param; i++) {
+ for(i = 0; i<max_param; i++) {
/* Width/precision arguments must be read before the main argument
they are attached to */
if(vto[i].flags & FLAGS_WIDTHPARAM) {
@@ -573,7 +569,7 @@ static int dprintf_formatf(
int done = 0;
long param; /* current parameter to read */
- long param_num=0; /* parameter counter */
+ long param_num = 0; /* parameter counter */
va_stack_t vto[MAX_PARAMETERS];
char *endpos[MAX_PARAMETERS];
@@ -643,7 +639,7 @@ static int dprintf_formatf(
/* If this is a positional parameter, the position must follow immediately
after the %, thus create a %<num>$ sequence */
- param=dprintf_DollarString(f, &f);
+ param = dprintf_DollarString(f, &f);
if(!param)
param = param_num;
@@ -952,7 +948,7 @@ static int dprintf_formatf(
output characters */
(sprintf)(work, formatbuf, p->data.dnum);
DEBUGASSERT(strlen(work) <= sizeof(work));
- for(fptr=work; *fptr; fptr++)
+ for(fptr = work; *fptr; fptr++)
OUTCHAR(*fptr);
}
break;
@@ -984,7 +980,7 @@ static int dprintf_formatf(
/* fputc() look-alike */
static int addbyter(int output, FILE *data)
{
- struct nsprintf *infop=(struct nsprintf *)data;
+ struct nsprintf *infop = (struct nsprintf *)data;
unsigned char outc = (unsigned char)output;
if(infop->length < infop->max) {
@@ -1032,7 +1028,7 @@ int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
/* fputc() look-alike */
static int alloc_addbyter(int output, FILE *data)
{
- struct asprintf *infop=(struct asprintf *)data;
+ struct asprintf *infop = (struct asprintf *)data;
unsigned char outc = (unsigned char)output;
if(!infop->buffer) {
@@ -1042,9 +1038,9 @@ static int alloc_addbyter(int output, FILE *data)
return -1; /* fail */
}
infop->alloc = 32;
- infop->len =0;
+ infop->len = 0;
}
- else if(infop->len+1 >= infop->alloc) {
+ else if(infop->len + 1 >= infop->alloc) {
char *newptr = NULL;
size_t newsize = infop->alloc*2;
@@ -1133,7 +1129,7 @@ int curl_msprintf(char *buffer, const char *format, ...)
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 */
+ *buffer = 0; /* we terminate this with a zero byte */
return retcode;
}
@@ -1162,7 +1158,7 @@ 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 */
+ *buffer = 0; /* we terminate this with a zero byte */
return retcode;
}
diff --git a/lib/multi.c b/lib/multi.c
index 1f8dfc5ce..e2596801f 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -592,7 +592,7 @@ static CURLcode multi_done(struct connectdata **connp,
/* if the transfer was completed in a paused state there can be buffered
data left to free */
- for(i=0; i < data->state.tempcount; i++) {
+ for(i = 0; i < data->state.tempcount; i++) {
free(data->state.tempwrite[i].buf);
}
data->state.tempcount = 0;
@@ -802,8 +802,8 @@ static int waitconnect_getsock(struct connectdata *conn,
int numsocks)
{
int i;
- int s=0;
- int rc=0;
+ int s = 0;
+ int rc = 0;
if(!numsocks)
return GETSOCK_BLANK;
@@ -813,7 +813,7 @@ static int waitconnect_getsock(struct connectdata *conn,
return Curl_ssl_getsock(conn, sock, numsocks);
#endif
- for(i=0; i<2; i++) {
+ for(i = 0; i<2; i++) {
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
sock[s] = conn->tempsock[i];
rc |= GETSOCK_WRITESOCK(s++);
@@ -924,7 +924,7 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
Some easy handles may not have connected to the remote host yet,
and then we must make sure that is done. */
struct Curl_easy *data;
- int this_max_fd=-1;
+ int this_max_fd = -1;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
int bitmap;
int i;
@@ -933,11 +933,11 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
- data=multi->easyp;
+ data = multi->easyp;
while(data) {
bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
- for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
@@ -994,11 +994,11 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
timeout_ms = (int)timeout_internal;
/* Count up how many fds we have from the multi handle */
- data=multi->easyp;
+ data = multi->easyp;
while(data) {
bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
- for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
if(bitmap & GETSOCK_READSOCK(i)) {
@@ -1041,11 +1041,11 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
if(curlfds) {
/* Add the curl handles to our pollfds first */
- data=multi->easyp;
+ data = multi->easyp;
while(data) {
bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
- for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
if(bitmap & GETSOCK_READSOCK(i)) {
@@ -1229,15 +1229,15 @@ static CURLcode multi_reconnect_request(struct connectdata **connp)
*/
static void do_complete(struct connectdata *conn)
{
- conn->data->req.chunk=FALSE;
+ conn->data->req.chunk = FALSE;
conn->data->req.maxfd = (conn->sockfd>conn->writesockfd?
- conn->sockfd:conn->writesockfd)+1;
+ conn->sockfd:conn->writesockfd) + 1;
Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
}
static CURLcode multi_do(struct connectdata **connp, bool *done)
{
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
struct connectdata *conn = *connp;
struct Curl_easy *data = conn->data;
@@ -1286,7 +1286,7 @@ static CURLcode multi_do(struct connectdata **connp, bool *done)
static CURLcode multi_do_more(struct connectdata *conn, int *complete)
{
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
*complete = 0;
@@ -1415,7 +1415,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
switch(data->mstate) {
case CURLM_STATE_INIT:
/* init this transfer. */
- result=Curl_pretransfer(data);
+ result = Curl_pretransfer(data);
if(!result) {
/* after init, go CONNECT */
@@ -1697,7 +1697,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
* back to the CONNECT phase so we can try again.
*/
char *newurl = NULL;
- followtype follow=FOLLOW_NONE;
+ followtype follow = FOLLOW_NONE;
CURLcode drc;
bool retry = FALSE;
@@ -1783,7 +1783,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(control) {
/* if positive, advance to DO_DONE
if negative, go back to DOING */
- multistate(data, control==1?
+ multistate(data, control == 1?
CURLM_STATE_DO_DONE:
CURLM_STATE_DOING);
rc = CURLM_CALL_MULTI_PERFORM;
@@ -1938,7 +1938,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multi_done(&data->easy_conn, result, TRUE);
}
else if(done) {
- followtype follow=FOLLOW_NONE;
+ followtype follow = FOLLOW_NONE;
/* call this even if the readwrite function returned error */
Curl_posttransfer(data);
@@ -2144,14 +2144,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
{
struct Curl_easy *data;
- CURLMcode returncode=CURLM_OK;
+ CURLMcode returncode = CURLM_OK;
struct Curl_tree *t;
struct curltime now = Curl_tvnow();
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
- data=multi->easyp;
+ data = multi->easyp;
while(data) {
CURLMcode result;
SIGPIPE_VARIABLE(pipe_st);
@@ -2246,7 +2246,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
/* remove all easy handles */
data = multi->easyp;
while(data) {
- nextdata=data->next;
+ 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);
@@ -2326,7 +2326,7 @@ static void singlesocket(struct Curl_multi *multi,
int num;
unsigned int curraction;
- for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
+ 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
@@ -2338,7 +2338,7 @@ static void singlesocket(struct Curl_multi *multi,
longer supervised ones and add new ones */
/* walk over the sockets we got right now */
- for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
+ for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
(curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
i++) {
int action = CURL_POLL_NONE;
@@ -2382,10 +2382,10 @@ static void singlesocket(struct Curl_multi *multi,
/* 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++) {
+ for(i = 0; i< data->numsocks; i++) {
int j;
s = data->sockets[i];
- for(j=0; j<num; j++) {
+ for(j = 0; j<num; j++) {
if(s == socks[j]) {
/* this is still supervised */
s = CURL_SOCKET_BAD;
@@ -2558,7 +2558,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
/* walk through each easy handle and do the socket state change magic
and callbacks */
if(result != CURLM_BAD_HANDLE) {
- data=multi->easyp;
+ data = multi->easyp;
while(data) {
singlesocket(multi, data);
data = data->next;
@@ -2795,7 +2795,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
* processors while the diff is still present but less than one
* millisecond! instead we return 1 until the time is ripe.
*/
- *timeout_ms=1;
+ *timeout_ms = 1;
}
else
/* 0 means immediately */
@@ -2831,7 +2831,7 @@ static int update_timer(struct Curl_multi *multi)
return -1;
}
if(timeout_ms < 0) {
- static const struct curltime none={0, 0};
+ static const struct curltime 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
@@ -3115,13 +3115,13 @@ void Curl_multi_dump(struct Curl_multi *multi)
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) {
+ 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++) {
+ for(i = 0; i < data->numsocks; i++) {
curl_socket_t s = data->sockets[i];
struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
diff --git a/lib/netrc.c b/lib/netrc.c
index e7afdbd44..084908ac7 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -56,14 +56,15 @@ int Curl_parsenetrc(const char *host,
char *netrcfile)
{
FILE *file;
- int retcode=1;
+ int retcode = 1;
int specific_login = (*loginp && **loginp != 0);
bool netrc_alloc = FALSE;
- enum host_lookup_state state=NOTHING;
+ 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 */
+ 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"
@@ -88,7 +89,7 @@ int Curl_parsenetrc(const char *host,
}
else {
struct passwd *pw;
- pw= getpwuid(geteuid());
+ pw = getpwuid(geteuid());
if(pw) {
home = pw->pw_dir;
}
@@ -113,19 +114,19 @@ int Curl_parsenetrc(const char *host,
if(file) {
char *tok;
char *tok_buf;
- bool done=FALSE;
+ 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);
+ tok = strtok_r(netrcbuffer, " \t\n", &tok_buf);
if(tok && *tok == '#')
/* treat an initial hash as a comment line */
continue;
while(!done && tok) {
if((*loginp && **loginp) && (*passwordp && **passwordp)) {
- done=TRUE;
+ done = TRUE;
break;
}
@@ -136,22 +137,22 @@ int Curl_parsenetrc(const char *host,
delimiter that starts the stuff entered for this machine,
after this we need to search for 'login' and
'password'. */
- state=HOSTFOUND;
+ state = HOSTFOUND;
}
else if(strcasecompare("default", tok)) {
- state=HOSTVALID;
- retcode=0; /* we did find our host */
+ state = HOSTVALID;
+ retcode = 0; /* we did find our host */
}
break;
case HOSTFOUND:
if(strcasecompare(host, tok)) {
/* and yes, this is our host! */
- state=HOSTVALID;
- retcode=0; /* we did find our host */
+ state = HOSTVALID;
+ retcode = 0; /* we did find our host */
}
else
/* not our host */
- state=NOTHING;
+ state = NOTHING;
break;
case HOSTVALID:
/* we are now parsing sub-keywords concerning "our" host */
@@ -167,7 +168,7 @@ int Curl_parsenetrc(const char *host,
goto out;
}
}
- state_login=0;
+ state_login = 0;
}
else if(state_password) {
if(state_our_login || !specific_login) {
@@ -178,12 +179,12 @@ int Curl_parsenetrc(const char *host,
goto out;
}
}
- state_password=0;
+ state_password = 0;
}
else if(strcasecompare("login", tok))
- state_login=1;
+ state_login = 1;
else if(strcasecompare("password", tok))
- state_password=1;
+ state_password = 1;
else if(strcasecompare("machine", tok)) {
/* ok, there's machine here go => */
state = HOSTFOUND;
diff --git a/lib/non-ascii.c b/lib/non-ascii.c
index 8fd0437dc..b9ac225e2 100644
--- a/lib/non-ascii.c
+++ b/lib/non-ascii.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -82,7 +82,7 @@ CURLcode Curl_convert_clone(struct Curl_easy *data,
CURLcode Curl_convert_to_network(struct Curl_easy *data,
char *buffer, size_t length)
{
- if(data->set.convtonetwork) {
+ if(data && data->set.convtonetwork) {
/* use translation callback */
CURLcode result = data->set.convtonetwork(buffer, length);
if(result) {
@@ -96,14 +96,18 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
else {
#ifdef HAVE_ICONV
/* do the translation ourselves */
+ iconv_t tmpcd = (iconv_t) -1;
+ iconv_t *cd = &tmpcd;
char *input_ptr, *output_ptr;
size_t in_bytes, out_bytes, rc;
/* 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) {
+ if(data)
+ cd = &data->outbound_cd;
+ if(*cd == (iconv_t)-1) {
+ *cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
+ CURL_ICONV_CODESET_OF_HOST);
+ if(*cd == (iconv_t)-1) {
failf(data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_NETWORK,
@@ -115,8 +119,10 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
/* call iconv */
input_ptr = output_ptr = buffer;
in_bytes = out_bytes = length;
- rc = iconv(data->outbound_cd, (const char **)&input_ptr, &in_bytes,
+ rc = iconv(*cd, &input_ptr, &in_bytes,
&output_ptr, &out_bytes);
+ if(!data)
+ iconv_close(tmpcd);
if((rc == ICONV_ERROR) || (in_bytes != 0)) {
failf(data,
"The Curl_convert_to_network iconv call failed with errno %i: %s",
@@ -139,7 +145,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
CURLcode Curl_convert_from_network(struct Curl_easy *data,
char *buffer, size_t length)
{
- if(data->set.convfromnetwork) {
+ if(data && data->set.convfromnetwork) {
/* use translation callback */
CURLcode result = data->set.convfromnetwork(buffer, length);
if(result) {
@@ -153,14 +159,18 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
else {
#ifdef HAVE_ICONV
/* do the translation ourselves */
+ iconv_t tmpcd = (iconv_t) -1;
+ iconv_t *cd = &tmpcd;
char *input_ptr, *output_ptr;
size_t in_bytes, out_bytes, rc;
/* 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) {
+ if(data)
+ cd = &data->inbound_cd;
+ if(*cd == (iconv_t)-1) {
+ *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_OF_NETWORK);
+ if(*cd == (iconv_t)-1) {
failf(data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_HOST,
@@ -172,8 +182,10 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
/* call iconv */
input_ptr = output_ptr = buffer;
in_bytes = out_bytes = length;
- rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
+ rc = iconv(*cd, &input_ptr, &in_bytes,
&output_ptr, &out_bytes);
+ if(!data)
+ iconv_close(tmpcd);
if((rc == ICONV_ERROR) || (in_bytes != 0)) {
failf(data,
"Curl_convert_from_network iconv call failed with errno %i: %s",
@@ -196,7 +208,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
char *buffer, size_t length)
{
- if(data->set.convfromutf8) {
+ if(data && data->set.convfromutf8) {
/* use translation callback */
CURLcode result = data->set.convfromutf8(buffer, length);
if(result) {
@@ -210,15 +222,19 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
else {
#ifdef HAVE_ICONV
/* do the translation ourselves */
- const char *input_ptr;
+ iconv_t tmpcd = (iconv_t) -1;
+ iconv_t *cd = &tmpcd;
+ char *input_ptr;
char *output_ptr;
size_t in_bytes, out_bytes, rc;
/* 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) {
+ if(data)
+ cd = &data->utf8_cd;
+ if(*cd == (iconv_t)-1) {
+ *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+ CURL_ICONV_CODESET_FOR_UTF8);
+ if(*cd == (iconv_t)-1) {
failf(data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_HOST,
@@ -230,8 +246,10 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
/* call iconv */
input_ptr = output_ptr = buffer;
in_bytes = out_bytes = length;
- rc = iconv(data->utf8_cd, &input_ptr, &in_bytes,
+ rc = iconv(*cd, &input_ptr, &in_bytes,
&output_ptr, &out_bytes);
+ if(!data)
+ iconv_close(tmpcd);
if((rc == ICONV_ERROR) || (in_bytes != 0)) {
failf(data,
"The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
@@ -301,29 +319,4 @@ void Curl_convert_close(struct Curl_easy *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 Curl_easy *data, struct FormData *form)
-{
- CURLcode result;
-
- if(!data)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- while(form) {
- if(form->type == FORM_DATA) {
- result = Curl_convert_to_network(data, form->line, form->length);
- /* Curl_convert_to_network calls failf if unsuccessful */
- if(result)
- return result;
- }
-
- form = form->next;
- }
-
- return CURLE_OK;
-}
-
#endif /* CURL_DOES_CONVERSIONS */
diff --git a/lib/non-ascii.h b/lib/non-ascii.h
index e27f1f41f..5fb5771e0 100644
--- a/lib/non-ascii.h
+++ b/lib/non-ascii.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,7 +48,6 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
char *buffer, size_t length);
CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
char *buffer, size_t length);
-CURLcode Curl_convert_form(struct Curl_easy *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
@@ -57,7 +56,6 @@ CURLcode Curl_convert_form(struct Curl_easy *data, struct FormData *form);
#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/lib/openldap.c b/lib/openldap.c
index 1b32d1f22..931719f97 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
+ * Copyright (C) 2010, 2017, Howard Chu, <hyc@openldap.org>
* Copyright (C) 2011 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
@@ -152,7 +152,7 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
{
ldapconninfo *li;
LDAPURLDesc *lud;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
int rc, proto;
CURLcode status;
@@ -198,7 +198,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
(void)done;
strcpy(hosturl, "ldap");
- ptr = hosturl+4;
+ ptr = hosturl + 4;
if(conn->handler->flags & PROTOPT_SSL)
*ptr++ = 's';
snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
@@ -354,7 +354,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
int rc = 0;
LDAPURLDesc *ludp = NULL;
int msgid;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
connkeep(conn, "OpenLDAP do");
@@ -519,7 +519,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
else
binary = 0;
- for(i=0; bvals[i].bv_val != NULL; i++) {
+ for(i = 0; bvals[i].bv_val != NULL; i++) {
int binval = 0;
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
if(writeerr) {
@@ -549,7 +549,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
else {
/* check for unprintable characters */
unsigned int j;
- for(j=0; j<bvals[i].bv_len; j++)
+ for(j = 0; j<bvals[i].bv_len; j++)
if(!ISPRINT(bvals[i].bv_val[j])) {
binval = 1;
break;
diff --git a/lib/parsedate.c b/lib/parsedate.c
index c39add846..9ba5b94ad 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -167,20 +167,20 @@ static const struct tzinfo tz[]= {
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 */
+ {"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 */
+ {"K", 10 * 60}, /* Kilo */
+ {"L", 11 * 60}, /* Lima */
+ {"M", 12 * 60}, /* Mike */
{"N", -1 * 60}, /* November */
{"O", -2 * 60}, /* Oscar */
{"P", -3 * 60}, /* Papa */
@@ -205,14 +205,14 @@ static int checkday(const char *check, size_t len)
{
int i;
const char * const *what;
- bool found= FALSE;
+ bool found = FALSE;
if(len > 3)
what = &weekday[0];
else
what = &Curl_wkday[0];
- for(i=0; i<7; i++) {
+ for(i = 0; i<7; i++) {
if(strcasecompare(check, what[0])) {
- found=TRUE;
+ found = TRUE;
break;
}
what++;
@@ -224,12 +224,12 @@ static int checkmonth(const char *check)
{
int i;
const char * const *what;
- bool found= FALSE;
+ bool found = FALSE;
what = &Curl_month[0];
- for(i=0; i<12; i++) {
+ for(i = 0; i<12; i++) {
if(strcasecompare(check, what[0])) {
- found=TRUE;
+ found = TRUE;
break;
}
what++;
@@ -244,12 +244,12 @@ static int checktz(const char *check)
{
unsigned int i;
const struct tzinfo *what;
- bool found= FALSE;
+ bool found = FALSE;
what = tz;
- for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) {
+ for(i = 0; i< sizeof(tz)/sizeof(tz[0]); i++) {
if(strcasecompare(check, what->name)) {
- found=TRUE;
+ found = TRUE;
break;
}
what++;
@@ -331,21 +331,21 @@ static time_t my_timegm(struct my_tm *tm)
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;
+ 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;
+ bool found = FALSE;
skip(&date);
@@ -386,7 +386,7 @@ static int parsedate(const char *date, time_t *output)
/* a digit */
int val;
char *end;
- int len=0;
+ int len = 0;
if((secnum == -1) &&
(3 == sscanf(date, "%02d:%02d:%02d%n",
&hournum, &minnum, &secnum, &len))) {
diff --git a/lib/pingpong.c b/lib/pingpong.c
index 5ed79b718..b8f214005 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -47,10 +47,10 @@
time_t Curl_pp_state_timeout(struct pingpong *pp)
{
struct connectdata *conn = pp->conn;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
time_t timeout_ms; /* in milliseconds */
time_t timeout2_ms; /* in milliseconds */
- long response_time= (data->set.server_response_timeout)?
+ 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
@@ -85,10 +85,10 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
int rc;
time_t interval_ms;
time_t timeout_ms = Curl_pp_state_timeout(pp);
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
- if(timeout_ms <=0) {
+ if(timeout_ms <= 0) {
failf(data, "server response timeout");
return CURLE_OPERATION_TIMEDOUT; /* already too little time */
}
@@ -270,7 +270,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
size_t *size) /* size of the response */
{
ssize_t perline; /* count bytes per line */
- bool keepon=TRUE;
+ bool keepon = TRUE;
ssize_t gotbytes;
char *ptr;
struct connectdata *conn = pp->conn;
@@ -281,7 +281,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
*code = 0; /* 0 for errors or not done */
*size = 0;
- ptr=buf + pp->nread_resp;
+ ptr = buf + pp->nread_resp;
/* number of bytes in the current line, so far */
perline = (ssize_t)(ptr-pp->linestart_resp);
@@ -297,7 +297,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
* 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+data->set.buffer_size+1));
+ DEBUGASSERT((ptr + pp->cache_size) <= (buf + data->set.buffer_size + 1));
memcpy(ptr, pp->cache, pp->cache_size);
gotbytes = (ssize_t)pp->cache_size;
free(pp->cache); /* free the cache */
@@ -351,7 +351,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
pp->nread_resp += gotbytes;
for(i = 0; i < gotbytes; ptr++, i++) {
perline++;
- if(*ptr=='\n') {
+ 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 */
@@ -378,17 +378,17 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
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 */
+ 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;
+ perline = 0; /* line starts over here */
+ pp->linestart_resp = ptr + 1;
}
}
@@ -490,7 +490,7 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
}
else {
free(pp->sendthis);
- pp->sendthis=NULL;
+ pp->sendthis = NULL;
pp->sendleft = pp->sendsize = 0;
pp->response = Curl_tvnow();
}
diff --git a/lib/progress.c b/lib/progress.c
index 740ff2887..00609d9ee 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -134,7 +134,7 @@ int Curl_pgrsDone(struct connectdata *conn)
{
int rc;
struct Curl_easy *data = conn->data;
- data->progress.lastshow=0;
+ data->progress.lastshow = 0;
rc = Curl_pgrsUpdate(conn); /* the final (forced) update */
if(rc)
return rc;
@@ -149,14 +149,9 @@ int Curl_pgrsDone(struct connectdata *conn)
return 0;
}
-/* reset all times except redirect, and reset the known transfer sizes */
-void Curl_pgrsResetTimesSizes(struct Curl_easy *data)
+/* reset the known transfer sizes */
+void Curl_pgrsResetTransferSizes(struct Curl_easy *data)
{
- data->progress.t_nslookup = 0;
- data->progress.t_connect = 0;
- data->progress.t_pretransfer = 0;
- data->progress.t_starttransfer = 0;
-
Curl_pgrsSetDownloadSize(data, -1);
Curl_pgrsSetUploadSize(data, -1);
}
@@ -181,6 +176,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
case TIMER_STARTSINGLE:
/* This is set at the start of each single fetch */
data->progress.t_startsingle = now;
+ data->progress.is_t_startransfer_set = false;
break;
case TIMER_STARTACCEPT:
data->progress.t_acceptdata = now;
@@ -205,10 +201,11 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
* This prevents repeated invocations of the function from incorrectly
* changing the t_starttransfer time.
*/
- if (*delta > data->progress.t_redirect) {
+ if(data->progress.is_t_startransfer_set) {
return;
}
else {
+ data->progress.is_t_startransfer_set = true;
break;
}
case TIMER_POSTRANSFER:
@@ -222,7 +219,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
time_t us = Curl_tvdiff_us(now, data->progress.t_startsingle);
if(!us)
us++; /* make sure at least one microsecond passed */
- *delta = us;
+ *delta += us;
}
}
@@ -230,6 +227,7 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
{
data->progress.speeder_c = 0; /* reset the progress meter display */
data->progress.start = Curl_tvnow();
+ data->progress.is_t_startransfer_set = false;
data->progress.ul_limit_start.tv_sec = 0;
data->progress.ul_limit_start.tv_usec = 0;
data->progress.dl_limit_start.tv_sec = 0;
@@ -354,9 +352,9 @@ int Curl_pgrsUpdate(struct connectdata *conn)
struct curltime 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 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;
@@ -367,10 +365,10 @@ int Curl_pgrsUpdate(struct connectdata *conn)
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 ulestimate = 0;
+ curl_off_t dlestimate = 0;
curl_off_t total_estimate;
- bool shownow=FALSE;
+ bool shownow = FALSE;
now = Curl_tvnow(); /* what time is it */
@@ -410,7 +408,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
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)?
+ 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 */
@@ -420,14 +418,14 @@ int Curl_pgrsUpdate(struct connectdata *conn)
/* 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)?
+ 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 */
+ span_ms = 1; /* at least one millisecond MUST have passed */
/* Calculate the average speed the last 'span_ms' milliseconds */
{
@@ -457,22 +455,22 @@ int Curl_pgrsUpdate(struct connectdata *conn)
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);
+ 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;
}
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);
+ 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;
diff --git a/lib/progress.h b/lib/progress.h
index ed57e3368..9333ab25c 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -47,7 +47,7 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
int Curl_pgrsUpdate(struct connectdata *);
-void Curl_pgrsResetTimesSizes(struct Curl_easy *data);
+void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
long Curl_pgrsLimitWaitTime(curl_off_t cursize,
curl_off_t startsize,
diff --git a/lib/rtsp.c b/lib/rtsp.c
index 8b895ed64..d3e62aada 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -250,7 +250,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
static CURLcode rtsp_do(struct connectdata *conn, bool *done)
{
struct Curl_easy *data = conn->data;
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
struct RTSP *rtsp = data->req.protop;
struct HTTP *http;
@@ -749,14 +749,28 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
struct Curl_easy *data = conn->data;
size_t wrote;
curl_write_callback writeit;
+ void *user_ptr;
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 the user has configured CURLOPT_INTERLEAVEFUNCTION then use that
+ function and any configured CURLOPT_INTERLEAVEDATA to write out the RTP
+ data. Otherwise, use the CURLOPT_WRITEFUNCTION with the CURLOPT_WRITEDATA
+ pointer to write out the RTP data. */
+ if(data->set.fwrite_rtp) {
+ writeit = data->set.fwrite_rtp;
+ user_ptr = data->set.rtp_out;
+ }
+ else
+ {
+ writeit = data->set.fwrite_func;
+ user_ptr = data->set.out;
+ }
+
+ wrote = writeit(ptr, 1, len, user_ptr);
if(CURL_WRITEFUNC_PAUSE == wrote) {
failf(data, "Cannot pause RTP");
diff --git a/lib/security.c b/lib/security.c
index f4a876341..9b989681f 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -7,7 +7,7 @@
* rewrite to work around the paragraph 2 in the BSD licenses as explained
* below.
*
- * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
+ * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
*
* Copyright (C) 2001 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
@@ -115,7 +115,7 @@ static char level_to_char(int level)
static int ftp_send_command(struct connectdata *conn, const char *message, ...)
{
int ftp_code;
- ssize_t nread=0;
+ ssize_t nread = 0;
va_list args;
char print_buffer[50];
diff --git a/lib/sendf.c b/lib/sendf.c
index 6a472fb47..d2bc10b46 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -63,7 +63,7 @@ static size_t convert_lineends(struct Curl_easy *data,
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);
+ memmove(startPtr, startPtr + 1, size-1);
size--;
/* and it wasn't a bare CR but a CRLF conversion instead */
data->state.crlf_conversions++;
@@ -75,7 +75,7 @@ static size_t convert_lineends(struct Curl_easy *data,
inPtr = outPtr = memchr(startPtr, '\r', size);
if(inPtr) {
/* at least one CR, now look for CRLF */
- while(inPtr < (startPtr+size-1)) {
+ 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 */
@@ -98,7 +98,7 @@ static size_t convert_lineends(struct Curl_easy *data,
inPtr++;
} /* end of while loop */
- if(inPtr < startPtr+size) {
+ if(inPtr < startPtr + size) {
/* handle last byte */
if(*inPtr == '\r') {
/* deal with a CR at the end of the buffer */
@@ -112,7 +112,7 @@ static size_t convert_lineends(struct Curl_easy *data,
}
outPtr++;
}
- if(outPtr < startPtr+size)
+ if(outPtr < startPtr + size)
/* tidy up by null terminating the now shorter data */
*outPtr = '\0';
@@ -279,7 +279,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
if(!s)
return CURLE_OUT_OF_MEMORY; /* failure */
- bytes_written=0;
+ bytes_written = 0;
write_len = strlen(s);
sptr = s;
@@ -387,7 +387,7 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
#endif
) {
/* this is just a case of EWOULDBLOCK */
- bytes_written=0;
+ bytes_written = 0;
*code = CURLE_AGAIN;
}
else {
@@ -480,7 +480,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
bool newtype = TRUE;
if(s->tempcount) {
- for(i=0; i< s->tempcount; i++) {
+ for(i = 0; i< s->tempcount; i++) {
if(s->tempwrite[i].type == type) {
/* data for this type exists */
newtype = FALSE;
@@ -704,7 +704,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
us use the correct ssl handle. */
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
- *n=0; /* reset amount to zero */
+ *n = 0; /* reset amount to zero */
/* If session can pipeline, check connection buffer */
if(pipelining) {
@@ -823,8 +823,8 @@ int Curl_debug(struct Curl_easy *data, curl_infotype type,
int rc;
if(data->set.printhost && conn && conn->host.dispname) {
char buffer[160];
- const char *t=NULL;
- const char *w="Data";
+ const char *t = NULL;
+ const char *w = "Data";
switch(type) {
case CURLINFO_HEADER_IN:
w = "Header";
diff --git a/lib/smtp.c b/lib/smtp.c
index 9f9bd1485..971236db7 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -67,6 +67,7 @@
#include "transfer.h"
#include "escape.h"
#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "mime.h"
#include "socks.h"
#include "smtp.h"
#include "strtoofft.h"
@@ -530,8 +531,40 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
}
}
+ /* Prepare the mime data if some. */
+ if(data->set.mimepost.kind != MIMEKIND_NONE) {
+ /* Use the whole structure as data. */
+ data->set.mimepost.flags &= ~MIME_BODY_ONLY;
+
+ /* Add external headers and mime version. */
+ curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
+ result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+ NULL, MIMESTRATEGY_MAIL);
+
+ if(!result)
+ if(!Curl_checkheaders(conn, "Mime-Version"))
+ result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
+ "Mime-Version: 1.0");
+
+ /* Make sure we will read the entire mime structure. */
+ if(!result)
+ result = Curl_mime_rewind(&data->set.mimepost);
+
+ if(result) {
+ free(from);
+ free(auth);
+ return result;
+ }
+
+ data->state.infilesize = Curl_mime_size(&data->set.mimepost);
+
+ /* Read from mime structure. */
+ data->state.fread_func = (curl_read_callback) Curl_mime_read;
+ data->state.in = (void *) &data->set.mimepost;
+ }
+
/* Calculate the optional SIZE parameter */
- if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) {
+ if(conn->proto.smtpc.size_supported && data->state.infilesize > 0) {
size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
if(!size) {
@@ -1159,7 +1192,8 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode 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) {
+ else if(!data->set.connect_only && data->set.mail_rcpt &&
+ (data->set.upload || data->set.mimepost.kind)) {
/* 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.
@@ -1249,7 +1283,7 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
smtp->rcpt = data->set.mail_rcpt;
/* Start the first command in the DO phase */
- if(data->set.upload && data->set.mail_rcpt)
+ if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
result = smtp_perform_mail(conn);
else
diff --git a/lib/socks.c b/lib/socks.c
index 000cd9c2d..e64cb98d4 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -154,7 +154,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
/* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) {
struct Curl_dns_entry *dns;
- Curl_addrinfo *hp=NULL;
+ Curl_addrinfo *hp = NULL;
int rc;
rc = Curl_resolv(conn, hostname, remote_port, &dns);
@@ -171,7 +171,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
* returns a Curl_addrinfo pointer that may not always look the same.
*/
if(dns)
- hp=dns->addr;
+ hp = dns->addr;
if(hp) {
char buf[64];
Curl_printable_address(hp, buf, sizeof(buf));
@@ -213,7 +213,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
return CURLE_COULDNT_CONNECT;
}
/* copy the proxy name WITH trailing zero */
- memcpy(socksreq + 8, proxy_user, plen+1);
+ memcpy(socksreq + 8, proxy_user, plen + 1);
}
/*
@@ -306,7 +306,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
", request rejected or failed.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
- (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
+ (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
return CURLE_COULDNT_CONNECT;
case 92:
@@ -316,7 +316,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
"identd on the client.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
- (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
+ (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
return CURLE_COULDNT_CONNECT;
case 93:
@@ -326,7 +326,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
"report different user-ids.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
- (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
+ (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
return CURLE_COULDNT_CONNECT;
default:
@@ -335,7 +335,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
", Unknown.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
- (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
+ (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
return CURLE_COULDNT_CONNECT;
}
@@ -483,7 +483,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
(void)curlx_nonblock(sock, FALSE);
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
if(result || (actualread != 2)) {
failf(data, "Unable to receive initial SOCKS5 response.");
return CURLE_COULDNT_CONNECT;
@@ -542,7 +542,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
return CURLE_COULDNT_CONNECT;
}
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
if(result || (actualread != 2)) {
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
return CURLE_COULDNT_CONNECT;
@@ -615,7 +615,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
* returns a Curl_addrinfo pointer that may not always look the same.
*/
if(dns)
- hp=dns->addr;
+ hp = dns->addr;
if(hp) {
int i;
char buf[64];
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 54d063504..96948ac4b 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -65,7 +65,7 @@ static int check_gss_err(struct Curl_easy *data,
&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);
+ strcpy(buf + len, (char *) status_string.value);
len += status_string.length;
}
gss_release_buffer(&min_stat, &status_string);
@@ -74,7 +74,7 @@ static int check_gss_err(struct Curl_easy *data,
gss_release_buffer(&min_stat, &status_string);
}
if(sizeof(buf) > len + 3) {
- strcpy(buf+len, ".\n");
+ strcpy(buf + len, ".\n");
len += 2;
}
msg_ctx = 0;
@@ -86,7 +86,7 @@ static int check_gss_err(struct Curl_easy *data,
&msg_ctx, &status_string);
if(maj_stat == GSS_S_COMPLETE) {
if(sizeof(buf) > len + status_string.length)
- strcpy(buf+len, (char *) status_string.value);
+ strcpy(buf + len, (char *) status_string.value);
gss_release_buffer(&min_stat, &status_string);
break;
}
@@ -119,7 +119,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
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;
+ char *user = NULL;
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ?
data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
@@ -146,11 +146,12 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
else {
service.value = malloc(serviceptr_length +
- strlen(conn->socks_proxy.host.name)+2);
+ strlen(conn->socks_proxy.host.name) + 2);
if(!service.value)
return CURLE_OUT_OF_MEMORY;
- service.length = serviceptr_length + strlen(conn->socks_proxy.host.name)+1;
- snprintf(service.value, service.length+1, "%s@%s",
+ service.length = serviceptr_length +
+ strlen(conn->socks_proxy.host.name) + 1;
+ snprintf(service.value, service.length + 1, "%s@%s",
serviceptr, conn->socks_proxy.host.name);
gss_major_status = gss_import_name(&gss_minor_status, &service,
@@ -196,7 +197,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
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));
+ memcpy(socksreq + 2, &us_length, sizeof(short));
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
@@ -236,7 +237,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
* +----+------+-----+----------------+
*/
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive GSS-API authentication response.");
gss_release_name(&gss_status, &server);
@@ -261,11 +262,11 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- memcpy(&us_length, socksreq+2, sizeof(short));
+ 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);
+ 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 "
@@ -275,8 +276,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
}
- result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
- gss_recv_token.length, &actualread);
+ result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ gss_recv_token.length, &actualread);
if(result || (actualread != us_length)) {
failf(data, "Failed to receive GSS-API authentication token.");
@@ -312,7 +313,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
failf(data, "Failed to determine user name.");
return CURLE_COULDNT_CONNECT;
}
- user=malloc(gss_send_token.length+1);
+ 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);
@@ -326,7 +327,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_buffer(&gss_status, &gss_send_token);
infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user);
free(user);
- user=NULL;
+ user = NULL;
/* Do encryption */
socksreq[0] = 1; /* GSS-API subnegotiation version */
@@ -341,7 +342,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_enc = 1;
infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
- (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality"));
+ (gss_enc == 0)?"no":((gss_enc==1)?"integrity":"confidentiality"));
/* force for the moment to no data protection */
gss_enc = 0;
/*
@@ -376,7 +377,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
*/
if(data->set.socks5_gssapi_nec) {
us_length = htons((short)1);
- memcpy(socksreq+2, &us_length, sizeof(short));
+ memcpy(socksreq + 2, &us_length, sizeof(short));
}
else {
gss_send_token.length = 1;
@@ -401,7 +402,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_buffer(&gss_status, &gss_send_token);
us_length = htons((short)gss_w_token.length);
- memcpy(socksreq+2, &us_length, sizeof(short));
+ memcpy(socksreq + 2, &us_length, sizeof(short));
}
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
@@ -433,7 +434,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_buffer(&gss_status, &gss_w_token);
}
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive GSS-API encryption response.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -455,17 +456,17 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- memcpy(&us_length, socksreq+2, sizeof(short));
+ 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);
+ 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);
+ result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ gss_recv_token.length, &actualread);
if(result || (actualread != us_length)) {
failf(data, "Failed to receive GSS-API encryptrion type.");
@@ -513,8 +514,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
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"));
+ (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)
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index edc73ad2e..34699d374 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
@@ -108,7 +108,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
if(!service_name)
return CURLE_OUT_OF_MEMORY;
snprintf(service_name, service_length +
- strlen(conn->socks_proxy.host.name)+2, "%s/%s",
+ strlen(conn->socks_proxy.host.name) + 2, "%s/%s",
service, conn->socks_proxy.host.name);
}
@@ -199,7 +199,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
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));
+ memcpy(socksreq + 2, &us_length, sizeof(short));
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
@@ -283,7 +283,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- memcpy(&us_length, socksreq+2, sizeof(short));
+ memcpy(&us_length, socksreq + 2, sizeof(short));
us_length = ntohs(us_length);
sspi_recv_token.cbBuffer = us_length;
@@ -341,7 +341,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_enc = 1;
infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
- (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") );
+ (gss_enc == 0)?"no":((gss_enc == 1)?"integrity":"confidentiality") );
/* force to no data protection, avoid encryption/decryption for now */
gss_enc = 0;
/*
@@ -377,7 +377,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
if(data->set.socks5_gssapi_nec) {
us_length = htons((short)1);
- memcpy(socksreq+2, &us_length, sizeof(short));
+ memcpy(socksreq + 2, &us_length, sizeof(short));
}
else {
status = s_pSecFn->QueryContextAttributes(&sspi_context,
@@ -445,8 +445,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
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[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);
@@ -460,7 +460,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
sspi_w_token[2].cbBuffer = 0;
us_length = htons((short)sspi_send_token.cbBuffer);
- memcpy(socksreq+2, &us_length, sizeof(short));
+ memcpy(socksreq + 2, &us_length, sizeof(short));
}
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
@@ -517,7 +517,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- memcpy(&us_length, socksreq+2, sizeof(short));
+ memcpy(&us_length, socksreq + 2, sizeof(short));
us_length = ntohs(us_length);
sspi_w_token[0].cbBuffer = us_length;
@@ -588,8 +588,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
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"));
+ (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];
diff --git a/lib/splay.c b/lib/splay.c
index 68ff9c5db..69af446eb 100644
--- a/lib/splay.c
+++ b/lib/splay.c
@@ -110,7 +110,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
if(t != NULL) {
t = Curl_splay(i, t);
- if(compare(i, t->key)==0) {
+ if(compare(i, t->key) == 0) {
/* There already exists a node in the tree with the very same key. Build
a doubly-linked circular list of nodes. We add the new 'node' struct
to the end of this list. */
diff --git a/lib/splay.h b/lib/splay.h
index 0273bad38..4612ec271 100644
--- a/lib/splay.h
+++ b/lib/splay.h
@@ -54,8 +54,8 @@ 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 : \
+#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))))
diff --git a/lib/ssh.c b/lib/ssh.c
index 3831f71a7..ae717f9cc 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -428,14 +428,14 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn,
/* Check for /~/, indicating relative to the user's home directory */
if(conn->handler->protocol & CURLPROTO_SCP) {
- real_path = malloc(working_path_len+1);
+ 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);
+ memcpy(real_path, working_path + 3, 4 + working_path_len-3);
else
memcpy(real_path, working_path, 1 + working_path_len);
}
@@ -451,19 +451,19 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn,
leading '/' */
memcpy(real_path, homedir, homelen);
real_path[homelen] = '/';
- real_path[homelen+1] = '\0';
+ real_path[homelen + 1] = '\0';
if(working_path_len > 3) {
- memcpy(real_path+homelen+1, working_path + 3,
+ memcpy(real_path + homelen + 1, working_path + 3,
1 + working_path_len -3);
}
}
else {
- real_path = malloc(working_path_len+1);
+ 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);
+ memcpy(real_path, working_path, 1 + working_path_len);
}
}
@@ -1813,7 +1813,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
zero even though libssh2_sftp_open() failed previously! We need
to work around that! */
sshc->actualcode = CURLE_SSH;
- err=-1;
+ err = -1;
}
failf(data, "Upload failed: %s (%d/%d)",
err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
@@ -1831,7 +1831,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
if(seekerr != CURL_SEEKFUNC_OK) {
- curl_off_t passed=0;
+ curl_off_t passed = 0;
if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
failf(data, "Could not seek stream");
@@ -1983,13 +1983,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = result?result:CURLE_SSH;
break;
}
- sshc->readdir_filename = malloc(PATH_MAX+1);
+ sshc->readdir_filename = malloc(PATH_MAX + 1);
if(!sshc->readdir_filename) {
state(conn, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- sshc->readdir_longentry = malloc(PATH_MAX+1);
+ sshc->readdir_longentry = malloc(PATH_MAX + 1);
if(!sshc->readdir_longentry) {
Curl_safefree(sshc->readdir_filename);
state(conn, SSH_SFTP_CLOSE);
@@ -2023,7 +2023,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
result = Curl_client_write(conn, CLIENTWRITE_BODY,
- tmpLine, sshc->readdir_len+1);
+ tmpLine, sshc->readdir_len + 1);
free(tmpLine);
if(result) {
@@ -2032,7 +2032,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
/* since this counts what we send to the client, we include the
newline in this counter */
- data->req.bytecount += sshc->readdir_len+1;
+ data->req.bytecount += sshc->readdir_len + 1;
/* output debug output if that is requested */
if(data->set.verbose) {
@@ -2233,18 +2233,25 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
curl_off_t from, to;
char *ptr;
char *ptr2;
+ CURLofft to_t;
+ CURLofft from_t;
- from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
- while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+ from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+ if(from_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
ptr++;
- to=curlx_strtoofft(ptr, &ptr2, 0);
- if((ptr == ptr2) /* no "to" value given */
+ to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+ if(to_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
|| (to >= size)) {
to = size - 1;
}
- if(from < 0) {
+ if(from_t) {
/* from is relative to end of file */
- from += size;
+ from = size - to;
+ to = size - 1;
}
if(from > size) {
failf(data, "Offset (%"
@@ -2935,6 +2942,13 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
return CURLE_FAILED_INIT;
}
+ if(data->set.ssh_compression) {
+#if LIBSSH2_VERSION_NUM >= 0x010208
+ if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
+#endif
+ infof(data, "Failed to enable compression for ssh session\n");
+ }
+
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
int rc;
@@ -3031,8 +3045,8 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
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 */
+ sshc->secondCreateDirs = 0; /* reset the create dir attempt state
+ variable */
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
diff --git a/lib/strcase.c b/lib/strcase.c
index c4a06bedb..c6732ff78 100644
--- a/lib/strcase.c
+++ b/lib/strcase.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -94,10 +94,11 @@ char Curl_raw_toupper(char 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 https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
- * some further explanation to why this function is necessary.
+ * Curl_strcasecompare() 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
+ * https://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.
diff --git a/lib/strdup.c b/lib/strdup.c
index 8d6258e81..a671f5c55 100644
--- a/lib/strdup.c
+++ b/lib/strdup.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,11 +44,11 @@ char *curlx_strdup(const char *str)
if(len >= ((size_t)-1) / sizeof(char))
return (char *)NULL;
- newstr = malloc((len+1)*sizeof(char));
+ newstr = malloc((len + 1)*sizeof(char));
if(!newstr)
return (char *)NULL;
- memcpy(newstr, str, (len+1)*sizeof(char));
+ memcpy(newstr, str, (len + 1)*sizeof(char));
return newstr;
diff --git a/lib/strtoofft.c b/lib/strtoofft.c
index c2adc7280..807fc5454 100644
--- a/lib/strtoofft.c
+++ b/lib/strtoofft.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,6 +20,7 @@
*
***************************************************************************/
+#include <errno.h>
#include "curl_setup.h"
#include "strtoofft.h"
@@ -32,7 +33,29 @@
* https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
*/
-#ifdef NEED_CURL_STRTOLL
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
+# ifdef HAVE_STRTOLL
+# define strtooff strtoll
+# else
+# if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
+# if defined(_SAL_VERSION)
+ _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
+ _In_z_ const char *_String,
+ _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
+# else
+ _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
+ char **_EndPtr, int _Radix);
+# endif
+# define strtooff _strtoi64
+# else
+# define PRIVATE_STRTOOFF 1
+# endif
+# endif
+#else
+# define strtooff strtol
+#endif
+
+#ifdef PRIVATE_STRTOOFF
/* Range tests can be used for alphanum decoding if characters are consecutive,
like in ASCII. Else an array is scanned. Determine this condition now. */
@@ -48,11 +71,10 @@ static const char valchars[] =
static int get_char(char c, int base);
/**
- * Emulated version of the strtoll function. This extracts a long long
+ * Custom version of the strtooff function. This extracts a curl_off_t
* value from the given input string and returns it.
*/
-curl_off_t
-curlx_strtoll(const char *nptr, char **endptr, int base)
+static curl_off_t strtooff(const char *nptr, char **endptr, int base)
{
char *end;
int is_negative = 0;
@@ -186,3 +208,34 @@ static int get_char(char c, int base)
return value;
}
#endif /* Only present if we need strtoll, but don't have it. */
+
+/*
+ * Parse a *positive* up to 64 bit number written in ascii.
+ */
+CURLofft curlx_strtoofft(const char *str, char **endp, int base,
+ curl_off_t *num)
+{
+ char *end;
+ curl_off_t number;
+ errno = 0;
+ *num = 0; /* clear by default */
+ while(str && *str && ISSPACE(*str))
+ str++;
+ if('-' == *str) {
+ if(endp)
+ *endp = (char *)str; /* didn't actually move */
+ return CURL_OFFT_INVAL; /* nothing parsed */
+ }
+ number = strtooff(str, &end, base);
+ if(endp)
+ *endp = end;
+ if(errno == ERANGE)
+ /* overflow/underflow */
+ return CURL_OFFT_FLOW;
+ else if(str == end)
+ /* nothing parsed */
+ return CURL_OFFT_INVAL;
+
+ *num = number;
+ return CURL_OFFT_OK;
+}
diff --git a/lib/strtoofft.h b/lib/strtoofft.h
index f4039f3a3..244411a87 100644
--- a/lib/strtoofft.h
+++ b/lib/strtoofft.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,31 +40,7 @@
* 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)
-# if defined(_SAL_VERSION)
- _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
- _In_z_ const char *_String,
- _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
-# else
- _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
- char **_EndPtr, int _Radix);
-# endif
-# 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)
+#if (SIZEOF_CURL_OFF_T == 4)
# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
#else
/* assume CURL_SIZEOF_CURL_OFF_T == 8 */
@@ -72,4 +48,13 @@
#endif
#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
+typedef enum {
+ CURL_OFFT_OK, /* parsed fine */
+ CURL_OFFT_FLOW, /* over or underflow */
+ CURL_OFFT_INVAL /* nothing was parsed */
+} CURLofft;
+
+CURLofft curlx_strtoofft(const char *str, char **endp, int base,
+ curl_off_t *num);
+
#endif /* HEADER_CURL_STRTOOFFT_H */
diff --git a/lib/telnet.c b/lib/telnet.c
index 8ef121fec..37458fa42 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -76,7 +76,7 @@
} WHILE_FALSE
#define CURL_SB_ACCUM(x,c) \
do { \
- if(x->subpointer < (x->subbuffer+sizeof x->subbuffer)) \
+ if(x->subpointer < (x->subbuffer + sizeof x->subbuffer)) \
*x->subpointer++ = (c); \
} WHILE_FALSE
@@ -295,8 +295,8 @@ 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)
+ for(i = 0; i < CURL_NTELOPTS; i++) {
+ if(i == CURL_TELOPT_ECHO)
continue;
if(tn->us_preferred[i] == CURL_YES)
@@ -792,7 +792,7 @@ static void printsub(struct Curl_easy *data,
case CURL_TELOPT_NEW_ENVIRON:
if(pointer[1] == CURL_TELQUAL_IS) {
infof(data, " ");
- for(i = 3;i < length;i++) {
+ for(i = 3; i < length; i++) {
switch(pointer[i]) {
case CURL_NEW_ENV_VAR:
infof(data, ", ");
@@ -843,7 +843,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
}
- for(head = data->set.telnet_options; head; head=head->next) {
+ for(head = data->set.telnet_options; head; head = head->next) {
if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
option_keyword, option_arg) == 2) {
@@ -890,8 +890,8 @@ static CURLcode check_telnet_options(struct connectdata *conn)
/* To take care or not of the 8th bit in data exchange */
if(strcasecompare(option_keyword, "BINARY")) {
- binary_option=atoi(option_arg);
- if(binary_option!=1) {
+ 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;
}
@@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn)
struct Curl_easy *data = conn->data;
struct TELNET *tn = (struct TELNET *)data->req.protop;
- printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
+ 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;
@@ -967,7 +967,7 @@ static void suboption(struct connectdata *conn)
CURL_TELQUAL_IS);
len = 4;
- for(v = tn->telnet_vars;v;v = v->next) {
+ 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) {
@@ -1019,8 +1019,8 @@ static void sendsuboption(struct connectdata *conn, int option)
CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS);
/* We must deal either with litte or big endian processors */
/* Window size must be sent according to the 'network order' */
- x=htons(tn->subopt_wsx);
- y=htons(tn->subopt_wsy);
+ x = htons(tn->subopt_wsx);
+ y = htons(tn->subopt_wsy);
uc1 = (unsigned char *)&x;
uc2 = (unsigned char *)&y;
CURL_SB_ACCUM(tn, uc1[0]);
@@ -1033,7 +1033,7 @@ static void sendsuboption(struct connectdata *conn, int option)
CURL_SB_TERM(tn);
/* data suboption is now ready */
- printsub(data, '>', (unsigned char *)tn->subbuffer+2,
+ printsub(data, '>', (unsigned char *)tn->subbuffer + 2,
CURL_SB_LEN(tn)-2);
/* we send the header of the suboption... */
@@ -1044,9 +1044,9 @@ static void sendsuboption(struct connectdata *conn, int option)
}
/* ... then the window size with the send_telnet_data() function
to deal with 0xFF cases ... */
- send_telnet_data(conn, (char *)tn->subbuffer+3, 4);
+ send_telnet_data(conn, (char *)tn->subbuffer + 3, 4);
/* ... and the footer */
- bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer+7, 2);
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2);
if(bytes_written < 0) {
err = SOCKERRNO;
failf(data, "Sending data failed (%d)", err);
@@ -1064,7 +1064,7 @@ CURLcode telrcv(struct connectdata *conn,
unsigned char c;
CURLcode result;
int in = 0;
- int startwrite=-1;
+ int startwrite = -1;
struct Curl_easy *data = conn->data;
struct TELNET *tn = (struct TELNET *)data->req.protop;
diff --git a/lib/tftp.c b/lib/tftp.c
index 51642c9b9..caa767127 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -76,12 +76,12 @@
#define TFTP_OPTION_INTERVAL "timeout"
typedef enum {
- TFTP_MODE_NETASCII=0,
+ TFTP_MODE_NETASCII = 0,
TFTP_MODE_OCTET
} tftp_mode_t;
typedef enum {
- TFTP_STATE_START=0,
+ TFTP_STATE_START = 0,
TFTP_STATE_RX,
TFTP_STATE_TX,
TFTP_STATE_FIN
@@ -100,7 +100,7 @@ typedef enum {
} tftp_event_t;
typedef enum {
- TFTP_ERR_UNDEF=0,
+ TFTP_ERR_UNDEF = 0,
TFTP_ERR_NOTFOUND,
TFTP_ERR_PERM,
TFTP_ERR_DISKFULL,
@@ -217,7 +217,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
if(start) {
maxtime = (time_t)(timeout_ms + 500) / 1000;
- state->max_time = state->start_time+maxtime;
+ state->max_time = state->start_time + maxtime;
/* Set per-block timeout to total */
timeout = maxtime;
@@ -232,7 +232,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
/* 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;
+ state->retry_time = 1;
}
else {
@@ -241,7 +241,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
else
maxtime = 3600;
- state->max_time = state->start_time+maxtime;
+ state->max_time = state->start_time + maxtime;
/* Set per-block timeout to total */
timeout = maxtime;
@@ -251,15 +251,15 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
}
/* But bound the total number */
if(state->retry_max<3)
- state->retry_max=3;
+ state->retry_max = 3;
if(state->retry_max>50)
- 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;
+ state->retry_time = 1;
infof(state->conn->data,
"set timeouts for state %d; Total %ld, retry %d maxtry %d\n",
@@ -321,7 +321,7 @@ static const char *tftp_option_get(const char *buf, size_t len,
return NULL;
*option = buf;
- loc += Curl_strnlen(buf+loc, len-loc);
+ loc += Curl_strnlen(buf + loc, len-loc);
loc++; /* NULL term */
if(loc > len)
@@ -475,7 +475,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
/* If we are uploading, send an WRQ */
setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
state->conn->data->req.upload_fromhere =
- (char *)state->spacket.data+4;
+ (char *)state->spacket.data + 4;
if(data->state.infilesize != -1)
Curl_pgrsSetUploadSize(data, data->state.infilesize);
}
@@ -493,10 +493,11 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
if(strlen(filename) > (state->blksize - strlen(mode) - 4)) {
failf(data, "TFTP file name too long\n");
+ free(filename);
return CURLE_TFTP_ILLEGAL; /* too long file name field */
}
- snprintf((char *)state->spacket.data+2,
+ snprintf((char *)state->spacket.data + 2,
state->blksize,
"%s%c%s%c", filename, '\0', mode, '\0');
sbytes = 4 + strlen(filename) + strlen(mode);
@@ -511,25 +512,25 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
strcpy(buf, "0"); /* the destination is large enough */
sbytes += tftp_option_add(state, sbytes,
- (char *)state->spacket.data+sbytes,
+ (char *)state->spacket.data + sbytes,
TFTP_OPTION_TSIZE);
sbytes += tftp_option_add(state, sbytes,
- (char *)state->spacket.data+sbytes, buf);
+ (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,
+ (char *)state->spacket.data + sbytes,
TFTP_OPTION_BLKSIZE);
sbytes += tftp_option_add(state, sbytes,
- (char *)state->spacket.data+sbytes, buf);
+ (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,
+ (char *)state->spacket.data + sbytes,
TFTP_OPTION_INTERVAL);
sbytes += tftp_option_add(state, sbytes,
- (char *)state->spacket.data+sbytes, buf);
+ (char *)state->spacket.data + sbytes, buf);
}
/* the typecase for the 3rd argument is mostly for systems that do
@@ -575,7 +576,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit
boundary */
-#define NEXT_BLOCKNUM(x) (((x)+1)&0xffff)
+#define NEXT_BLOCKNUM(x) (((x) + 1)&0xffff)
/**********************************************************
*
@@ -626,7 +627,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
}
/* Check if completed (That is, a less than full packet is received) */
- if(state->rbytes < (ssize_t)state->blksize+4) {
+ if(state->rbytes < (ssize_t)state->blksize + 4) {
state->state = TFTP_STATE_FIN;
}
else {
@@ -742,7 +743,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
else {
/* Re-send the data packet */
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
- 4+state->sbytes, SEND_4TH_ARG,
+ 4 + state->sbytes, SEND_4TH_ARG,
(struct sockaddr *)&state->remote_addr,
state->remote_addrlen);
/* Check all sbytes were sent */
@@ -775,7 +776,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
* data block.
* */
state->sbytes = 0;
- state->conn->data->req.upload_fromhere = (char *)state->spacket.data+4;
+ state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4;
do {
result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
&cb);
@@ -812,7 +813,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
else {
/* Re-send the data packet */
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
- 4+state->sbytes, SEND_4TH_ARG,
+ 4 + state->sbytes, SEND_4TH_ARG,
(struct sockaddr *)&state->remote_addr,
state->remote_addrlen);
/* Check all sbytes were sent */
@@ -1108,11 +1109,11 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
fromlen = sizeof(fromaddr);
state->rbytes = (int)recvfrom(state->sockfd,
(void *)state->rpacket.data,
- state->blksize+4,
+ state->blksize + 4,
0,
(struct sockaddr *)&fromaddr,
&fromlen);
- if(state->remote_addrlen==0) {
+ if(state->remote_addrlen == 0) {
memcpy(&state->remote_addr, &fromaddr, fromlen);
state->remote_addrlen = fromlen;
}
@@ -1134,7 +1135,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
if(state->rbytes > 4 &&
(NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
result = Curl_client_write(conn, CLIENTWRITE_BODY,
- (char *)state->rpacket.data+4,
+ (char *)state->rpacket.data + 4,
state->rbytes-4);
if(result) {
tftp_state_machine(state, TFTP_EVENT_ERROR);
@@ -1148,14 +1149,14 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
{
unsigned short error = getrpacketblock(&state->rpacket);
state->error = (tftp_error_t)error;
- infof(data, "%s\n", (const char *)state->rpacket.data+4);
+ 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,
+ (const char *)state->rpacket.data + 2,
state->rbytes-2);
if(result)
return result;
@@ -1199,7 +1200,7 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
state->state = TFTP_STATE_FIN;
return 0;
}
- if(current > state->rx_time+state->retry_time) {
+ if(current > state->rx_time + state->retry_time) {
if(event)
*event = TFTP_EVENT_TIMEOUT;
time(&state->rx_time); /* update even though we received nothing */
diff --git a/lib/transfer.c b/lib/transfer.c
index f09985def..30e936407 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -73,12 +73,38 @@
#include "connect.h"
#include "non-ascii.h"
#include "http2.h"
+#include "mime.h"
+#include "strcase.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_IMAP)
+/*
+ * checkheaders() checks the linked list of custom 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 Curl_easy *data = conn->data;
+
+ for(head = data->set.headers; head; head = head->next) {
+ if(strncasecompare(head->data, thisheader, thislen))
+ return head->data;
+ }
+
+ return NULL;
+}
+#endif
+
/*
* This function will call the read callback to fill our buffer with data
* to upload.
@@ -195,27 +221,28 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
strlen(endofline_network));
#ifdef CURL_DOES_CONVERSIONS
- CURLcode result;
- int length;
- if(data->set.prefer_ascii) {
- /* translate the protocol and data */
- length = nread;
- }
- else {
- /* just translate the protocol portion */
- length = strlen(hexbuffer);
+ {
+ CURLcode result;
+ int length;
+ if(data->set.prefer_ascii)
+ /* translate the protocol and data */
+ length = nread;
+ else
+ /* just translate the protocol portion */
+ length = (int)strlen(hexbuffer);
+ result = Curl_convert_to_network(data, data->req.upload_fromhere,
+ length);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result)
+ return result;
}
- result = Curl_convert_to_network(data, data->req.upload_fromhere, length);
- /* Curl_convert_to_network calls failf if unsuccessful */
- if(result)
- return result;
#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 */
+ nread += (int)strlen(endofline_native); /* for the added end of line */
}
#ifdef CURL_DOES_CONVERSIONS
else if((data->set.prefer_ascii) && (!sending_http_headers)) {
@@ -241,6 +268,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
CURLcode Curl_readrewind(struct connectdata *conn)
{
struct Curl_easy *data = conn->data;
+ curl_mimepart *mimepart = &data->set.mimepost;
conn->bits.rewindaftersend = FALSE; /* we rewind now */
@@ -253,9 +281,21 @@ CURLcode Curl_readrewind(struct connectdata *conn)
/* 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))
+ if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
+ struct HTTP *http = data->req.protop;
+
+ if(http->sendit)
+ mimepart = http->sendit;
+ }
+ if(data->set.postfields)
; /* do nothing */
+ else if(data->set.httpreq == HTTPREQ_POST_MIME ||
+ data->set.httpreq == HTTPREQ_POST_FORM) {
+ if(Curl_mime_rewind(mimepart)) {
+ failf(data, "Cannot rewind mime/post data");
+ return CURLE_SEND_FAIL_REWIND;
+ }
+ }
else {
if(data->set.seek_func) {
int err;
@@ -560,7 +600,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
infof(data, "Ignoring the response-body\n");
}
if(data->state.resume_from && !k->content_range &&
- (data->set.httpreq==HTTPREQ_GET) &&
+ (data->set.httpreq == HTTPREQ_GET) &&
!k->ignorebody) {
if(k->size == data->state.resume_from) {
@@ -915,7 +955,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/* this is a paused transfer */
break;
}
- if(nread<=0) {
+ if(nread <= 0) {
result = done_sending(conn, k);
if(result)
return result;
@@ -1055,7 +1095,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
{
struct SingleRequest *k = &data->req;
CURLcode result;
- int didwhat=0;
+ int didwhat = 0;
curl_socket_t fd_read;
curl_socket_t fd_write;
@@ -1303,7 +1343,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
if(result)
return result;
- data->set.followlocation=0; /* reset the location-follow counter */
+ data->set.followlocation = 0; /* reset the location-follow counter */
data->state.this_is_a_follow = FALSE; /* reset this */
data->state.errorbuf = FALSE; /* no error has occurred */
data->state.httpversion = 0; /* don't assume any particular server version */
@@ -1345,7 +1385,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
#endif
Curl_initinfo(data); /* reset session-specific information "variables" */
- Curl_pgrsResetTimesSizes(data);
+ Curl_pgrsResetTransferSizes(data);
Curl_pgrsStartNow(data);
if(data->set.timeout)
@@ -1427,14 +1467,14 @@ static const char *find_host_sep(const char *url)
static size_t strlen_url(const char *url, bool relative)
{
const unsigned char *ptr;
- size_t newlen=0;
- bool left=TRUE; /* left side of the ? */
+ size_t newlen = 0;
+ bool left = TRUE; /* left side of the ? */
const unsigned char *host_sep = (const unsigned char *) url;
if(!relative)
host_sep = (const unsigned char *) find_host_sep(url);
- for(ptr=(unsigned char *)url; *ptr; ptr++) {
+ for(ptr = (unsigned char *)url; *ptr; ptr++) {
if(ptr < host_sep) {
++newlen;
@@ -1443,7 +1483,7 @@ static size_t strlen_url(const char *url, bool relative)
switch(*ptr) {
case '?':
- left=FALSE;
+ left = FALSE;
/* fall through */
default:
if(*ptr >= 0x80)
@@ -1452,7 +1492,7 @@ static size_t strlen_url(const char *url, bool relative)
break;
case ' ':
if(left)
- newlen+=3;
+ newlen += 3;
else
newlen++;
break;
@@ -1469,7 +1509,7 @@ static size_t strlen_url(const char *url, bool relative)
static void strcpy_url(char *output, const char *url, bool relative)
{
/* we must add this with whitespace-replacing */
- bool left=TRUE;
+ bool left = TRUE;
const unsigned char *iptr;
char *optr = output;
const unsigned char *host_sep = (const unsigned char *) url;
@@ -1488,7 +1528,7 @@ static void strcpy_url(char *output, const char *url, bool relative)
switch(*iptr) {
case '?':
- left=FALSE;
+ left = FALSE;
/* fall through */
default:
if(*iptr >= 0x80) {
@@ -1509,7 +1549,7 @@ static void strcpy_url(char *output, const char *url, bool relative)
break;
}
}
- *optr=0; /* zero terminate output buffer */
+ *optr = 0; /* zero terminate output buffer */
}
@@ -1548,26 +1588,26 @@ static char *concat_url(const char *base, const char *relurl)
/* 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);
+ 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, "//");
+ protsep = strstr(url_clone, "//");
if(!protsep)
- protsep=url_clone;
+ protsep = url_clone;
else
- protsep+=2; /* pass the slashes */
+ protsep += 2; /* pass the slashes */
if('/' != relurl[0]) {
- int level=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;
+ *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
@@ -1576,14 +1616,14 @@ static char *concat_url(const char *base, const char *relurl)
if(useurl[0] != '?') {
pathsep = strrchr(protsep, '/');
if(pathsep)
- *pathsep=0;
+ *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;
+ protsep = pathsep + 1;
else
protsep = NULL;
@@ -1591,13 +1631,13 @@ static char *concat_url(const char *base, const char *relurl)
and act accordingly */
if((useurl[0] == '.') && (useurl[1] == '/'))
- useurl+=2; /* just skip the "./" */
+ useurl += 2; /* just skip the "./" */
while((useurl[0] == '.') &&
(useurl[1] == '.') &&
(useurl[2] == '/')) {
level++;
- useurl+=3; /* pass the "../" */
+ useurl += 3; /* pass the "../" */
}
if(protsep) {
@@ -1605,9 +1645,9 @@ static char *concat_url(const char *base, const char *relurl)
/* cut off one more level from the right of the original URL */
pathsep = strrchr(protsep, '/');
if(pathsep)
- *pathsep=0;
+ *pathsep = 0;
else {
- *protsep=0;
+ *protsep = 0;
break;
}
}
@@ -1619,7 +1659,7 @@ static char *concat_url(const char *base, const char *relurl)
if((relurl[0] == '/') && (relurl[1] == '/')) {
/* the new URL starts with //, just keep the protocol part from the
original one */
- *protsep=0;
+ *protsep = 0;
useurl = &relurl[2]; /* we keep the slashes from the original, so we
skip the new ones */
host_changed = TRUE;
@@ -1635,7 +1675,7 @@ static char *concat_url(const char *base, const char *relurl)
char *sep = strchr(protsep, '?');
if(sep && (sep < pathsep))
pathsep = sep;
- *pathsep=0;
+ *pathsep = 0;
}
else {
/* There was no slash. Now, since we might be operating on a badly
@@ -1644,7 +1684,7 @@ static char *concat_url(const char *base, const char *relurl)
?-letter as well! */
pathsep = strchr(protsep, '?');
if(pathsep)
- *pathsep=0;
+ *pathsep = 0;
}
}
}
@@ -1735,7 +1775,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
}
}
- if(!is_absolute_url(newurl)) {
+ 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!
@@ -1754,7 +1794,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
/* This is an absolute URL, don't allow the custom port number */
disallowport = TRUE;
- newest = malloc(newlen+1); /* get memory for this */
+ newest = malloc(newlen + 1); /* get memory for this */
if(!newest)
return CURLE_OUT_OF_MEMORY;
@@ -1826,7 +1866,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
* can be overridden with CURLOPT_POSTREDIR.
*/
if((data->set.httpreq == HTTPREQ_POST
- || data->set.httpreq == HTTPREQ_POST_FORM)
+ || data->set.httpreq == HTTPREQ_POST_FORM
+ || data->set.httpreq == HTTPREQ_POST_MIME)
&& !(data->set.keep_post & CURL_REDIR_POST_301)) {
infof(data, "Switch from POST to GET\n");
data->set.httpreq = HTTPREQ_GET;
@@ -1850,7 +1891,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
* can be overridden with CURLOPT_POSTREDIR.
*/
if((data->set.httpreq == HTTPREQ_POST
- || data->set.httpreq == HTTPREQ_POST_FORM)
+ || data->set.httpreq == HTTPREQ_POST_FORM
+ || data->set.httpreq == HTTPREQ_POST_MIME)
&& !(data->set.keep_post & CURL_REDIR_POST_302)) {
infof(data, "Switch from POST to GET\n");
data->set.httpreq = HTTPREQ_GET;
@@ -1883,7 +1925,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
break;
}
Curl_pgrsTime(data, TIMER_REDIRECT);
- Curl_pgrsResetTimesSizes(data);
+ Curl_pgrsResetTransferSizes(data);
return CURLE_OK;
#endif /* CURL_DISABLE_HTTP */
diff --git a/lib/transfer.h b/lib/transfer.h
index 518967260..72526a834 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,6 +22,9 @@
*
***************************************************************************/
+char *Curl_checkheaders(const struct connectdata *conn,
+ const char *thisheader);
+
void Curl_init_CONNECT(struct Curl_easy *data);
CURLcode Curl_pretransfer(struct Curl_easy *data);
diff --git a/lib/url.c b/lib/url.c
index acaf913da..55884c982 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -71,6 +71,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "netrc.h"
#include "formdata.h"
+#include "mime.h"
#include "vtls/vtls.h"
#include "hostip.h"
#include "transfer.h"
@@ -284,7 +285,7 @@ void Curl_freeset(struct Curl_easy *data)
{
/* Free all dynamic strings stored in the data->set substructure. */
enum dupstring i;
- for(i=(enum dupstring)0; i < STRING_LAST; i++) {
+ for(i = (enum dupstring)0; i < STRING_LAST; i++) {
Curl_safefree(data->set.str[i]);
}
@@ -371,7 +372,7 @@ CURLcode Curl_dupset(struct Curl_easy *dst, struct Curl_easy *src)
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
/* duplicate all strings */
- for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
+ for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
result = setstropt(&dst->set.str[i], src->set.str[i]);
if(result)
return result;
@@ -479,6 +480,8 @@ CURLcode Curl_close(struct Curl_easy *data)
Curl_http2_cleanup_dependencies(data);
Curl_convert_close(data);
+ Curl_mime_cleanpart(&data->set.mimepost);
+
/* No longer a dirty share, if it exists */
if(data->share) {
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
@@ -668,6 +671,8 @@ CURLcode Curl_open(struct Curl_easy **curl)
result = CURLE_OUT_OF_MEMORY;
}
+ Curl_mime_initpart(&data->set.mimepost, data);
+
data->state.headerbuff = malloc(HEADERSIZE);
if(!data->state.headerbuff) {
DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
@@ -676,7 +681,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
else {
result = Curl_init_userdefined(&data->set);
- data->state.headersize=HEADERSIZE;
+ data->state.headersize = HEADERSIZE;
Curl_convert_init(data);
@@ -1147,6 +1152,20 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
data->set.httpreq = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
+#endif /* CURL_DISABLE_HTTP */
+
+ case CURLOPT_MIMEPOST:
+ /*
+ * Set to make us do MIME/form POST
+ */
+ result = curl_mime_subparts(&data->set.mimepost,
+ va_arg(param, curl_mime *));
+ if(!result) {
+ data->set.mimepost.freefunc = NULL; /* Avoid free upon easy cleanup. */
+ data->set.httpreq = HTTPREQ_POST_MIME;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ break;
case CURLOPT_REFERER:
/*
@@ -1176,6 +1195,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
data->set.headers = va_arg(param, struct curl_slist *);
break;
+#ifndef CURL_DISABLE_HTTP
case CURLOPT_PROXYHEADER:
/*
* Set a list with proxy headers to use (or replace internals with)
@@ -1327,7 +1347,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
}
break;
-#endif /* CURL_DISABLE_COOKIES */
+#endif /* !CURL_DISABLE_COOKIES */
case CURLOPT_HTTPGET:
/*
@@ -1353,6 +1373,16 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
data->set.httpversion = arg;
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_HTTPAUTH:
/*
* Set HTTP Authentication type BITMASK.
@@ -1404,16 +1434,6 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
}
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
@@ -1659,28 +1679,28 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* 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);
+ 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);
+ 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);
+ 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);
+ data->set.low_speed_time = va_arg(param, long);
break;
case CURLOPT_URL:
/*
@@ -1875,13 +1895,13 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_RESUME_FROM:
/*
- * Resume transfer at the give file position
+ * Resume transfer at the given file position
*/
data->set.set_resume_from = va_arg(param, long);
break;
case CURLOPT_RESUME_FROM_LARGE:
/*
- * Resume transfer at the give file position
+ * Resume transfer at the given file position
*/
data->set.set_resume_from = va_arg(param, curl_off_t);
break;
@@ -2179,24 +2199,26 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
TRUE : FALSE;
break;
case CURLOPT_SSL_CTX_FUNCTION:
-#ifdef have_curlssl_ssl_ctx
/*
* Set a SSL_CTX callback
*/
- data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
-#else
- result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+ if(Curl_ssl->have_ssl_ctx)
+ data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
+ else
#endif
+ result = CURLE_NOT_BUILT_IN;
break;
case CURLOPT_SSL_CTX_DATA:
-#ifdef have_curlssl_ssl_ctx
/*
* Set a SSL_CTX callback parameter pointer
*/
- data->set.ssl.fsslctxp = va_arg(param, void *);
-#else
- result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+ if(Curl_ssl->have_ssl_ctx)
+ data->set.ssl.fsslctxp = va_arg(param, void *);
+ else
#endif
+ result = CURLE_NOT_BUILT_IN;
break;
case CURLOPT_SSL_FALSESTART:
/*
@@ -2210,35 +2232,38 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_CERTINFO:
-#ifdef have_curlssl_certinfo
- data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
-#else
- result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+ if(Curl_ssl->have_certinfo)
+ data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ else
#endif
+ result = CURLE_NOT_BUILT_IN;
break;
case CURLOPT_PINNEDPUBLICKEY:
-#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
/*
* Set pinned public key for SSL connection.
* Specify file name of the public key in DER format.
*/
- result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
- va_arg(param, char *));
-#else
- result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+ if(Curl_ssl->have_pinnedpubkey)
+ result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+ va_arg(param, char *));
+ else
#endif
+ result = CURLE_NOT_BUILT_IN;
break;
case CURLOPT_PROXY_PINNEDPUBLICKEY:
-#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
/*
* Set pinned public key for SSL connection.
* Specify file name of the public key in DER format.
*/
- result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
- va_arg(param, char *));
-#else
- result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+ if(Curl_ssl->have_pinnedpubkey)
+ result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
+ va_arg(param, char *));
+ else
#endif
+ result = CURLE_NOT_BUILT_IN;
break;
case CURLOPT_CAINFO:
/*
@@ -2256,30 +2281,32 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
va_arg(param, char *));
break;
case CURLOPT_CAPATH:
-#ifdef have_curlssl_ca_path /* not supported by all backends */
/*
* 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_ORIG],
- va_arg(param, char *));
-#else
- result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+ if(Curl_ssl->have_ca_path)
+ /* This does not work on windows. */
+ result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+ va_arg(param, char *));
+ else
#endif
+ result = CURLE_NOT_BUILT_IN;
break;
case CURLOPT_PROXY_CAPATH:
-#ifdef have_curlssl_ca_path /* not supported by all backends */
/*
* Set CA path info for SSL connection proxy. 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_PROXY],
- va_arg(param, char *));
-#else
- result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+ if(Curl_ssl->have_ca_path)
+ /* This does not work on windows. */
+ result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
+ va_arg(param, char *));
+ else
#endif
+ result = CURLE_NOT_BUILT_IN;
break;
case CURLOPT_CRLFILE:
/*
@@ -2910,7 +2937,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
return CURLE_NOT_BUILT_IN;
#else
arg = va_arg(param, long);
- if((arg>=1) && (arg <= 256))
+ if((arg >= 1) && (arg <= 256))
data->set.stream_weight = (int)arg;
break;
#endif
@@ -2936,6 +2963,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
case CURLOPT_SUPPRESS_CONNECT_HEADERS:
data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
break;
+ case CURLOPT_SSH_COMPRESSION:
+ data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
+ break;
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
@@ -3273,7 +3303,7 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
struct curl_hash_iterator iter;
struct curl_llist_element *curr;
struct curl_hash_element *he;
- time_t highscore=-1;
+ time_t highscore =- 1;
time_t score;
struct curltime now;
struct connectdata *conn_candidate = NULL;
@@ -3336,7 +3366,7 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
struct connectbundle *bundle)
{
struct curl_llist_element *curr;
- time_t highscore=-1;
+ time_t highscore = -1;
time_t score;
struct curltime now;
struct connectdata *conn_candidate = NULL;
@@ -3967,7 +3997,7 @@ int Curl_doing_getsock(struct connectdata *conn,
CURLcode Curl_protocol_connecting(struct connectdata *conn,
bool *done)
{
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
if(conn && conn->handler->connecting) {
*done = FALSE;
@@ -3986,7 +4016,7 @@ CURLcode Curl_protocol_connecting(struct connectdata *conn,
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
{
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
if(conn && conn->handler->doing) {
*done = FALSE;
@@ -4006,7 +4036,7 @@ CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
CURLcode Curl_protocol_connect(struct connectdata *conn,
bool *protocol_done)
{
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
*protocol_done = FALSE;
@@ -4093,7 +4123,7 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
if(len && (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;
+ host->name[len-1] = 0;
/* Check name for non-ASCII and convert hostname to ACE form if we can */
if(!is_ASCII_name(host->name)) {
@@ -4146,7 +4176,7 @@ static void free_fixed_hostname(struct hostname *host)
host->encalloc = NULL;
}
#elif defined(USE_WIN32_IDN)
- free(host->encalloc); /* must be freed withidn_free() since this was
+ free(host->encalloc); /* must be freed with free() since this was
allocated by curl_win32_idn_to_ascii */
host->encalloc = NULL;
#else
@@ -4166,7 +4196,12 @@ static void llist_dtor(void *user, void *element)
*/
static struct connectdata *allocate_conn(struct Curl_easy *data)
{
- struct connectdata *conn = calloc(1, sizeof(struct connectdata));
+#ifdef USE_SSL
+#define SSL_EXTRA + 4 * Curl_ssl->sizeof_ssl_backend_data - sizeof(long long)
+#else
+#define SSL_EXTRA 0
+#endif
+ struct connectdata *conn = calloc(1, sizeof(struct connectdata) + SSL_EXTRA);
if(!conn)
return NULL;
@@ -4249,6 +4284,23 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->ip_version = data->set.ipver;
+#ifdef USE_SSL
+ /*
+ * To save on malloc()s, the SSL backend-specific data has been allocated
+ * at the end of the connectdata struct.
+ */
+ {
+ char *p = (char *)&conn->align_data__do_not_use;
+ conn->ssl[0].backend = (struct ssl_backend_data *)p;
+ conn->ssl[1].backend =
+ (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data);
+ conn->proxy_ssl[0].backend =
+ (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 2);
+ conn->proxy_ssl[1].backend =
+ (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 3);
+ }
+#endif
+
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
defined(NTLM_WB_ENABLED)
conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
@@ -4430,7 +4482,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
/* This cannot be done with strcpy() in a portable manner, since the
memory areas overlap! */
- memmove(path, path + 2, strlen(path + 2)+1);
+ memmove(path, path + 2, strlen(path + 2) + 1);
}
/*
@@ -4471,8 +4523,9 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
ptr++;
/* This cannot be made with strcpy, as the memory chunks overlap! */
- memmove(path, ptr, strlen(ptr)+1);
+ memmove(path, ptr, strlen(ptr) + 1);
}
+#endif
#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
if(STARTS_WITH_DRIVE_PREFIX(path)) {
@@ -4487,7 +4540,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
else {
/* clear path */
char slashbuf[4];
- path[0]=0;
+ path[0] = 0;
rc = sscanf(data->change.url,
"%15[^\n/:]:%3[/]%[^\n/?#]%[^\n]",
@@ -4572,7 +4625,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
*/
at = strchr(conn->host.name, '@');
if(at)
- query = strchr(at+1, '?');
+ query = strchr(at + 1, '?');
else
query = strchr(conn->host.name, '?');
@@ -4590,15 +4643,15 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
/* move the existing path plus the zero byte forward, to make room for
the host-name part */
- memmove(path+hostlen+1, path, pathlen+1);
+ memmove(path + hostlen + 1, path, pathlen + 1);
/* now copy the trailing host part in front of the existing path */
- memcpy(path+1, query, hostlen);
+ memcpy(path + 1, query, hostlen);
path[0]='/'; /* prepend the missing slash */
rebuild_url = TRUE;
- *query=0; /* now cut off the hostname at the ? */
+ *query = 0; /* now cut off the hostname at the ? */
}
else if(!path[0]) {
/* if there's no path set, use a single slash */
@@ -4614,7 +4667,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
/* 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);
+ memmove(&path[1], path, strlen(path) + 1);
path[0] = '/';
rebuild_url = TRUE;
}
@@ -4720,7 +4773,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
if(*endp == ']') {
/* The address scope was well formed. Knock it out of the
hostname. */
- memmove(percent, endp, strlen(endp)+1);
+ memmove(percent, endp, strlen(endp) + 1);
conn->scope_id = (unsigned int)scope;
}
else {
@@ -4990,7 +5043,7 @@ static char *detect_proxy(struct connectdata *conn)
strcpy(envp, "_proxy");
/* read the protocol proxy: */
- prox=curl_getenv(proxy_env);
+ prox = curl_getenv(proxy_env);
/*
* We don't try the uppercase version of HTTP_PROXY because of
@@ -5007,7 +5060,7 @@ static char *detect_proxy(struct connectdata *conn)
if(!prox && !strcasecompare("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);
+ prox = curl_getenv(proxy_env);
}
if(prox)
@@ -5015,7 +5068,7 @@ static char *detect_proxy(struct connectdata *conn)
else {
proxy = curl_getenv("all_proxy"); /* default proxy to use */
if(!proxy)
- proxy=curl_getenv("ALL_PROXY");
+ proxy = curl_getenv("ALL_PROXY");
}
return proxy;
@@ -5050,7 +5103,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
/* Parse the protocol part if present */
endofprot = strstr(proxy, "://");
if(endofprot) {
- proxyptr = endofprot+3;
+ proxyptr = endofprot + 3;
if(checkprefix("https", proxy))
proxytype = CURLPROXY_HTTPS;
else if(checkprefix("socks5h", proxy))
@@ -5072,13 +5125,14 @@ static CURLcode parse_proxy(struct Curl_easy *data,
else
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
-#ifndef HTTPS_PROXY_SUPPORT
- if(proxytype == CURLPROXY_HTTPS) {
- failf(data, "Unsupported proxy \'%s\'"
- ", libcurl is built without the HTTPS-proxy support.", proxy);
- return CURLE_NOT_BUILT_IN;
- }
+#ifdef USE_SSL
+ if(!Curl_ssl->support_https_proxy)
#endif
+ if(proxytype == CURLPROXY_HTTPS) {
+ failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
+ "HTTPS-proxy support.", proxy);
+ return CURLE_NOT_BUILT_IN;
+ }
sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
proxytype == CURLPROXY_SOCKS5 ||
@@ -5299,22 +5353,21 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
}
}
- no_proxy = curl_getenv("no_proxy");
- if(!no_proxy)
- no_proxy = curl_getenv("NO_PROXY");
+ if(!data->set.str[STRING_NOPROXY]) {
+ no_proxy = curl_getenv("no_proxy");
+ if(!no_proxy)
+ no_proxy = curl_getenv("NO_PROXY");
+ }
- if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY]) ||
- (!data->set.str[STRING_NOPROXY] &&
- check_noproxy(conn->host.name, no_proxy))) {
+ if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
+ data->set.str[STRING_NOPROXY] : no_proxy)) {
Curl_safefree(proxy);
Curl_safefree(socksproxy);
}
- else if(!proxy && !socksproxy)
#ifndef CURL_DISABLE_HTTP
+ else if(!proxy && !socksproxy)
/* if the host is not in the noproxy list, detect proxy. */
proxy = detect_proxy(conn);
-#else /* !CURL_DISABLE_HTTP */
- proxy = NULL;
#endif /* CURL_DISABLE_HTTP */
Curl_safefree(no_proxy);
@@ -5762,7 +5815,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
char *rest;
long port;
- port=strtol(portptr+1, &rest, 10); /* Port number must be decimal */
+ 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 */
@@ -6118,7 +6171,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
struct connectdata *conn,
bool *async)
{
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
/*************************************************************
@@ -6281,11 +6334,10 @@ static void reuse_conn(struct connectdata *old_conn,
free_fixed_hostname(&conn->conn_to_host);
Curl_safefree(conn->host.rawalloc);
Curl_safefree(conn->conn_to_host.rawalloc);
- conn->host=old_conn->host;
- conn->bits.conn_to_host = old_conn->bits.conn_to_host;
+ conn->host = old_conn->host;
conn->conn_to_host = old_conn->conn_to_host;
- conn->bits.conn_to_port = old_conn->bits.conn_to_port;
conn->conn_to_port = old_conn->conn_to_port;
+ conn->remote_port = old_conn->remote_port;
/* persist connection info in session handle */
Curl_persistconninfo(conn);
@@ -6384,9 +6436,9 @@ static CURLcode create_conn(struct Curl_easy *data,
* other parts of the code will rely on this fact
***********************************************************/
#define LEAST_PATH_ALLOC 256
- urllen=strlen(data->change.url);
+ urllen = strlen(data->change.url);
if(urllen < LEAST_PATH_ALLOC)
- urllen=LEAST_PATH_ALLOC;
+ urllen = LEAST_PATH_ALLOC;
/*
* We malloc() the buffers below urllen+2 to make room for 2 possibilities:
@@ -6397,14 +6449,14 @@ static CURLcode create_conn(struct Curl_easy *data,
Curl_safefree(data->state.pathbuffer);
data->state.path = NULL;
- data->state.pathbuffer = malloc(urllen+2);
+ 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);
+ conn->host.rawalloc = malloc(urllen + 2);
if(NULL == conn->host.rawalloc) {
Curl_safefree(data->state.pathbuffer);
data->state.path = NULL;
@@ -7037,7 +7089,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
k->buf = data->state.buffer;
k->hbufp = data->state.headerbuff;
- k->ignorebody=FALSE;
+ k->ignorebody = FALSE;
Curl_speedinit(data);
diff --git a/lib/urldata.h b/lib/urldata.h
index bde643b46..6dc715394 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -82,75 +82,6 @@
#include "cookie.h"
#include "formdata.h"
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
-#endif /* USE_OPENSSL */
-
-#ifdef USE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
-
-#ifdef USE_MBEDTLS
-
-#include <mbedtls/ssl.h>
-#include <mbedtls/version.h>
-#include <mbedtls/entropy.h>
-#include <mbedtls/ctr_drbg.h>
-
-#elif defined 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_GSKIT
-#include <gskssl.h>
-#endif
-
-#ifdef USE_AXTLS
-#include <axTLS/config.h>
-#include <axTLS/ssl.h>
-#undef malloc
-#undef calloc
-#undef realloc
-#endif /* USE_AXTLS */
-
-#if defined(USE_SCHANNEL) || defined(USE_WINDOWS_SSPI)
-#include "curl_sspi.h"
-#endif
-#ifdef USE_SCHANNEL
-#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
@@ -172,6 +103,7 @@
#include "hash.h"
#include "splay.h"
+#include "mime.h"
#include "imap.h"
#include "pop3.h"
#include "smtp.h"
@@ -240,20 +172,6 @@ enum protection_level {
};
#endif
-#ifdef USE_SCHANNEL
-/* Structs to store Schannel handles */
-struct curl_schannel_cred {
- CredHandle cred_handle;
- TimeStamp time_stamp;
- int refcount;
-};
-
-struct curl_schannel_ctxt {
- CtxtHandle ctxt_handle;
- TimeStamp time_stamp;
-};
-#endif
-
/* enum for the nonblocking SSL connection state machine */
typedef enum {
ssl_connect_1,
@@ -270,6 +188,9 @@ typedef enum {
ssl_connection_complete
} ssl_connection_state;
+/* SSL backend-specific data; declared differently by each SSL backend */
+struct ssl_backend_data;
+
/* struct for data related to each SSL connection */
struct ssl_connect_data {
/* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm
@@ -278,78 +199,9 @@ struct ssl_connect_data {
bool use;
ssl_connection_state state;
ssl_connect_state connecting_state;
-#if defined(USE_OPENSSL)
- /* these ones requires specific SSL-types */
- SSL_CTX* ctx;
- SSL* handle;
- X509* server_cert;
-#elif defined(USE_GNUTLS)
- gnutls_session_t session;
- gnutls_certificate_credentials_t cred;
-#ifdef USE_TLS_SRP
- gnutls_srp_client_credentials_t srp_client_cred;
-#endif
-#elif defined(USE_MBEDTLS)
- mbedtls_ctr_drbg_context ctr_drbg;
- mbedtls_entropy_context entropy;
- mbedtls_ssl_context ssl;
- int server_fd;
- mbedtls_x509_crt cacert;
- mbedtls_x509_crt clicert;
- mbedtls_x509_crl crl;
- mbedtls_pk_context pk;
- mbedtls_ssl_config config;
- const char *protocols[3];
-#elif defined(USE_POLARSSL)
- ctr_drbg_context ctr_drbg;
- entropy_context entropy;
- ssl_context ssl;
- int server_fd;
- x509_crt cacert;
- x509_crt clicert;
- x509_crl crl;
- rsa_context rsa;
-#elif defined(USE_CYASSL)
- SSL_CTX* ctx;
- SSL* handle;
-#elif defined(USE_NSS)
- PRFileDesc *handle;
- char *client_nickname;
- struct Curl_easy *data;
- struct curl_llist obj_list;
- PK11GenericObject *obj_clicert;
-#elif defined(USE_GSKIT)
- gsk_handle handle;
- int iocport;
- int localfd;
- int remotefd;
-#elif defined(USE_AXTLS)
- SSL_CTX* ssl_ctx;
- SSL* ssl;
-#elif defined(USE_SCHANNEL)
- struct curl_schannel_cred *cred;
- struct curl_schannel_ctxt *ctxt;
- SecPkgContext_StreamSizes stream_sizes;
- size_t encdata_length, decdata_length;
- size_t encdata_offset, decdata_offset;
- unsigned char *encdata_buffer, *decdata_buffer;
- /* encdata_is_incomplete: if encdata contains only a partial record that
- can't be decrypted without another Curl_read_plain (that is, status is
- SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
- more bytes into encdata then set this back to false. */
- bool encdata_is_incomplete;
- unsigned long req_flags, ret_flags;
- CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
- bool recv_sspi_close_notify; /* true if connection closed by close_notify */
- bool recv_connection_closed; /* true if connection closed, regardless how */
- bool use_alpn; /* true if ALPN is used for this connection */
-#elif defined(USE_DARWINSSL)
- SSLContextRef ssl_ctx;
- curl_socket_t ssl_sockfd;
- bool ssl_direction; /* true if writing, false if reading */
- size_t ssl_write_buffered_length;
-#elif defined(USE_SSL)
-#error "SSL backend specific information missing from ssl_connect_data"
+
+#if defined(USE_SSL)
+ struct ssl_backend_data *backend;
#endif
};
@@ -359,13 +211,13 @@ struct ssl_primary_config {
bool verifypeer; /* set TRUE if this is desired */
bool verifyhost; /* set TRUE if CN/SAN must match hostname */
bool verifystatus; /* set TRUE if certificate status must be checked */
+ bool sessionid; /* cache session IDs or not */
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
char *clientcert;
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 */
- bool sessionid; /* cache session IDs or not */
};
struct ssl_config_data {
@@ -411,6 +263,10 @@ struct curl_ssl_session {
struct ssl_primary_config ssl_config; /* setup for this session */
};
+#ifdef USE_WINDOWS_SSPI
+#include "curl_sspi.h"
+#endif
+
/* Struct used for Digest challenge-response authentication */
struct digestdata {
#if defined(USE_WINDOWS_SSPI)
@@ -442,10 +298,6 @@ typedef enum {
NTLMSTATE_LAST
} curlntlm;
-#ifdef USE_WINDOWS_SSPI
-#include "curl_sspi.h"
-#endif
-
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
#include <iconv.h>
#endif
@@ -1179,6 +1031,16 @@ struct connectdata {
char *unix_domain_socket;
bool abstract_unix_socket;
#endif
+
+#ifdef USE_SSL
+ /*
+ * To avoid multiple malloc() calls, the ssl_connect_data structures
+ * associated with a connectdata struct are allocated in the same block
+ * as the latter. This field forces alignment to an 8-byte boundary so
+ * that this all works.
+ */
+ long long *align_data__do_not_use;
+#endif
};
/* The end of connectdata. */
@@ -1259,6 +1121,8 @@ struct Progress {
struct curltime t_startop;
struct curltime t_acceptdata;
+ bool is_t_startransfer_set;
+
/* upload speed limit */
struct curltime ul_limit_start;
curl_off_t ul_limit_size;
@@ -1266,7 +1130,7 @@ struct Progress {
struct curltime dl_limit_start;
curl_off_t dl_limit_size;
-#define CURR_TIME (5+1) /* 6 entries for 5 seconds */
+#define CURR_TIME (5 + 1) /* 6 entries for 5 seconds */
curl_off_t speeder[ CURR_TIME ];
struct curltime speeder_time[ CURR_TIME ];
@@ -1278,6 +1142,7 @@ typedef enum {
HTTPREQ_GET,
HTTPREQ_POST,
HTTPREQ_POST_FORM, /* we make a difference internally */
+ HTTPREQ_POST_MIME, /* we make a difference internally */
HTTPREQ_PUT,
HTTPREQ_HEAD,
HTTPREQ_OPTIONS,
@@ -1387,7 +1252,7 @@ struct UrlState {
size_t headersize; /* size of the allocation */
char *buffer; /* download buffer */
- char uploadbuffer[UPLOAD_BUFSIZE+1]; /* upload buffer */
+ char uploadbuffer[UPLOAD_BUFSIZE + 1]; /* upload buffer */
curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */
@@ -1431,7 +1296,8 @@ struct UrlState {
ares_channel f.e. */
#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
- ENGINE *engine;
+ /* void instead of ENGINE to avoid bleeding OpenSSL into this header */
+ void *engine;
#endif /* USE_OPENSSL */
struct curltime expiretime; /* set this with Curl_expire() only */
struct Curl_tree timenode; /* for the splay stuff */
@@ -1694,7 +1560,8 @@ struct UserDefined {
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 */
+ struct curl_httppost *httppost; /* linked list of old POST data */
+ curl_mimepart mimepost; /* MIME/POST data. */
bool sep_headers; /* handle host and proxy headers separately */
bool cookiesession; /* new cookie session? */
bool crlf; /* convert crlf on ftp upload(?) */
@@ -1740,6 +1607,7 @@ struct UserDefined {
curl_sshkeycallback ssh_keyfunc; /* key matching callback */
void *ssh_keyfunc_userp; /* custom pointer to callback */
+ bool ssh_compression; /* enable SSH compression */
/* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially
diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c
index 3d583e417..b40239931 100644
--- a/lib/vauth/digest_sspi.c
+++ b/lib/vauth/digest_sspi.c
@@ -352,8 +352,8 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
if(!Curl_auth_digest_get_pair(p, value, content, &p))
break;
- if(Curl_strcasecompare(value, "stale")
- && Curl_strcasecompare(content, "true")) {
+ if(strcasecompare(value, "stale") &&
+ strcasecompare(content, "true")) {
stale = true;
break;
}
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index 42196455f..50d922208 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,7 +44,9 @@
#include "rand.h"
#include "vtls/vtls.h"
-#ifdef USE_NSS
+/* SSL backend-specific #if branches in this file must be kept in the order
+ documented in curl_ntlm_core. */
+#if defined(NTLM_NEEDS_NSS_INIT)
#include "vtls/nssg.h" /* for Curl_nss_force_init() */
#endif
@@ -272,7 +274,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
unsigned char *type2 = NULL;
size_t type2_len = 0;
-#if defined(USE_NSS)
+#if defined(NTLM_NEEDS_NSS_INIT)
/* Make sure the crypto backend is initialized */
result = Curl_nss_force_init(data);
if(result)
@@ -350,6 +352,7 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
*
* 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.
@@ -359,7 +362,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
+CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
+ const char *userp,
const char *passwdp,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
@@ -458,7 +462,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
});
/* Return with binary blob encoded into base64 */
- return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+ return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
}
/*
@@ -827,7 +831,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
return CURLE_CONV_FAILED;
/* Return with binary blob encoded into base64 */
- result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+ result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
Curl_auth_ntlm_cleanup(ntlm);
diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c
index 227d6de50..c955b69ea 100644
--- a/lib/vauth/ntlm_sspi.c
+++ b/lib/vauth/ntlm_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,6 +29,7 @@
#include "vauth/vauth.h"
#include "urldata.h"
#include "curl_base64.h"
+#include "curl_ntlm_core.h"
#include "warnless.h"
#include "curl_multibyte.h"
#include "sendf.h"
@@ -66,6 +67,7 @@ bool Curl_auth_is_ntlm_supported(void)
*
* 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.
@@ -75,7 +77,8 @@ bool Curl_auth_is_ntlm_supported(void)
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
+CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
+ const char *userp,
const char *passwdp,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
@@ -166,7 +169,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
return CURLE_RECV_ERROR;
/* Base64 encode the response */
- return Curl_base64_encode(NULL, (char *) ntlm->output_token,
+ return Curl_base64_encode(data, (char *) ntlm->output_token,
type_1_buf.cbBuffer, outptr, outlen);
}
diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h
index 24b7d24d8..15abea520 100644
--- a/lib/vauth/vauth.h
+++ b/lib/vauth/vauth.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2017, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -119,7 +119,8 @@ void Curl_auth_digest_cleanup(struct digestdata *digest);
bool Curl_auth_is_ntlm_supported(void);
/* This is used to generate a base64 encoded NTLM type-1 message */
-CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
+CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
+ const char *userp,
const char *passwdp,
struct ntlmdata *ntlm,
char **outptr,
diff --git a/lib/version.c b/lib/version.c
index 9207c3384..33e5fee3c 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -324,8 +324,8 @@ static curl_version_info_data version_info = {
#if defined(USE_LIBPSL)
| CURL_VERSION_PSL
#endif
-#if defined(HTTPS_PROXY_SUPPORT)
- | CURL_VERSION_HTTPS_PROXY
+#if defined(CURL_WITH_MULTI_SSL)
+ | CURL_VERSION_MULTI_SSL
#endif
,
NULL, /* ssl_version */
@@ -355,6 +355,10 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
#ifdef USE_SSL
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
+ if(Curl_ssl->support_https_proxy)
+ version_info.features |= CURL_VERSION_HTTPS_PROXY;
+ else
+ version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
#endif
#ifdef HAVE_LIBZ
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
index f0e376640..6b42708d8 100644
--- a/lib/vtls/axtls.c
+++ b/lib/vtls/axtls.c
@@ -47,21 +47,12 @@
#include "curl_memory.h"
#include "memdebug.h"
+struct ssl_backend_data {
+ SSL_CTX* ssl_ctx;
+ SSL* ssl;
+};
-/* 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;
-}
+#define BACKEND connssl->backend
static CURLcode map_error_to_curl(int axtls_err)
{
@@ -120,13 +111,13 @@ 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(BACKEND->ssl) {
+ ssl_free(BACKEND->ssl);
+ BACKEND->ssl = NULL;
}
- if(connssl->ssl_ctx) {
- ssl_ctx_free(connssl->ssl_ctx);
- connssl->ssl_ctx = NULL;
+ if(BACKEND->ssl_ctx) {
+ ssl_ctx_free(BACKEND->ssl_ctx);
+ BACKEND->ssl_ctx = NULL;
}
}
@@ -137,6 +128,7 @@ static void free_ssl_structs(struct ssl_connect_data *connssl)
*/
static CURLcode connect_prep(struct connectdata *conn, int sockindex)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
SSL_CTX *ssl_ctx;
SSL *ssl = NULL;
@@ -151,7 +143,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
SSL_SERVER_VERIFY_LATER |
SSL_CONNECT_IN_PARTS;
- if(conn->ssl[sockindex].state == ssl_connection_complete)
+ if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
same connection */
return CURLE_OK;
@@ -185,8 +177,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
}
- conn->ssl[sockindex].ssl_ctx = ssl_ctx;
- conn->ssl[sockindex].ssl = NULL;
+ BACKEND->ssl_ctx = ssl_ctx;
+ BACKEND->ssl = NULL;
/* Load the trusted CA cert bundle file */
if(SSL_CONN_CONFIG(CAfile)) {
@@ -212,7 +204,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
/* Load client certificate */
if(SSL_SET_OPTION(cert)) {
- i=0;
+ 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],
@@ -236,7 +228,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
If a pkcs12 file successfully loaded a cert, then there's nothing to do
because the key has already been loaded. */
if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
- i=0;
+ 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],
@@ -281,10 +273,26 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
if(!ssl)
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
- conn->ssl[sockindex].ssl = ssl;
+ BACKEND->ssl = ssl;
return CURLE_OK;
}
+static 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(BACKEND->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);
+}
+
/*
* For both blocking and non-blocking connects, this function finalizes the
* SSL connection.
@@ -292,7 +300,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
static CURLcode connect_finish(struct connectdata *conn, int sockindex)
{
struct Curl_easy *data = conn->data;
- SSL *ssl = conn->ssl[sockindex].ssl;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SSL *ssl = BACKEND->ssl;
const char *peer_CN;
uint32_t dns_altname_index;
const char *dns_altname;
@@ -387,7 +396,7 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
}
/* General housekeeping */
- conn->ssl[sockindex].state = ssl_connection_complete;
+ connssl->state = ssl_connection_complete;
conn->recv[sockindex] = axtls_recv;
conn->send[sockindex] = axtls_send;
@@ -409,11 +418,10 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
* 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)
+static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CURLcode conn_step;
int ssl_fcn_return;
int i;
@@ -421,23 +429,23 @@ CURLcode Curl_axtls_connect_nonblocking(
*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) {
+ if(connssl->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;
+ connssl->connecting_state = ssl_connect_2;
}
- if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
+ if(connssl->connecting_state == ssl_connect_2) {
/* Check to make sure handshake was ok. */
- if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
+ if(ssl_handshake_status(BACKEND->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);
+ for(i = 0; i<5; i++) {
+ ssl_fcn_return = ssl_read(BACKEND->ssl, NULL);
if(ssl_fcn_return < 0) {
Curl_axtls_close(conn, sockindex);
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
@@ -447,10 +455,10 @@ CURLcode Curl_axtls_connect_nonblocking(
}
}
infof(conn->data, "handshake completed successfully\n");
- conn->ssl[sockindex].connecting_state = ssl_connect_3;
+ connssl->connecting_state = ssl_connect_3;
}
- if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
+ if(connssl->connecting_state == ssl_connect_3) {
conn_step = connect_finish(conn, sockindex);
if(conn_step != CURLE_OK) {
Curl_axtls_close(conn, sockindex);
@@ -458,15 +466,15 @@ CURLcode Curl_axtls_connect_nonblocking(
}
/* Reset connect state */
- conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ connssl->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;
+ connssl->state = ssl_connection_none;
+ connssl->connecting_state = ssl_connect_1;
/* Return value perhaps not strictly correct, but distinguishes the issue.*/
return CURLE_BAD_FUNCTION_ARGUMENT;
}
@@ -476,15 +484,13 @@ CURLcode Curl_axtls_connect_nonblocking(
* 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)
-
+static CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex)
{
struct Curl_easy *data = conn->data;
CURLcode conn_step = connect_prep(conn, sockindex);
int ssl_fcn_return;
- SSL *ssl = conn->ssl[sockindex].ssl;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SSL *ssl = BACKEND->ssl;
long timeout_ms;
if(conn_step != CURLE_OK) {
@@ -530,8 +536,9 @@ static ssize_t axtls_send(struct connectdata *conn,
size_t len,
CURLcode *err)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* ssl_write() returns 'int' while write() and send() returns 'size_t' */
- int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
+ int rc = ssl_write(BACKEND->ssl, mem, (int)len);
infof(conn->data, " axtls_send\n");
@@ -544,27 +551,11 @@ static ssize_t axtls_send(struct connectdata *conn,
return rc;
}
-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)
+static 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.
@@ -584,17 +575,17 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
/* 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);
+ (void)SSL_shutdown(BACKEND->ssl);
*/
- if(connssl->ssl) {
+ if(BACKEND->ssl) {
int what = SOCKET_READABLE(conn->sock[sockindex], 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);
+ nread = (ssize_t)ssl_read(BACKEND->ssl, &buf);
if(nread < SSL_OK) {
failf(data, "close notify alert not received during shutdown");
@@ -630,7 +621,7 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
*err = CURLE_OK;
if(connssl) {
- ret = ssl_read(connssl->ssl, &read_buf);
+ ret = ssl_read(BACKEND->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. */
@@ -663,9 +654,10 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-int Curl_axtls_check_cxn(struct connectdata *conn)
+static int Curl_axtls_check_cxn(struct connectdata *conn)
{
- /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
+ /* openssl.c line:
+ rc = SSL_peek(conn->ssl[FIRSTSOCKET].backend->ssl, (void*)&buf, 1);
axTLS compat layer always returns the last argument, so connection is
always alive? */
@@ -673,7 +665,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn)
return 1; /* connection still in place */
}
-void Curl_axtls_session_free(void *ptr)
+static void Curl_axtls_session_free(void *ptr)
{
(void)ptr;
/* free the ID */
@@ -681,14 +673,13 @@ void Curl_axtls_session_free(void *ptr)
compatibility layer does nothing, so we do nothing too. */
}
-size_t Curl_axtls_version(char *buffer, size_t size)
+static size_t Curl_axtls_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "axTLS/%s", ssl_version());
}
-CURLcode Curl_axtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode Curl_axtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
static bool ssl_seeded = FALSE;
(void)data;
@@ -703,4 +694,49 @@ CURLcode Curl_axtls_random(struct Curl_easy *data,
return CURLE_OK;
}
+static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->ssl;
+}
+
+const struct Curl_ssl Curl_ssl_axtls = {
+ { CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
+
+ 0, /* have_ca_path */
+ 0, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ /*
+ * axTLS has no global init. Everything is done through SSL and SSL_CTX
+ * structs stored in connectdata structure.
+ */
+ Curl_none_init, /* init */
+ /* axTLS has no global cleanup. */
+ Curl_none_cleanup, /* cleanup */
+ Curl_axtls_version, /* version */
+ Curl_axtls_check_cxn, /* check_cxn */
+ Curl_axtls_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_axtls_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_axtls_connect, /* connect */
+ Curl_axtls_connect_nonblocking, /* connect_nonblocking */
+ Curl_axtls_get_internals, /* get_internals */
+ Curl_axtls_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_axtls_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ NULL /* sha256sum */
+};
+
#endif /* USE_AXTLS */
diff --git a/lib/vtls/axtls.h b/lib/vtls/axtls.h
index 4e5994666..5f518e4b7 100644
--- a/lib/vtls/axtls.h
+++ b/lib/vtls/axtls.h
@@ -27,44 +27,7 @@
#include "gnurl/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);
-
- /* 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);
-CURLcode Curl_axtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
-
-/* Set the API backend definition to axTLS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS
-
-/* 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(x) ((void)x)
-#define curlssl_close Curl_axtls_close
-#define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)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) ((void)x, (void)y, 0)
-#define curlssl_random(x,y,z) Curl_axtls_random(x,y,z)
+extern const struct Curl_ssl Curl_ssl_axtls;
#endif /* USE_AXTLS */
#endif /* HEADER_CURL_AXTLS_H */
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index 01bfdabd1..ba5ee1548 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -91,6 +91,7 @@ and that's a problem since options.h hasn't been included yet. */
#include "x509asn1.h"
#include "curl_printf.h"
+#include <cyassl/openssl/ssl.h>
#include <cyassl/ssl.h>
#ifdef HAVE_CYASSL_ERROR_SSL_H
#include <cyassl/error-ssl.h>
@@ -110,6 +111,25 @@ and that's a problem since options.h hasn't been included yet. */
#define CYASSL_MAX_ERROR_SZ 80
#endif
+/* KEEP_PEER_CERT is a product of the presence of build time symbol
+ OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
+ in wolfSSL's settings.h, and the latter two are build time symbols in
+ options.h. */
+#ifndef KEEP_PEER_CERT
+#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \
+ defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
+ (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
+#define KEEP_PEER_CERT
+#endif
+#endif
+
+struct ssl_backend_data {
+ SSL_CTX* ctx;
+ SSL* handle;
+};
+
+#define BACKEND connssl->backend
+
static Curl_recv cyassl_recv;
static Curl_send cyassl_send;
@@ -136,7 +156,7 @@ cyassl_connect_step1(struct connectdata *conn,
char error_buffer[CYASSL_MAX_ERROR_SZ];
char *ciphers;
struct Curl_easy *data = conn->data;
- struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
SSL_METHOD* req_method = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
#ifdef HAVE_SNI
@@ -146,7 +166,7 @@ cyassl_connect_step1(struct connectdata *conn,
#define use_sni(x) Curl_nop_stmt
#endif
- if(conssl->state == ssl_connection_complete)
+ if(connssl->state == ssl_connection_complete)
return CURLE_OK;
if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
@@ -205,11 +225,11 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
- if(conssl->ctx)
- SSL_CTX_free(conssl->ctx);
- conssl->ctx = SSL_CTX_new(req_method);
+ if(BACKEND->ctx)
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = SSL_CTX_new(req_method);
- if(!conssl->ctx) {
+ if(!BACKEND->ctx) {
failf(data, "SSL: couldn't create a context!");
return CURLE_OUT_OF_MEMORY;
}
@@ -225,9 +245,9 @@ cyassl_connect_step1(struct connectdata *conn,
version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion
because only the former will work before the user's CTX callback is called.
*/
- if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) &&
- (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) &&
- (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) {
+ if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) &&
+ (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) &&
+ (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)) {
failf(data, "SSL: couldn't set the minimum protocol version");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -237,7 +257,7 @@ cyassl_connect_step1(struct connectdata *conn,
ciphers = SSL_CONN_CONFIG(cipher_list);
if(ciphers) {
- if(!SSL_CTX_set_cipher_list(conssl->ctx, ciphers)) {
+ if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
failf(data, "failed setting cipher list: %s", ciphers);
return CURLE_SSL_CIPHER;
}
@@ -247,7 +267,7 @@ cyassl_connect_step1(struct connectdata *conn,
#ifndef NO_FILESYSTEM
/* load trusted cacert */
if(SSL_CONN_CONFIG(CAfile)) {
- if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
+ if(1 != SSL_CTX_load_verify_locations(BACKEND->ctx,
SSL_CONN_CONFIG(CAfile),
SSL_CONN_CONFIG(CApath))) {
if(SSL_CONN_CONFIG(verifypeer)) {
@@ -284,7 +304,7 @@ cyassl_connect_step1(struct connectdata *conn,
if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
int file_type = do_file_type(SSL_SET_OPTION(cert_type));
- if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert),
+ if(SSL_CTX_use_certificate_file(BACKEND->ctx, SSL_SET_OPTION(cert),
file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
@@ -292,7 +312,7 @@ cyassl_connect_step1(struct connectdata *conn,
}
file_type = do_file_type(SSL_SET_OPTION(key_type));
- if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
+ if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key),
file_type) != 1) {
failf(data, "unable to set private key");
return CURLE_SSL_CONNECT_ERROR;
@@ -304,7 +324,7 @@ cyassl_connect_step1(struct connectdata *conn,
* 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,
+ SSL_CTX_set_verify(BACKEND->ctx,
SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
SSL_VERIFY_NONE,
NULL);
@@ -323,7 +343,7 @@ cyassl_connect_step1(struct connectdata *conn,
#ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
#endif
- (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname,
+ (CyaSSL_CTX_UseSNI(BACKEND->ctx, CYASSL_SNI_HOST_NAME, hostname,
(unsigned short)hostname_len) != 1)) {
infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n");
@@ -336,15 +356,15 @@ cyassl_connect_step1(struct connectdata *conn,
https://github.com/wolfSSL/wolfssl/issues/366
The supported curves below are those also supported by OpenSSL 1.0.2 and
in the same order. */
- CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x17); /* secp256r1 */
- CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x19); /* secp521r1 */
- CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x18); /* secp384r1 */
+ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x17); /* secp256r1 */
+ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x19); /* secp521r1 */
+ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x18); /* secp384r1 */
#endif
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
CURLcode result = CURLE_OK;
- result = (*data->set.ssl.fsslctx)(data, conssl->ctx,
+ result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
data->set.ssl.fsslctxp);
if(result) {
failf(data, "error signaled by ssl ctx callback");
@@ -362,10 +382,10 @@ cyassl_connect_step1(struct connectdata *conn,
#endif
/* Let's make an SSL structure */
- if(conssl->handle)
- SSL_free(conssl->handle);
- conssl->handle = SSL_new(conssl->ctx);
- if(!conssl->handle) {
+ if(BACKEND->handle)
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = SSL_new(BACKEND->ctx);
+ if(!BACKEND->handle) {
failf(data, "SSL: couldn't create a context (handle)!");
return CURLE_OUT_OF_MEMORY;
}
@@ -388,7 +408,7 @@ cyassl_connect_step1(struct connectdata *conn,
strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
- if(wolfSSL_UseALPN(conssl->handle, protocols,
+ if(wolfSSL_UseALPN(BACKEND->handle, protocols,
(unsigned)strlen(protocols),
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
failf(data, "SSL: failed setting ALPN protocols");
@@ -404,10 +424,10 @@ cyassl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
- if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
+ if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSL_set_session failed: %s",
- ERR_error_string(SSL_get_error(conssl->handle, 0),
+ ERR_error_string(SSL_get_error(BACKEND->handle, 0),
error_buffer));
return CURLE_SSL_CONNECT_ERROR;
}
@@ -418,12 +438,12 @@ cyassl_connect_step1(struct connectdata *conn,
}
/* pass the raw socket into the SSL layer */
- if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
+ if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) {
failf(data, "SSL: SSL_set_fd failed");
return CURLE_SSL_CONNECT_ERROR;
}
- conssl->connecting_state = ssl_connect_2;
+ connssl->connecting_state = ssl_connect_2;
return CURLE_OK;
}
@@ -434,7 +454,7 @@ cyassl_connect_step2(struct connectdata *conn,
{
int ret = -1;
struct Curl_easy *data = conn->data;
- struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const char * const dispname = SSL_IS_PROXY() ?
@@ -448,22 +468,22 @@ cyassl_connect_step2(struct connectdata *conn,
/* Enable RFC2818 checks */
if(SSL_CONN_CONFIG(verifyhost)) {
- ret = CyaSSL_check_domain_name(conssl->handle, hostname);
+ ret = CyaSSL_check_domain_name(BACKEND->handle, hostname);
if(ret == SSL_FAILURE)
return CURLE_OUT_OF_MEMORY;
}
- ret = SSL_connect(conssl->handle);
+ ret = SSL_connect(BACKEND->handle);
if(ret != 1) {
char error_buffer[CYASSL_MAX_ERROR_SZ];
- int detail = SSL_get_error(conssl->handle, ret);
+ int detail = SSL_get_error(BACKEND->handle, ret);
if(SSL_ERROR_WANT_READ == detail) {
- conssl->connecting_state = ssl_connect_2_reading;
+ connssl->connecting_state = ssl_connect_2_reading;
return CURLE_OK;
}
else if(SSL_ERROR_WANT_WRITE == detail) {
- conssl->connecting_state = ssl_connect_2_writing;
+ connssl->connecting_state = ssl_connect_2_writing;
return CURLE_OK;
}
/* There is no easy way to override only the CN matching.
@@ -524,7 +544,7 @@ cyassl_connect_step2(struct connectdata *conn,
curl_asn1Element *pubkey;
CURLcode result;
- x509 = SSL_get_peer_certificate(conssl->handle);
+ x509 = SSL_get_peer_certificate(BACKEND->handle);
if(!x509) {
failf(data, "SSL: failed retrieving server certificate");
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
@@ -566,7 +586,7 @@ cyassl_connect_step2(struct connectdata *conn,
char *protocol = NULL;
unsigned short protocol_len = 0;
- rc = wolfSSL_ALPN_GetProtocol(conssl->handle, &protocol, &protocol_len);
+ rc = wolfSSL_ALPN_GetProtocol(BACKEND->handle, &protocol, &protocol_len);
if(rc == SSL_SUCCESS) {
infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
@@ -595,11 +615,11 @@ cyassl_connect_step2(struct connectdata *conn,
}
#endif /* HAVE_ALPN */
- conssl->connecting_state = ssl_connect_3;
+ connssl->connecting_state = ssl_connect_3;
#if (LIBCYASSL_VERSION_HEX >= 0x03009010)
infof(data, "SSL connection using %s / %s\n",
- wolfSSL_get_version(conssl->handle),
- wolfSSL_get_cipher_name(conssl->handle));
+ wolfSSL_get_version(BACKEND->handle),
+ wolfSSL_get_cipher_name(BACKEND->handle));
#else
infof(data, "SSL connected\n");
#endif
@@ -623,7 +643,7 @@ cyassl_connect_step3(struct connectdata *conn,
SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
- our_ssl_sessionid = SSL_get_session(connssl->handle);
+ our_ssl_sessionid = SSL_get_session(BACKEND->handle);
Curl_ssl_sessionid_lock(conn);
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
@@ -660,12 +680,13 @@ static ssize_t cyassl_send(struct connectdata *conn,
size_t len,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
char error_buffer[CYASSL_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
- int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+ int rc = SSL_write(BACKEND->handle, mem, memlen);
if(rc < 0) {
- int err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+ int err = SSL_get_error(BACKEND->handle, rc);
switch(err) {
case SSL_ERROR_WANT_READ:
@@ -684,18 +705,18 @@ static ssize_t cyassl_send(struct connectdata *conn,
return rc;
}
-void Curl_cyassl_close(struct connectdata *conn, int sockindex)
+static void Curl_cyassl_close(struct connectdata *conn, int sockindex)
{
- struct ssl_connect_data *conssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- if(conssl->handle) {
- (void)SSL_shutdown(conssl->handle);
- SSL_free(conssl->handle);
- conssl->handle = NULL;
+ if(BACKEND->handle) {
+ (void)SSL_shutdown(BACKEND->handle);
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
}
- if(conssl->ctx) {
- SSL_CTX_free(conssl->ctx);
- conssl->ctx = NULL;
+ if(BACKEND->ctx) {
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = NULL;
}
}
@@ -705,12 +726,13 @@ static ssize_t cyassl_recv(struct connectdata *conn,
size_t buffersize,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
char error_buffer[CYASSL_MAX_ERROR_SZ];
int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
- int nread = SSL_read(conn->ssl[num].handle, buf, buffsize);
+ int nread = SSL_read(BACKEND->handle, buf, buffsize);
if(nread < 0) {
- int err = SSL_get_error(conn->ssl[num].handle, nread);
+ int err = SSL_get_error(BACKEND->handle, nread);
switch(err) {
case SSL_ERROR_ZERO_RETURN: /* no more data */
@@ -732,14 +754,14 @@ static ssize_t cyassl_recv(struct connectdata *conn,
}
-void Curl_cyassl_session_free(void *ptr)
+static 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)
+static size_t Curl_cyassl_version(char *buffer, size_t size)
{
#if LIBCYASSL_VERSION_HEX >= 0x03006000
return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
@@ -753,16 +775,18 @@ size_t Curl_cyassl_version(char *buffer, size_t size)
}
-int Curl_cyassl_init(void)
+static int Curl_cyassl_init(void)
{
return (CyaSSL_Init() == SSL_SUCCESS);
}
-bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
+static 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;
+ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
+ if(BACKEND->handle) /* SSL is in use */
+ return (0 != SSL_pending(BACKEND->handle)) ? TRUE : FALSE;
else
return FALSE;
}
@@ -772,14 +796,14 @@ bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
* 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)
+static 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;
+ if(BACKEND->handle) {
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
}
return retval;
}
@@ -804,7 +828,7 @@ cyassl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
@@ -836,9 +860,9 @@ cyassl_connect_common(struct connectdata *conn,
if(connssl->connecting_state == ssl_connect_2_reading
|| connssl->connecting_state == ssl_connect_2_writing) {
- curl_socket_t writefd = 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==
+ curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -899,18 +923,14 @@ cyassl_connect_common(struct connectdata *conn,
}
-CURLcode
-Curl_cyassl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static 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)
+static CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -924,9 +944,8 @@ Curl_cyassl_connect(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode Curl_cyassl_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode Curl_cyassl_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
RNG rng;
(void)data;
@@ -939,10 +958,10 @@ CURLcode Curl_cyassl_random(struct Curl_easy *data,
return CURLE_OK;
}
-void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
+static void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
{
Sha256 SHA256pw;
(void)unused;
@@ -951,4 +970,48 @@ void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
Sha256Final(&SHA256pw, sha256sum);
}
+static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_cyassl = {
+ { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
+
+ 0, /* have_ca_path */
+ 0, /* have_certinfo */
+#ifdef KEEP_PEER_CERT
+ 1, /* have_pinnedpubkey */
+#else
+ 0, /* have_pinnedpubkey */
+#endif
+ 1, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_cyassl_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ Curl_cyassl_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_cyassl_shutdown, /* shutdown */
+ Curl_cyassl_data_pending, /* data_pending */
+ Curl_cyassl_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_cyassl_connect, /* connect */
+ Curl_cyassl_connect_nonblocking, /* connect_nonblocking */
+ Curl_cyassl_get_internals, /* get_internals */
+ Curl_cyassl_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_cyassl_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ Curl_cyassl_sha256sum /* sha256sum */
+};
+
#endif
diff --git a/lib/vtls/cyassl.h b/lib/vtls/cyassl.h
index f47719e4e..01e11cc23 100644
--- a/lib/vtls/cyassl.h
+++ b/lib/vtls/cyassl.h
@@ -25,68 +25,7 @@
#ifdef USE_CYASSL
-/* KEEP_PEER_CERT is a product of the presence of build time symbol
- OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
- in wolfSSL's settings.h, and the latter two are build time symbols in
- options.h. */
-#ifndef KEEP_PEER_CERT
-#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \
- defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
- (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
-#define KEEP_PEER_CERT
-#endif
-#endif
-
-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);
-
- /* 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);
-CURLcode Curl_cyassl_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
-void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t unused);
-
-/* Set the API backend definition to CyaSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-#ifdef KEEP_PEER_CERT
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-#endif
-
-/* 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(x) ((void)x)
-#define curlssl_close Curl_cyassl_close
-#define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_cyassl_version
-#define curlssl_check_cxn(x) ((void)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 curlssl_sha256sum(a,b,c,d) Curl_cyassl_sha256sum(a,b,c,d)
+extern const struct Curl_ssl Curl_ssl_cyassl;
#endif /* USE_CYASSL */
#endif /* HEADER_CURL_CYASSL_H */
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index 6f9c6012e..a98f43307 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -44,6 +44,8 @@
#endif
#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>
#include <CoreFoundation/CoreFoundation.h>
#include <CommonCrypto/CommonDigest.h>
@@ -118,6 +120,33 @@
#define ioErr -36
#define paramErr -50
+struct ssl_backend_data {
+ SSLContextRef ssl_ctx;
+ curl_socket_t ssl_sockfd;
+ bool ssl_direction; /* true if writing, false if reading */
+ size_t ssl_write_buffered_length;
+};
+
+#define BACKEND connssl->backend
+
+/* pinned public key support tests */
+
+/* version 1 supports macOS 10.12+ and iOS 10+ */
+#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
+ (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
+#define DARWIN_SSL_PINNEDPUBKEY_V1 1
+#endif
+
+/* version 2 supports MacOSX 10.7+ */
+#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
+#define DARWIN_SSL_PINNEDPUBKEY_V2 1
+#endif
+
+#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
+/* this backend supports CURLOPT_PINNEDPUBLICKEY */
+#define DARWIN_SSL_PINNEDPUBKEY 1
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
#ifdef DARWIN_SSL_PINNEDPUBKEY
/* both new and old APIs return rsa keys missing the spki header (not DER) */
static const unsigned char rsa4096SpkiHeader[] = {
@@ -161,7 +190,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
UInt8 *currData = (UInt8 *)data;
/*int sock = *(int *)connection;*/
struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
- int sock = connssl->ssl_sockfd;
+ int sock = BACKEND->ssl_sockfd;
OSStatus rtn = noErr;
size_t bytesRead;
ssize_t rrtn;
@@ -190,7 +219,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
break;
case EAGAIN:
rtn = errSSLWouldBlock;
- connssl->ssl_direction = false;
+ BACKEND->ssl_direction = false;
break;
default:
rtn = ioErr;
@@ -221,7 +250,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
size_t bytesSent = 0;
/*int sock = *(int *)connection;*/
struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
- int sock = connssl->ssl_sockfd;
+ int sock = BACKEND->ssl_sockfd;
ssize_t length;
size_t dataLen = *dataLength;
const UInt8 *dataPtr = (UInt8 *)data;
@@ -241,7 +270,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
theErr = errno;
if(theErr == EAGAIN) {
ortn = errSSLWouldBlock;
- connssl->ssl_direction = true;
+ BACKEND->ssl_direction = true;
}
else {
ortn = ioErr;
@@ -849,7 +878,7 @@ CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
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)
+CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
{
CFStringRef server_cert_summary = CFSTR("(null)");
@@ -876,6 +905,54 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
return server_cert_summary;
}
+static CURLcode CopyCertSubject(struct Curl_easy *data,
+ SecCertificateRef cert, char **certp)
+{
+ CFStringRef c = getsubject(cert);
+ CURLcode result = CURLE_OK;
+ const char *direct;
+ char *cbuf = NULL;
+ *certp = NULL;
+
+ if(!c) {
+ failf(data, "SSL: invalid CA certificate subject");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* If the subject is already available as UTF-8 encoded (ie 'direct') then
+ use that, else convert it. */
+ direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
+ if(direct) {
+ *certp = strdup(direct);
+ if(!*certp) {
+ failf(data, "SSL: out of memory");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
+ cbuf = calloc(cbuf_size, 1);
+ if(cbuf) {
+ if(!CFStringGetCString(c, cbuf, cbuf_size,
+ kCFStringEncodingUTF8)) {
+ failf(data, "SSL: invalid CA certificate subject");
+ result = CURLE_SSL_CACERT;
+ }
+ else
+ /* pass back the buffer */
+ *certp = cbuf;
+ }
+ else {
+ failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ if(result)
+ free(cbuf);
+ CFRelease(c);
+ return result;
+}
+
#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: */
@@ -968,7 +1045,7 @@ static OSStatus CopyIdentityWithLabel(char *label,
keys_list_count = CFArrayGetCount(keys_list);
*out_cert_and_key = NULL;
status = 1;
- for(i=0; i<keys_list_count; i++) {
+ for(i = 0; i<keys_list_count; i++) {
OSStatus err = noErr;
SecCertificateRef cert = NULL;
SecIdentityRef identity =
@@ -1142,30 +1219,30 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result;
}
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max);
+ (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min);
+ (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max);
return result;
}
else {
#if CURL_SUPPORT_MAC_10_8
long i = ssl_version;
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocolAll,
false);
for(; i <= (ssl_version_max >> 16); i++) {
switch(i) {
case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1,
true);
break;
case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol11,
true);
break;
case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol12,
true);
break;
@@ -1211,10 +1288,10 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#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) {
+ if(BACKEND->ssl_ctx)
+ CFRelease(BACKEND->ssl_ctx);
+ BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
+ if(!BACKEND->ssl_ctx) {
failf(data, "SSL: couldn't create a context!");
return CURLE_OUT_OF_MEMORY;
}
@@ -1222,9 +1299,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
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(BACKEND->ssl_ctx)
+ (void)SSLDisposeContext(BACKEND->ssl_ctx);
+ err = SSLNewContext(false, &(BACKEND->ssl_ctx));
if(err != noErr) {
failf(data, "SSL: couldn't create a context: OSStatus %d", err);
return CURLE_OUT_OF_MEMORY;
@@ -1232,15 +1309,15 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_SUPPORT_MAC_10_8 */
}
#else
- if(connssl->ssl_ctx)
- (void)SSLDisposeContext(connssl->ssl_ctx);
- err = SSLNewContext(false, &(connssl->ssl_ctx));
+ if(BACKEND->ssl_ctx)
+ (void)SSLDisposeContext(BACKEND->ssl_ctx);
+ err = SSLNewContext(false, &(BACKEND->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 */
+ BACKEND->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
@@ -1248,8 +1325,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+ (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
+ (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
@@ -1262,20 +1339,20 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break;
}
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+ err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3);
if(err != noErr) {
failf(data, "Your version of the OS does not support SSLv3");
return CURLE_SSL_CONNECT_ERROR;
}
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+ (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3);
break;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
+ err = SSLSetProtocolVersionMin(BACKEND->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);
+ (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2);
break;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
@@ -1284,19 +1361,19 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
else {
#if CURL_SUPPORT_MAC_10_8
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocolAll,
false);
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1,
true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol11,
true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol12,
true);
break;
@@ -1311,7 +1388,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break;
}
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol3,
true);
if(err != noErr) {
@@ -1320,7 +1397,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
break;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol2,
true);
if(err != noErr) {
@@ -1340,12 +1417,12 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
" SSL/TLS version");
return CURLE_SSL_CONNECT_ERROR;
}
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false);
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kTLSProtocol1,
true);
break;
@@ -1359,7 +1436,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
failf(data, "Your version of the OS does not support TLSv1.3");
return CURLE_SSL_CONNECT_ERROR;
case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol2,
true);
if(err != noErr) {
@@ -1368,7 +1445,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
break;
case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
kSSLProtocol3,
true);
if(err != noErr) {
@@ -1418,25 +1495,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* 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);
+ char *certp;
+ CURLcode result = CopyCertSubject(data, cert, &certp);
+ if(!result) {
+ infof(data, "Client certificate: %s\n", certp);
+ free(certp);
}
+
+ CFRelease(cert);
+ if(result)
+ return result;
}
certs_c[0] = cert_and_key;
certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
&kCFTypeArrayCallBacks);
- err = SSLSetCertificate(connssl->ssl_ctx, certs);
+ err = SSLSetCertificate(BACKEND->ssl_ctx, certs);
if(certs)
CFRelease(certs);
if(err != noErr) {
@@ -1499,7 +1572,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
if(SSLSetSessionOption != NULL) {
#endif /* CURL_BUILD_MAC */
bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
- err = SSLSetSessionOption(connssl->ssl_ctx,
+ err = SSLSetSessionOption(BACKEND->ssl_ctx,
kSSLSessionOptionBreakOnServerAuth,
break_on_auth);
if(err != noErr) {
@@ -1509,7 +1582,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
else {
#if CURL_SUPPORT_MAC_10_8
- err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+ err = SSLSetEnableCertVerify(BACKEND->ssl_ctx,
conn->ssl_config.verifypeer?true:false);
if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
@@ -1518,7 +1591,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_SUPPORT_MAC_10_8 */
}
#else
- err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+ err = SSLSetEnableCertVerify(BACKEND->ssl_ctx,
conn->ssl_config.verifypeer?true:false);
if(err != noErr) {
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
@@ -1539,7 +1612,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
* Both hostname check and SNI require SSLSetPeerDomainName().
* Also: the verifyhost setting influences SNI usage */
if(conn->ssl_config.verifyhost) {
- err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname,
+ err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname,
strlen(hostname));
if(err != noErr) {
@@ -1565,11 +1638,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
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);
+ (void)SSLGetNumberSupportedCiphers(BACKEND->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,
+ SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers,
&all_ciphers_count) == noErr) {
for(i = 0UL ; i < all_ciphers_count ; i++) {
#if CURL_BUILD_MAC
@@ -1651,7 +1724,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
break;
}
}
- err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers,
+ err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers,
allowed_ciphers_count);
if(err != noErr) {
failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
@@ -1672,9 +1745,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
specifically doesn't want us doing that: */
if(SSLSetSessionOption != NULL) {
/* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */
- SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
+ SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
!data->set.ssl.enable_beast);
- SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart,
+ SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart,
data->set.ssl.falsestart); /* false start support */
}
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
@@ -1688,7 +1761,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
&ssl_sessionid_len, sockindex)) {
/* we got a session id, use it! */
- err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+ err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
Curl_ssl_sessionid_unlock(conn);
if(err != noErr) {
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
@@ -1706,7 +1779,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
ssl_sessionid_len = strlen(ssl_sessionid);
- err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+ err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
if(err != noErr) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
@@ -1723,7 +1796,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
}
- err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
+ err = SSLSetIOFuncs(BACKEND->ssl_ctx, SocketRead, SocketWrite);
if(err != noErr) {
failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -1733,8 +1806,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* 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);
+ BACKEND->ssl_sockfd = sockfd;
+ err = SSLSetConnection(BACKEND->ssl_ctx, connssl);
if(err != noErr) {
failf(data, "SSL: SSLSetConnection() failed: %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -1797,7 +1870,7 @@ 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;
+ unsigned char buf[512], *data;
fd = open(file, 0);
if(fd < 0)
@@ -1875,6 +1948,8 @@ static int append_cert_to_array(struct Curl_easy *data,
CFMutableArrayRef array)
{
CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
+ char *certp;
+ CURLcode result;
if(!certdata) {
failf(data, "SSL: failed to allocate array for CA certificate");
return CURLE_OUT_OF_MEMORY;
@@ -1889,25 +1964,10 @@ static int append_cert_to_array(struct Curl_easy *data,
}
/* 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;
- }
+ result = CopyCertSubject(data, cacert, &certp);
+ if(result)
+ return result;
+ free(certp);
CFArrayAppendValue(array, cacert);
CFRelease(cacert);
@@ -2155,12 +2215,12 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|| ssl_connect_2_writing == connssl->connecting_state);
/* Here goes nothing: */
- err = SSLHandshake(connssl->ssl_ctx);
+ err = SSLHandshake(BACKEND->ssl_ctx);
if(err != noErr) {
switch(err) {
case errSSLWouldBlock: /* they're not done with us yet */
- connssl->connecting_state = connssl->ssl_direction ?
+ connssl->connecting_state = BACKEND->ssl_direction ?
ssl_connect_2_writing : ssl_connect_2_reading;
return CURLE_OK;
@@ -2169,7 +2229,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
case -9841:
if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
- connssl->ssl_ctx);
+ BACKEND->ssl_ctx);
if(res != CURLE_OK)
return res;
}
@@ -2247,7 +2307,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
#ifdef DARWIN_SSL_PINNEDPUBKEY
if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
- CURLcode result = pkp_pin_peer_pubkey(data, connssl->ssl_ctx,
+ CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx,
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
if(result) {
failf(data, "SSL: public key does not match pinned public key!");
@@ -2257,8 +2317,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
#endif /* DARWIN_SSL_PINNEDPUBKEY */
/* Informational message */
- (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
- (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
+ (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher);
+ (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol);
switch(protocol) {
case kSSLProtocol2:
infof(data, "SSL 2.0 connection using %s\n",
@@ -2299,36 +2359,32 @@ show_verbose_server_cert(struct connectdata *conn,
{
struct Curl_easy *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;
- if(!connssl->ssl_ctx)
+ if(!BACKEND->ssl_ctx)
return;
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
#if CURL_BUILD_IOS
#pragma unused(server_certs)
- err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+ err = SSLCopyPeerTrust(BACKEND->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++) {
+ CURLcode result;
+ char *certp;
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);
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s\n", certp);
+ free(certp);
}
- CFRelease(server_cert_summary);
}
CFRelease(trust);
}
@@ -2341,45 +2397,40 @@ show_verbose_server_cert(struct connectdata *conn,
Lion or later. */
if(SecTrustEvaluateAsync != NULL) {
#pragma unused(server_certs)
- err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+ err = SSLCopyPeerTrust(BACKEND->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++) {
+ char *certp;
+ CURLcode result;
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);
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s\n", certp);
+ free(certp);
}
- CFRelease(server_cert_summary);
}
CFRelease(trust);
}
}
else {
#if CURL_SUPPORT_MAC_10_8
- err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+ err = SSLCopyPeerCertificates(BACKEND->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++) {
+ char *certp;
+ CURLcode result;
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);
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s\n", certp);
+ free(certp);
}
- CFRelease(server_cert_summary);
}
CFRelease(server_certs);
}
@@ -2388,20 +2439,18 @@ show_verbose_server_cert(struct connectdata *conn,
#endif /* CURL_BUILD_IOS */
#else
#pragma unused(trust)
- err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+ err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs);
if(err == noErr) {
count = CFArrayGetCount(server_certs);
for(i = 0L ; i < count ; i++) {
+ CURLcode result;
+ char *certp;
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);
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s\n", certp);
+ free(certp);
}
- CFRelease(server_cert_summary);
}
CFRelease(server_certs);
}
@@ -2450,7 +2499,7 @@ darwinssl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
@@ -2545,17 +2594,13 @@ darwinssl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode
-Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static 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)
+static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -2570,28 +2615,28 @@ Curl_darwinssl_connect(struct connectdata *conn,
return CURLE_OK;
}
-void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
+static 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(BACKEND->ssl_ctx) {
+ (void)SSLClose(BACKEND->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
if(SSLCreateContext != NULL)
- CFRelease(connssl->ssl_ctx);
+ CFRelease(BACKEND->ssl_ctx);
#if CURL_SUPPORT_MAC_10_8
else
- (void)SSLDisposeContext(connssl->ssl_ctx);
+ (void)SSLDisposeContext(BACKEND->ssl_ctx);
#endif /* CURL_SUPPORT_MAC_10_8 */
#else
- (void)SSLDisposeContext(connssl->ssl_ctx);
+ (void)SSLDisposeContext(BACKEND->ssl_ctx);
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- connssl->ssl_ctx = NULL;
+ BACKEND->ssl_ctx = NULL;
}
- connssl->ssl_sockfd = 0;
+ BACKEND->ssl_sockfd = 0;
}
-int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
@@ -2600,7 +2645,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
int rc;
char buf[120];
- if(!connssl->ssl_ctx)
+ if(!BACKEND->ssl_ctx)
return 0;
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@@ -2644,7 +2689,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
return rc;
}
-void Curl_darwinssl_session_free(void *ptr)
+static 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
@@ -2655,7 +2700,7 @@ void Curl_darwinssl_session_free(void *ptr)
Curl_safefree(ptr);
}
-size_t Curl_darwinssl_version(char *buffer, size_t size)
+static size_t Curl_darwinssl_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "SecureTransport");
}
@@ -2668,14 +2713,14 @@ size_t Curl_darwinssl_version(char *buffer, size_t size)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-int Curl_darwinssl_check_cxn(struct connectdata *conn)
+static 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(BACKEND->ssl_ctx) {
+ err = SSLGetSessionState(BACKEND->ssl_ctx, &state);
if(err == noErr)
return state == kSSLConnected || state == kSSLHandshake;
return -1;
@@ -2683,15 +2728,15 @@ int Curl_darwinssl_check_cxn(struct connectdata *conn)
return 0;
}
-bool Curl_darwinssl_data_pending(const struct connectdata *conn,
- int connindex)
+static 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(BACKEND->ssl_ctx) { /* SSL is in use */
+ err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer);
if(err == noErr)
return buffer > 0UL;
return false;
@@ -2700,14 +2745,16 @@ bool Curl_darwinssl_data_pending(const struct connectdata *conn,
return false;
}
-CURLcode Curl_darwinssl_random(unsigned char *entropy,
- size_t length)
+static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM,
+ 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;
+ (void)data;
+
for(i = 0 ; i < length ; i++) {
if(i % sizeof(u_int32_t) == 0)
random_number = arc4random();
@@ -2718,25 +2765,26 @@ CURLcode Curl_darwinssl_random(unsigned char *entropy,
return CURLE_OK;
}
-void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
+static CURLcode 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);
+ return CURLE_OK;
}
-void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static void Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
- assert(sha256len >= SHA256_DIGEST_LENGTH);
+ assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
}
-bool Curl_darwinssl_false_start(void)
+static bool Curl_darwinssl_false_start(void)
{
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
if(SSLSetSessionOption != NULL)
@@ -2771,15 +2819,15 @@ static ssize_t darwinssl_send(struct connectdata *conn,
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) {
+ if(BACKEND->ssl_write_buffered_length) {
/* Write the buffered data: */
- err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
+ err = SSLWrite(BACKEND->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;
+ processed = BACKEND->ssl_write_buffered_length;
+ BACKEND->ssl_write_buffered_length = 0UL;
break;
case errSSLWouldBlock: /* argh, try again */
*curlcode = CURLE_AGAIN;
@@ -2792,13 +2840,13 @@ static ssize_t darwinssl_send(struct connectdata *conn,
}
else {
/* We've got new data to write: */
- err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
+ err = SSLWrite(BACKEND->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;
+ BACKEND->ssl_write_buffered_length = len;
*curlcode = CURLE_AGAIN;
return -1L;
default:
@@ -2820,7 +2868,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
/*struct Curl_easy *data = conn->data;*/
struct ssl_connect_data *connssl = &conn->ssl[num];
size_t processed = 0UL;
- OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
+ OSStatus err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed);
if(err != noErr) {
switch(err) {
@@ -2851,6 +2899,50 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
return (ssize_t)processed;
}
+static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->ssl_ctx;
+}
+
+const struct Curl_ssl Curl_ssl_darwinssl = {
+ { CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */
+
+ 0, /* have_ca_path */
+ 0, /* have_certinfo */
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+ 1, /* have_pinnedpubkey */
+#else
+ 0, /* have_pinnedpubkey */
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_none_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ Curl_darwinssl_version, /* version */
+ Curl_darwinssl_check_cxn, /* check_cxn */
+ Curl_darwinssl_shutdown, /* shutdown */
+ Curl_darwinssl_data_pending, /* data_pending */
+ Curl_darwinssl_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_darwinssl_connect, /* connect */
+ Curl_darwinssl_connect_nonblocking, /* connect_nonblocking */
+ Curl_darwinssl_get_internals, /* get_internals */
+ Curl_darwinssl_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_darwinssl_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_darwinssl_false_start, /* false_start */
+ Curl_darwinssl_md5sum, /* md5sum */
+ Curl_darwinssl_sha256sum /* sha256sum */
+};
+
#ifdef __clang__
#pragma clang diagnostic pop
#endif
diff --git a/lib/vtls/darwinssl.h b/lib/vtls/darwinssl.h
index 13e78515a..23c7f705c 100644
--- a/lib/vtls/darwinssl.h
+++ b/lib/vtls/darwinssl.h
@@ -26,76 +26,7 @@
#ifdef USE_DARWINSSL
-CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-
-/* 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);
-
-CURLcode 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);
-void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len);
-bool Curl_darwinssl_false_start(void);
-
-/* Set the API backend definition to SecureTransport */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
-
-/* pinned public key support tests */
-
-/* version 1 supports macOS 10.12+ and iOS 10+ */
-#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
- (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
-#define DARWIN_SSL_PINNEDPUBKEY_V1 1
-#endif
-
-/* version 2 supports MacOSX 10.7+ */
-#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
-#define DARWIN_SSL_PINNEDPUBKEY_V2 1
-#endif
-
-#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define DARWIN_SSL_PINNEDPUBKEY 1
-#define have_curlssl_pinnedpubkey 1
-#endif /* DARWIN_SSL_PINNEDPUBKEY */
-
-/* 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(x) ((void)x)
-#define curlssl_close Curl_darwinssl_close
-#define curlssl_shutdown(x,y) 0
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)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) ((void)x, Curl_darwinssl_random(y,z))
-#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
-#define curlssl_sha256sum(a,b,c,d) \
- Curl_darwinssl_sha256sum((unsigned char *)a, b, c, d)
-#define curlssl_false_start() Curl_darwinssl_false_start()
+extern const struct Curl_ssl Curl_ssl_darwinssl;
#endif /* USE_DARWINSSL */
#endif /* HEADER_CURL_DARWINSSL_H */
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 565f10f07..ec142fb9e 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -98,6 +98,14 @@
#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
#define CURL_GSKPROTO_LAST 5
+struct ssl_backend_data {
+ gsk_handle handle;
+ int iocport;
+ int localfd;
+ int remotefd;
+};
+
+#define BACKEND connssl->backend
/* Supported ciphers. */
typedef struct {
@@ -427,7 +435,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
}
-int Curl_gskit_init(void)
+static int Curl_gskit_init(void)
{
/* No initialisation needed. */
@@ -435,7 +443,7 @@ int Curl_gskit_init(void)
}
-void Curl_gskit_cleanup(void)
+static void Curl_gskit_cleanup(void)
{
/* Nothing to do. */
}
@@ -495,14 +503,14 @@ static void cancel_async_handshake(struct connectdata *conn, int sockindex)
Qso_OverlappedIO_t cstat;
if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
- QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
+ QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
}
static void close_async_handshake(struct ssl_connect_data *connssl)
{
- QsoDestroyIOCompletionPort(connssl->iocport);
- connssl->iocport = -1;
+ QsoDestroyIOCompletionPort(BACKEND->iocport);
+ BACKEND->iocport = -1;
}
/* SSL over SSL
@@ -620,12 +628,12 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
FD_ZERO(&fds_write);
n = -1;
if(directions & SOS_READ) {
- FD_SET(connssl->remotefd, &fds_write);
- n = connssl->remotefd;
+ FD_SET(BACKEND->remotefd, &fds_write);
+ n = BACKEND->remotefd;
}
if(directions & SOS_WRITE) {
- FD_SET(connssl->remotefd, &fds_read);
- n = connssl->remotefd;
+ FD_SET(BACKEND->remotefd, &fds_read);
+ n = BACKEND->remotefd;
FD_SET(conn->sock[sockindex], &fds_write);
if(n < conn->sock[sockindex])
n = conn->sock[sockindex];
@@ -634,14 +642,15 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
if(i < 0)
return -1; /* Select error. */
- if(FD_ISSET(connssl->remotefd, &fds_write)) {
+ if(FD_ISSET(BACKEND->remotefd, &fds_write)) {
/* Try getting data from HTTPS proxy and pipe it upstream. */
n = 0;
- i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
+ i = gsk_secure_soc_read(connproxyssl->backend->handle,
+ buf, sizeof buf, &n);
switch(i) {
case GSK_OK:
if(n) {
- i = write(connssl->remotefd, buf, n);
+ i = write(BACKEND->remotefd, buf, n);
if(i < 0)
return -1;
ret = 1;
@@ -655,14 +664,14 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
}
}
- if(FD_ISSET(connssl->remotefd, &fds_read) &&
+ if(FD_ISSET(BACKEND->remotefd, &fds_read) &&
FD_ISSET(conn->sock[sockindex], &fds_write)) {
/* Pipe data to HTTPS proxy. */
- n = read(connssl->remotefd, buf, sizeof buf);
+ n = read(BACKEND->remotefd, buf, sizeof buf);
if(n < 0)
return -1;
if(n) {
- i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
+ i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
if(i != GSK_OK || n != m)
return -1;
ret = 1;
@@ -676,23 +685,23 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
static void close_one(struct ssl_connect_data *connssl,
struct connectdata *conn, int sockindex)
{
- if(connssl->handle) {
- gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
+ if(BACKEND->handle) {
+ gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
"gsk_secure_soc_close()", 0);
/* Last chance to drain output. */
while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
;
- connssl->handle = (gsk_handle) NULL;
- if(connssl->localfd >= 0) {
- close(connssl->localfd);
- connssl->localfd = -1;
+ BACKEND->handle = (gsk_handle) NULL;
+ if(BACKEND->localfd >= 0) {
+ close(BACKEND->localfd);
+ BACKEND->localfd = -1;
}
- if(connssl->remotefd >= 0) {
- close(connssl->remotefd);
- connssl->remotefd = -1;
+ if(BACKEND->remotefd >= 0) {
+ close(BACKEND->remotefd);
+ BACKEND->remotefd = -1;
}
}
- if(connssl->iocport >= 0)
+ if(BACKEND->iocport >= 0)
close_async_handshake(connssl);
}
@@ -700,13 +709,14 @@ static void close_one(struct ssl_connect_data *connssl,
static ssize_t gskit_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
CURLcode cc = CURLE_SEND_ERROR;
int written;
if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
cc = gskit_status(data,
- gsk_secure_soc_write(conn->ssl[sockindex].handle,
+ gsk_secure_soc_write(BACKEND->handle,
(char *) mem, (int) len, &written),
"gsk_secure_soc_write()", CURLE_SEND_ERROR);
if(cc == CURLE_OK)
@@ -724,6 +734,7 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
size_t buffersize, CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
struct Curl_easy *data = conn->data;
int buffsize;
int nread;
@@ -731,7 +742,7 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
- cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+ cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
buf, buffsize, &nread),
"gsk_secure_soc_read()", CURLE_RECV_ERROR);
}
@@ -806,10 +817,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
/* Create SSL environment, start (preferably asynchronous) handshake. */
- connssl->handle = (gsk_handle) NULL;
- connssl->iocport = -1;
- connssl->localfd = -1;
- connssl->remotefd = -1;
+ BACKEND->handle = (gsk_handle) NULL;
+ BACKEND->iocport = -1;
+ BACKEND->localfd = -1;
+ BACKEND->remotefd = -1;
/* GSKit supports two ways of specifying an SSL context: either by
* application identifier (that should have been defined at the system
@@ -842,7 +853,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
/* Create secure session. */
- result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
+ result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
"gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
gsk_environment_close(&envir);
if(result)
@@ -852,18 +863,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(conn->proxy_ssl[sockindex].use) {
if(inetsocketpair(sockpair))
return CURLE_SSL_CONNECT_ERROR;
- connssl->localfd = sockpair[0];
- connssl->remotefd = sockpair[1];
- setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
+ BACKEND->localfd = sockpair[0];
+ BACKEND->remotefd = sockpair[1];
+ setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
(void *) sobufsize, sizeof sobufsize);
- setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
+ setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
(void *) sobufsize, sizeof sobufsize);
- setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
+ setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
(void *) sobufsize, sizeof sobufsize);
- setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
+ setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
(void *) sobufsize, sizeof sobufsize);
- curlx_nonblock(connssl->localfd, TRUE);
- curlx_nonblock(connssl->remotefd, TRUE);
+ curlx_nonblock(BACKEND->localfd, TRUE);
+ curlx_nonblock(BACKEND->remotefd, TRUE);
}
/* Determine which SSL/TLS version should be enabled. */
@@ -897,7 +908,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
/* Process SNI. Ignore if not supported (on OS400 < V7R1). */
if(sni) {
- result = set_buffer(data, connssl->handle,
+ result = set_buffer(data, BACKEND->handle,
GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL)
result = CURLE_OK;
@@ -911,34 +922,34 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(timeout < 0)
result = CURLE_OPERATION_TIMEDOUT;
else
- result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
+ result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
(timeout + 999) / 1000);
}
if(!result)
- result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
+ result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
if(!result)
- result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
- connssl->localfd: conn->sock[sockindex]);
+ result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
+ BACKEND->localfd: conn->sock[sockindex]);
if(!result)
- result = set_ciphers(conn, connssl->handle, &protoflags);
+ result = set_ciphers(conn, BACKEND->handle, &protoflags);
if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled");
result = CURLE_SSL_CIPHER;
}
if(!result)
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
(protoflags & CURL_GSKPROTO_SSLV2_MASK)?
GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
if(!result)
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
(protoflags & CURL_GSKPROTO_SSLV3_MASK)?
GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
if(!result)
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
(protoflags & CURL_GSKPROTO_TLSV10_MASK)?
GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
if(!result) {
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
(protoflags & CURL_GSKPROTO_TLSV11_MASK)?
GSK_TRUE: GSK_FALSE, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -950,7 +961,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
}
if(!result) {
- result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
+ result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
(protoflags & CURL_GSKPROTO_TLSV12_MASK)?
GSK_TRUE: GSK_FALSE, TRUE);
if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -962,18 +973,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
}
if(!result)
- result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
+ result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
verifypeer? GSK_SERVER_AUTH_FULL:
GSK_SERVER_AUTH_PASSTHRU, FALSE);
if(!result) {
/* Start handshake. Try asynchronous first. */
memset(&commarea, 0, sizeof commarea);
- connssl->iocport = QsoCreateIOCompletionPort();
- if(connssl->iocport != -1) {
+ BACKEND->iocport = QsoCreateIOCompletionPort();
+ if(BACKEND->iocport != -1) {
result = gskit_status(data,
- gsk_secure_soc_startInit(connssl->handle,
- connssl->iocport,
+ gsk_secure_soc_startInit(BACKEND->handle,
+ BACKEND->iocport,
&commarea),
"gsk_secure_soc_startInit()",
CURLE_SSL_CONNECT_ERROR);
@@ -993,7 +1004,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
else {
/* No more completion port available. Use synchronous IO. */
- result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
+ result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
"gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
if(!result) {
connssl->connecting_state = ssl_connect_3;
@@ -1026,7 +1037,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
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)) {
+ switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat, &stmv)) {
case 1: /* Operation complete. */
break;
case -1: /* An error occurred: handshake still in progress. */
@@ -1075,7 +1086,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
/* SSL handshake done: gather certificate info and verify host. */
- if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
+ if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
GSK_PARTNER_CERT_INFO,
&cdev, &cdec),
"gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
@@ -1216,9 +1227,8 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
}
-CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
CURLcode result;
@@ -1229,7 +1239,7 @@ CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
}
-CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done;
@@ -1245,14 +1255,14 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
}
-void Curl_gskit_close(struct connectdata *conn, int sockindex)
+static void Curl_gskit_close(struct connectdata *conn, int sockindex)
{
close_one(&conn->ssl[sockindex], conn, sockindex);
close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
}
-int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct Curl_easy *data = conn->data;
@@ -1261,7 +1271,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
int rc;
char buf[120];
- if(!connssl->handle)
+ if(!BACKEND->handle)
return 0;
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@@ -1306,21 +1316,22 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
}
-size_t Curl_gskit_version(char *buffer, size_t size)
+static 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)
+static int Curl_gskit_check_cxn(struct connectdata *cxn)
{
+ struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
int err;
int errlen;
/* The only thing that can be tested here is at the socket level. */
- if(!cxn->ssl[FIRSTSOCKET].handle)
+ if(!BACKEND->handle)
return 0; /* connection has been closed */
err = 0;
@@ -1334,4 +1345,46 @@ int Curl_gskit_check_cxn(struct connectdata *cxn)
return -1; /* connection status unknown */
}
+static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_gskit = {
+ { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
+
+ 0, /* have_ca_path */
+ 1, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ /* TODO: convert to 1 and fix test #1014 (if need) */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_gskit_init, /* init */
+ Curl_gskit_cleanup, /* cleanup */
+ Curl_gskit_version, /* version */
+ Curl_gskit_check_cxn, /* check_cxn */
+ Curl_gskit_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_gskit_connect, /* connect */
+ Curl_gskit_connect_nonblocking, /* connect_nonblocking */
+ Curl_gskit_get_internals, /* get_internals */
+ Curl_gskit_close, /* close */
+ Curl_none_close_all, /* close_all */
+ /* No session handling for GSKit */
+ Curl_none_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ NULL /* sha256sum */
+};
+
#endif /* USE_GSKIT */
diff --git a/lib/vtls/gskit.h b/lib/vtls/gskit.h
index 229759217..466ee4d9d 100644
--- a/lib/vtls/gskit.h
+++ b/lib/vtls/gskit.h
@@ -30,44 +30,8 @@
#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_shutdown(struct connectdata *conn, int sockindex);
-size_t Curl_gskit_version(char *buffer, size_t size);
-int Curl_gskit_check_cxn(struct connectdata *cxn);
-
-/* Support HTTPS-proxy */
-/* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */
-
-/* Set the API backend definition to GSKit */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* 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(x) ((void)x)
-#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 curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
+extern const struct Curl_ssl Curl_ssl_gskit;
#endif /* USE_GSKIT */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index d55f995e8..a844915ef 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -107,6 +107,16 @@ static bool gtls_inited = FALSE;
# include <gnutls/ocsp.h>
#endif
+struct ssl_backend_data {
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t cred;
+#ifdef USE_TLS_SRP
+ gnutls_srp_client_credentials_t srp_client_cred;
+#endif
+};
+
+#define BACKEND connssl->backend
+
/*
* 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()
@@ -186,7 +196,7 @@ static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
* must only be called from within curl_global_init() to keep the thread
* situation under control!
*/
-int Curl_gtls_init(void)
+static int Curl_gtls_init(void)
{
int ret = 1;
if(!gtls_inited) {
@@ -200,13 +210,12 @@ int Curl_gtls_init(void)
return ret;
}
-int Curl_gtls_cleanup(void)
+static void Curl_gtls_cleanup(void)
{
if(gtls_inited) {
gnutls_global_deinit();
gtls_inited = FALSE;
}
- return 1;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -277,7 +286,7 @@ static CURLcode handshake(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- gnutls_session_t session = conn->ssl[sockindex].session;
+ gnutls_session_t session = BACKEND->session;
curl_socket_t sockfd = conn->sock[sockindex];
time_t timeout_ms;
int rc;
@@ -297,9 +306,9 @@ static CURLcode handshake(struct connectdata *conn,
if(connssl->connecting_state == ssl_connect_2_reading
|| connssl->connecting_state == ssl_connect_2_writing) {
- curl_socket_t writefd = 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==
+ curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -475,6 +484,7 @@ gtls_connect_step1(struct connectdata *conn,
int sockindex)
{
struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned int init_flags;
gnutls_session_t session;
int rc;
@@ -510,7 +520,7 @@ gtls_connect_step1(struct connectdata *conn,
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
- if(conn->ssl[sockindex].state == ssl_connection_complete)
+ if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
same connection */
return CURLE_OK;
@@ -526,7 +536,7 @@ gtls_connect_step1(struct connectdata *conn,
sni = FALSE; /* SSLv3 has no SNI */
/* allocate a cred struct */
- rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
+ rc = gnutls_certificate_allocate_credentials(&BACKEND->cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
@@ -537,15 +547,14 @@ gtls_connect_step1(struct connectdata *conn,
infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
rc = gnutls_srp_allocate_client_credentials(
- &conn->ssl[sockindex].srp_client_cred);
+ &BACKEND->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,
+ rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred,
SSL_SET_OPTION(username),
SSL_SET_OPTION(password));
if(rc != GNUTLS_E_SUCCESS) {
@@ -558,10 +567,10 @@ gtls_connect_step1(struct connectdata *conn,
if(SSL_CONN_CONFIG(CAfile)) {
/* set the trusted CA cert bundle file */
- gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
+ gnutls_certificate_set_verify_flags(BACKEND->cred,
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
- rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
+ rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred,
SSL_CONN_CONFIG(CAfile),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
@@ -578,7 +587,7 @@ gtls_connect_step1(struct connectdata *conn,
#ifdef HAS_CAPATH
if(SSL_CONN_CONFIG(CApath)) {
/* set the trusted CA cert directory */
- rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
+ rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred,
SSL_CONN_CONFIG(CApath),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
@@ -597,13 +606,13 @@ gtls_connect_step1(struct connectdata *conn,
/* use system ca certificate store as fallback */
if(SSL_CONN_CONFIG(verifypeer) &&
!(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
- gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
+ gnutls_certificate_set_x509_system_trust(BACKEND->cred);
}
#endif
if(SSL_SET_OPTION(CRLfile)) {
/* set the CRL list file */
- rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
+ rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred,
SSL_SET_OPTION(CRLfile),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
@@ -624,14 +633,14 @@ gtls_connect_step1(struct connectdata *conn,
init_flags |= GNUTLS_NO_TICKETS;
#endif
- rc = gnutls_init(&conn->ssl[sockindex].session, init_flags);
+ rc = gnutls_init(&BACKEND->session, init_flags);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_init() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
}
/* convenient assign */
- session = conn->ssl[sockindex].session;
+ session = BACKEND->session;
if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6
@@ -788,7 +797,7 @@ gtls_connect_step1(struct connectdata *conn,
GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
GNUTLS_PKCS_USE_PBES2_AES_256;
rc = gnutls_certificate_set_x509_key_file2(
- conn->ssl[sockindex].cred,
+ BACKEND->cred,
SSL_SET_OPTION(cert),
SSL_SET_OPTION(key) ?
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
@@ -808,7 +817,7 @@ gtls_connect_step1(struct connectdata *conn,
}
else {
if(gnutls_certificate_set_x509_key_file(
- conn->ssl[sockindex].cred,
+ BACKEND->cred,
SSL_SET_OPTION(cert),
SSL_SET_OPTION(key) ?
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
@@ -824,7 +833,7 @@ gtls_connect_step1(struct connectdata *conn,
/* put the credentials to the current session */
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
- conn->ssl[sockindex].srp_client_cred);
+ BACKEND->srp_client_cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
@@ -834,7 +843,7 @@ gtls_connect_step1(struct connectdata *conn,
#endif
{
rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
- conn->ssl[sockindex].cred);
+ BACKEND->cred);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
@@ -842,7 +851,7 @@ gtls_connect_step1(struct connectdata *conn,
}
if(conn->proxy_ssl[sockindex].use) {
- transport_ptr = conn->proxy_ssl[sockindex].session;
+ transport_ptr = conn->proxy_ssl[sockindex].backend->session;
gnutls_transport_push = Curl_gtls_push_ssl;
gnutls_transport_pull = Curl_gtls_pull_ssl;
}
@@ -967,7 +976,8 @@ gtls_connect_step3(struct connectdata *conn,
time_t certclock;
const char *ptr;
struct Curl_easy *data = conn->data;
- gnutls_session_t session = conn->ssl[sockindex].session;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ gnutls_session_t session = BACKEND->session;
int rc;
#ifdef HAS_ALPN
gnutls_datum_t proto;
@@ -1198,7 +1208,7 @@ gtls_connect_step3(struct connectdata *conn,
SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
}
- size=sizeof(certbuf);
+ 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,
@@ -1238,7 +1248,7 @@ gtls_connect_step3(struct connectdata *conn,
#endif
if(addrlen) {
- for(i=0; ; i++) {
+ for(i = 0; ; i++) {
certaddrlen = sizeof(certaddr);
ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
&certaddrlen, NULL);
@@ -1471,7 +1481,7 @@ gtls_connect_common(struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* Initiate the connection, if not already done */
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
rc = gtls_connect_step1(conn, sockindex);
if(rc)
return rc;
@@ -1483,29 +1493,24 @@ gtls_connect_common(struct connectdata *conn,
return rc;
/* Finish connecting once the handshake is done */
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
rc = gtls_connect_step3(conn, sockindex);
if(rc)
return rc;
}
- *done = ssl_connect_1==connssl->connecting_state;
+ *done = ssl_connect_1 == connssl->connecting_state;
return CURLE_OK;
}
-CURLcode
-Curl_gtls_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static 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)
-
+static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -1519,15 +1524,18 @@ Curl_gtls_connect(struct connectdata *conn,
return CURLE_OK;
}
-bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
+static bool Curl_gtls_data_pending(const struct connectdata *conn,
+ int connindex)
{
+ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
bool res = FALSE;
- if(conn->ssl[connindex].session &&
- 0 != gnutls_record_check_pending(conn->ssl[connindex].session))
+ if(BACKEND->session &&
+ 0 != gnutls_record_check_pending(BACKEND->session))
res = TRUE;
- if(conn->proxy_ssl[connindex].session &&
- 0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
+ connssl = &conn->proxy_ssl[connindex];
+ if(BACKEND->session &&
+ 0 != gnutls_record_check_pending(BACKEND->session))
res = TRUE;
return res;
@@ -1539,7 +1547,8 @@ static ssize_t gtls_send(struct connectdata *conn,
size_t len,
CURLcode *curlcode)
{
- ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ ssize_t rc = gnutls_record_send(BACKEND->session, mem, len);
if(rc < 0) {
*curlcode = (rc == GNUTLS_E_AGAIN)
@@ -1552,26 +1561,26 @@ static ssize_t gtls_send(struct connectdata *conn,
return rc;
}
-static void close_one(struct ssl_connect_data *ssl)
+static void close_one(struct ssl_connect_data *connssl)
{
- if(ssl->session) {
- gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
- gnutls_deinit(ssl->session);
- ssl->session = NULL;
+ if(BACKEND->session) {
+ gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR);
+ gnutls_deinit(BACKEND->session);
+ BACKEND->session = NULL;
}
- if(ssl->cred) {
- gnutls_certificate_free_credentials(ssl->cred);
- ssl->cred = NULL;
+ if(BACKEND->cred) {
+ gnutls_certificate_free_credentials(BACKEND->cred);
+ BACKEND->cred = NULL;
}
#ifdef USE_TLS_SRP
- if(ssl->srp_client_cred) {
- gnutls_srp_free_client_credentials(ssl->srp_client_cred);
- ssl->srp_client_cred = NULL;
+ if(BACKEND->srp_client_cred) {
+ gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
+ BACKEND->srp_client_cred = NULL;
}
#endif
}
-void Curl_gtls_close(struct connectdata *conn, int sockindex)
+static void Curl_gtls_close(struct connectdata *conn, int sockindex)
{
close_one(&conn->ssl[sockindex]);
close_one(&conn->proxy_ssl[sockindex]);
@@ -1581,8 +1590,9 @@ void Curl_gtls_close(struct connectdata *conn, int 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)
+static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
ssize_t result;
int retval = 0;
struct Curl_easy *data = conn->data;
@@ -1595,16 +1605,16 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
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);
+ gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR);
- if(conn->ssl[sockindex].session) {
+ if(BACKEND->session) {
while(!done) {
int what = SOCKET_READABLE(conn->sock[sockindex],
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,
+ result = gnutls_record_recv(BACKEND->session,
buf, sizeof(buf));
switch(result) {
case 0:
@@ -1635,18 +1645,18 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
done = 1;
}
}
- gnutls_deinit(conn->ssl[sockindex].session);
+ gnutls_deinit(BACKEND->session);
}
- gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
+ gnutls_certificate_free_credentials(BACKEND->cred);
#ifdef USE_TLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL)
- gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
+ gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
#endif
- conn->ssl[sockindex].cred = NULL;
- conn->ssl[sockindex].session = NULL;
+ BACKEND->cred = NULL;
+ BACKEND->session = NULL;
return retval;
}
@@ -1657,9 +1667,10 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
ssize_t ret;
- ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
+ ret = gnutls_record_recv(BACKEND->session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = CURLE_AGAIN;
return -1;
@@ -1679,6 +1690,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
if(ret < 0) {
failf(conn->data, "GnuTLS recv error (%d): %s",
+
(int)ret, gnutls_strerror((int)ret));
*curlcode = CURLE_RECV_ERROR;
return -1;
@@ -1687,12 +1699,12 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
return ret;
}
-void Curl_gtls_session_free(void *ptr)
+static void Curl_gtls_session_free(void *ptr)
{
free(ptr);
}
-size_t Curl_gtls_version(char *buffer, size_t size)
+static size_t Curl_gtls_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}
@@ -1722,9 +1734,8 @@ static int Curl_gtls_seed(struct Curl_easy *data)
#endif
/* data might be NULL! */
-CURLcode Curl_gtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode Curl_gtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
#if defined(USE_GNUTLS_NETTLE)
int rc;
@@ -1739,10 +1750,10 @@ CURLcode Curl_gtls_random(struct Curl_easy *data,
return CURLE_OK;
}
-void Curl_gtls_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
+static CURLcode 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;
@@ -1756,12 +1767,13 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
gcry_md_close(MD5pw);
#endif
+ return CURLE_OK;
}
-void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
#if defined(USE_GNUTLS_NETTLE)
struct sha256_ctx SHA256pw;
@@ -1777,7 +1789,7 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
#endif
}
-bool Curl_gtls_cert_status_request(void)
+static bool Curl_gtls_cert_status_request(void)
{
#ifdef HAS_OCSP
return TRUE;
@@ -1786,4 +1798,44 @@ bool Curl_gtls_cert_status_request(void)
#endif
}
+static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->session;
+}
+
+const struct Curl_ssl Curl_ssl_gnutls = {
+ { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
+
+ 1, /* have_ca_path */
+ 1, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 1, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_gtls_init, /* init */
+ Curl_gtls_cleanup, /* cleanup */
+ Curl_gtls_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_gtls_shutdown, /* shutdown */
+ Curl_gtls_data_pending, /* data_pending */
+ Curl_gtls_random, /* random */
+ Curl_gtls_cert_status_request, /* cert_status_request */
+ Curl_gtls_connect, /* connect */
+ Curl_gtls_connect_nonblocking, /* connect_nonblocking */
+ Curl_gtls_get_internals, /* get_internals */
+ Curl_gtls_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_gtls_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_gtls_md5sum, /* md5sum */
+ Curl_gtls_sha256sum /* sha256sum */
+};
+
#endif /* USE_GNUTLS */
diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h
index 462c04853..780fc109d 100644
--- a/lib/vtls/gtls.h
+++ b/lib/vtls/gtls.h
@@ -28,69 +28,7 @@
#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);
-bool Curl_gtls_data_pending(const struct connectdata *conn,
- int connindex);
-
- /* 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);
-CURLcode Curl_gtls_random(struct Curl_easy *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);
-void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len);
-
-bool Curl_gtls_cert_status_request(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to GnuTLS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 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(x) ((void)x)
-#define curlssl_close Curl_gtls_close
-#define curlssl_shutdown(x,y) Curl_gtls_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_gtls_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y)
-#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 curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
-#define curlssl_cert_status_request() Curl_gtls_cert_status_request()
+extern const struct Curl_ssl Curl_ssl_gnutls;
#endif /* USE_GNUTLS */
#endif /* HEADER_CURL_GTLS_H */
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 037babe38..ce1f8eba8 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -61,6 +61,21 @@
#include "curl_memory.h"
#include "memdebug.h"
+struct ssl_backend_data {
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_entropy_context entropy;
+ mbedtls_ssl_context ssl;
+ int server_fd;
+ mbedtls_x509_crt cacert;
+ mbedtls_x509_crt clicert;
+ mbedtls_x509_crl crl;
+ mbedtls_pk_context pk;
+ mbedtls_ssl_config config;
+ const char *protocols[3];
+};
+
+#define BACKEND connssl->backend
+
/* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
#define THREADING_SUPPORT
@@ -214,9 +229,9 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result;
}
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
mbedtls_ver_min);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
mbedtls_ver_max);
return result;
@@ -238,7 +253,7 @@ mbed_connect_step1(struct connectdata *conn,
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
int ret = -1;
char errorbuf[128];
- errorbuf[0]=0;
+ errorbuf[0] = 0;
/* mbedTLS only supports SSLv3 and TLSv1 */
if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
@@ -248,9 +263,9 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef THREADING_SUPPORT
entropy_init_mutex(&ts_entropy);
- mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
+ mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
- ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
+ ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex,
&ts_entropy, NULL, 0);
if(ret) {
#ifdef MBEDTLS_ERROR_C
@@ -260,11 +275,11 @@ mbed_connect_step1(struct connectdata *conn,
-ret, errorbuf);
}
#else
- mbedtls_entropy_init(&connssl->entropy);
- mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
+ mbedtls_entropy_init(&BACKEND->entropy);
+ mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
- ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func,
- &connssl->entropy, NULL, 0);
+ ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func,
+ &BACKEND->entropy, NULL, 0);
if(ret) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -275,10 +290,10 @@ mbed_connect_step1(struct connectdata *conn,
#endif /* THREADING_SUPPORT */
/* Load the trusted CA */
- mbedtls_x509_crt_init(&connssl->cacert);
+ mbedtls_x509_crt_init(&BACKEND->cacert);
if(ssl_cafile) {
- ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile);
+ ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile);
if(ret<0) {
#ifdef MBEDTLS_ERROR_C
@@ -293,7 +308,7 @@ mbed_connect_step1(struct connectdata *conn,
}
if(ssl_capath) {
- ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath);
+ ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath);
if(ret<0) {
#ifdef MBEDTLS_ERROR_C
@@ -308,10 +323,10 @@ mbed_connect_step1(struct connectdata *conn,
}
/* Load the client certificate */
- mbedtls_x509_crt_init(&connssl->clicert);
+ mbedtls_x509_crt_init(&BACKEND->clicert);
if(ssl_cert) {
- ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert);
+ ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert);
if(ret) {
#ifdef MBEDTLS_ERROR_C
@@ -325,12 +340,12 @@ mbed_connect_step1(struct connectdata *conn,
}
/* Load the client private key */
- mbedtls_pk_init(&connssl->pk);
+ mbedtls_pk_init(&BACKEND->pk);
if(SSL_SET_OPTION(key)) {
- ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
+ ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key),
SSL_SET_OPTION(key_passwd));
- if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
+ if(ret == 0 && !mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA))
ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
if(ret) {
@@ -345,10 +360,10 @@ mbed_connect_step1(struct connectdata *conn,
}
/* Load the CRL */
- mbedtls_x509_crl_init(&connssl->crl);
+ mbedtls_x509_crl_init(&BACKEND->crl);
if(ssl_crlfile) {
- ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile);
+ ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile);
if(ret) {
#ifdef MBEDTLS_ERROR_C
@@ -363,14 +378,14 @@ mbed_connect_step1(struct connectdata *conn,
infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
- mbedtls_ssl_config_init(&connssl->config);
+ mbedtls_ssl_config_init(&BACKEND->config);
- mbedtls_ssl_init(&connssl->ssl);
- if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) {
+ mbedtls_ssl_init(&BACKEND->ssl);
+ if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) {
failf(data, "mbedTLS: ssl_init failed");
return CURLE_SSL_CONNECT_ERROR;
}
- ret = mbedtls_ssl_config_defaults(&connssl->config,
+ ret = mbedtls_ssl_config_defaults(&BACKEND->config,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
@@ -380,20 +395,20 @@ mbed_connect_step1(struct connectdata *conn,
}
/* new profile with RSA min key len = 1024 ... */
- mbedtls_ssl_conf_cert_profile(&connssl->config,
+ mbedtls_ssl_conf_cert_profile(&BACKEND->config,
&mbedtls_x509_crt_profile_fr);
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_1);
infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
break;
case CURL_SSLVERSION_SSLv3:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_0);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_0);
infof(data, "mbedTLS: Set SSL version to SSLv3\n");
break;
@@ -412,25 +427,25 @@ mbed_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
- mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
+ mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
- mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random,
- &connssl->ctr_drbg);
- mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex],
+ mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random,
+ &BACKEND->ctr_drbg);
+ mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex],
mbedtls_net_send,
mbedtls_net_recv,
NULL /* rev_timeout() */);
- mbedtls_ssl_conf_ciphersuites(&connssl->config,
+ mbedtls_ssl_conf_ciphersuites(&BACKEND->config,
mbedtls_ssl_list_ciphersuites());
#if defined(MBEDTLS_SSL_RENEGOTIATION)
- mbedtls_ssl_conf_renegotiation(&connssl->config,
+ mbedtls_ssl_conf_renegotiation(&BACKEND->config,
MBEDTLS_SSL_RENEGOTIATION_ENABLED);
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
- mbedtls_ssl_conf_session_tickets(&connssl->config,
+ mbedtls_ssl_conf_session_tickets(&BACKEND->config,
MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
#endif
@@ -440,7 +455,7 @@ mbed_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
- ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
+ ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session);
if(ret) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
@@ -451,15 +466,15 @@ mbed_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_unlock(conn);
}
- mbedtls_ssl_conf_ca_chain(&connssl->config,
- &connssl->cacert,
- &connssl->crl);
+ mbedtls_ssl_conf_ca_chain(&BACKEND->config,
+ &BACKEND->cacert,
+ &BACKEND->crl);
if(SSL_SET_OPTION(key)) {
- mbedtls_ssl_conf_own_cert(&connssl->config,
- &connssl->clicert, &connssl->pk);
+ mbedtls_ssl_conf_own_cert(&BACKEND->config,
+ &BACKEND->clicert, &BACKEND->pk);
}
- if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
+ if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) {
/* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
the name to set in the SNI extension. So even if curl connects to a
host specified as an IP address, this function must be used. */
@@ -469,7 +484,7 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
- const char **p = &connssl->protocols[0];
+ const char **p = &BACKEND->protocols[0];
#ifdef USE_NGHTTP2
if(data->set.httpversion >= CURL_HTTP_VERSION_2)
*p++ = NGHTTP2_PROTO_VERSION_ID;
@@ -478,19 +493,19 @@ mbed_connect_step1(struct connectdata *conn,
*p = NULL;
/* this function doesn't clone the protocols array, which is why we need
to keep it around */
- if(mbedtls_ssl_conf_alpn_protocols(&connssl->config,
- &connssl->protocols[0])) {
+ if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config,
+ &BACKEND->protocols[0])) {
failf(data, "Failed setting ALPN protocols");
return CURLE_SSL_CONNECT_ERROR;
}
- for(p = &connssl->protocols[0]; *p; ++p)
+ for(p = &BACKEND->protocols[0]; *p; ++p)
infof(data, "ALPN, offering %s\n", *p);
}
#endif
#ifdef MBEDTLS_DEBUG
/* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
- mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data);
+ mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data);
/* - 0 No debug
* - 1 Error
* - 2 State change
@@ -502,7 +517,7 @@ mbed_connect_step1(struct connectdata *conn,
/* give application a chance to interfere with mbedTLS set up. */
if(data->set.ssl.fsslctx) {
- ret = (*data->set.ssl.fsslctx)(data, &connssl->config,
+ ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config,
data->set.ssl.fsslctxp);
if(ret) {
failf(data, "error signaled by ssl ctx callback");
@@ -537,7 +552,7 @@ mbed_connect_step2(struct connectdata *conn,
conn->recv[sockindex] = mbed_recv;
conn->send[sockindex] = mbed_send;
- ret = mbedtls_ssl_handshake(&connssl->ssl);
+ ret = mbedtls_ssl_handshake(&BACKEND->ssl);
if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
connssl->connecting_state = ssl_connect_2_reading;
@@ -557,10 +572,10 @@ mbed_connect_step2(struct connectdata *conn,
}
infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
- mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
+ mbedtls_ssl_get_ciphersuite(&BACKEND->ssl)
);
- ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+ ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl);
if(ret && SSL_CONN_CONFIG(verifypeer)) {
if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
@@ -580,7 +595,7 @@ mbed_connect_step2(struct connectdata *conn,
return CURLE_PEER_FAILED_VERIFICATION;
}
- peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl);
+ peercert = mbedtls_ssl_get_peer_cert(&BACKEND->ssl);
if(peercert && data->set.verbose) {
const size_t bufsize = 16384;
@@ -650,7 +665,7 @@ mbed_connect_step2(struct connectdata *conn,
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
- next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl);
+ next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl);
if(next_protocol) {
infof(data, "ALPN, server accepted to use %s\n", next_protocol);
@@ -700,7 +715,7 @@ mbed_connect_step3(struct connectdata *conn,
mbedtls_ssl_session_init(our_ssl_sessionid);
- ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid);
+ ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
if(ret) {
free(our_ssl_sessionid);
failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
@@ -730,9 +745,10 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
int ret = -1;
- ret = mbedtls_ssl_write(&conn->ssl[sockindex].ssl,
+ ret = mbedtls_ssl_write(&BACKEND->ssl,
(unsigned char *)mem, len);
if(ret < 0) {
@@ -744,22 +760,23 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex,
return ret;
}
-void Curl_mbedtls_close_all(struct Curl_easy *data)
+static void Curl_mbedtls_close_all(struct Curl_easy *data)
{
(void)data;
}
-void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
+static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
{
- mbedtls_pk_free(&conn->ssl[sockindex].pk);
- mbedtls_x509_crt_free(&conn->ssl[sockindex].clicert);
- mbedtls_x509_crt_free(&conn->ssl[sockindex].cacert);
- mbedtls_x509_crl_free(&conn->ssl[sockindex].crl);
- mbedtls_ssl_config_free(&conn->ssl[sockindex].config);
- mbedtls_ssl_free(&conn->ssl[sockindex].ssl);
- mbedtls_ctr_drbg_free(&conn->ssl[sockindex].ctr_drbg);
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ mbedtls_pk_free(&BACKEND->pk);
+ mbedtls_x509_crt_free(&BACKEND->clicert);
+ mbedtls_x509_crt_free(&BACKEND->cacert);
+ mbedtls_x509_crl_free(&BACKEND->crl);
+ mbedtls_ssl_config_free(&BACKEND->config);
+ mbedtls_ssl_free(&BACKEND->ssl);
+ mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg);
#ifndef THREADING_SUPPORT
- mbedtls_entropy_free(&conn->ssl[sockindex].entropy);
+ mbedtls_entropy_free(&BACKEND->entropy);
#endif /* THREADING_SUPPORT */
}
@@ -767,11 +784,12 @@ static ssize_t mbed_recv(struct connectdata *conn, int num,
char *buf, size_t buffersize,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
int ret = -1;
ssize_t len = -1;
memset(buf, 0, buffersize);
- ret = mbedtls_ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf,
+ ret = mbedtls_ssl_read(&BACKEND->ssl, (unsigned char *)buf,
buffersize);
if(ret <= 0) {
@@ -788,21 +806,21 @@ static ssize_t mbed_recv(struct connectdata *conn, int num,
return len;
}
-void Curl_mbedtls_session_free(void *ptr)
+static void Curl_mbedtls_session_free(void *ptr)
{
mbedtls_ssl_session_free(ptr);
free(ptr);
}
-size_t Curl_mbedtls_version(char *buffer, size_t size)
+static size_t Curl_mbedtls_version(char *buffer, size_t size)
{
unsigned int version = mbedtls_version_get_number();
return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
(version>>16)&0xff, (version>>8)&0xff);
}
-CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length)
+static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
#if defined(MBEDTLS_CTR_DRBG_C)
int ret = -1;
@@ -811,7 +829,7 @@ CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_init(&ctr_entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
- errorbuf[0]=0;
+ errorbuf[0] = 0;
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
&ctr_entropy, NULL, 0);
@@ -869,7 +887,7 @@ mbed_connect_common(struct connectdata *conn,
return CURLE_OK;
}
- if(ssl_connect_1==connssl->connecting_state) {
+ if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
@@ -900,9 +918,9 @@ mbed_connect_common(struct connectdata *conn,
if(connssl->connecting_state == ssl_connect_2_reading
|| connssl->connecting_state == ssl_connect_2_writing) {
- curl_socket_t writefd = 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==
+ curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -942,13 +960,13 @@ mbed_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
- if(ssl_connect_3==connssl->connecting_state) {
+ if(ssl_connect_3 == connssl->connecting_state) {
retcode = mbed_connect_step3(conn, sockindex);
if(retcode)
return retcode;
}
- if(ssl_connect_done==connssl->connecting_state) {
+ if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
conn->recv[sockindex] = mbed_recv;
conn->send[sockindex] = mbed_send;
@@ -963,18 +981,14 @@ mbed_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode
-Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return mbed_connect_common(conn, sockindex, TRUE, done);
}
-CURLcode
-Curl_mbedtls_connect(struct connectdata *conn,
- int sockindex)
+static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
{
CURLcode retcode;
bool done = FALSE;
@@ -992,19 +1006,70 @@ Curl_mbedtls_connect(struct connectdata *conn,
* return 0 error initializing SSL
* return 1 SSL initialized successfully
*/
-int Curl_mbedtls_init(void)
+static int Curl_mbedtls_init(void)
{
return Curl_polarsslthreadlock_thread_setup();
}
-void Curl_mbedtls_cleanup(void)
+static void Curl_mbedtls_cleanup(void)
{
(void)Curl_polarsslthreadlock_thread_cleanup();
}
-int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
+static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
+ int sockindex)
{
- return mbedtls_ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
+ const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0;
}
+static void Curl_mbedtls_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
+{
+ (void)sha256len;
+ mbedtls_sha256(input, inputlen, sha256sum, 0);
+}
+
+static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return &BACKEND->ssl;
+}
+
+const struct Curl_ssl Curl_ssl_mbedtls = {
+ { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
+
+ 1, /* have_ca_path */
+ 0, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 1, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_mbedtls_init, /* init */
+ Curl_mbedtls_cleanup, /* cleanup */
+ Curl_mbedtls_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_none_shutdown, /* shutdown */
+ Curl_mbedtls_data_pending, /* data_pending */
+ Curl_mbedtls_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_mbedtls_connect, /* connect */
+ Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
+ Curl_mbedtls_get_internals, /* get_internals */
+ Curl_mbedtls_close, /* close */
+ Curl_mbedtls_close_all, /* close_all */
+ Curl_mbedtls_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ Curl_mbedtls_sha256sum /* sha256sum */
+};
+
#endif /* USE_MBEDTLS */
diff --git a/lib/vtls/mbedtls.h b/lib/vtls/mbedtls.h
index 71d17a491..4a938605b 100644
--- a/lib/vtls/mbedtls.h
+++ b/lib/vtls/mbedtls.h
@@ -26,57 +26,7 @@
#ifdef USE_MBEDTLS
-#include <mbedtls/sha256.h>
-
-/* Called on first use mbedTLS, setup threading if supported */
-int Curl_mbedtls_init(void);
-void Curl_mbedtls_cleanup(void);
-int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-
-/* tell mbedTLS to close down all open information regarding connections (and
- thus session ID caching etc) */
-void Curl_mbedtls_close_all(struct Curl_easy *data);
-
- /* close a SSL connection */
-void Curl_mbedtls_close(struct connectdata *conn, int sockindex);
-
-void Curl_mbedtls_session_free(void *ptr);
-size_t Curl_mbedtls_version(char *buffer, size_t size);
-int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length);
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-/* API setup for mbedTLS */
-#define curlssl_init() Curl_mbedtls_init()
-#define curlssl_cleanup() Curl_mbedtls_cleanup()
-#define curlssl_connect Curl_mbedtls_connect
-#define curlssl_connect_nonblocking Curl_mbedtls_connect_nonblocking
-#define curlssl_session_free(x) Curl_mbedtls_session_free(x)
-#define curlssl_close_all Curl_mbedtls_close_all
-#define curlssl_close Curl_mbedtls_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_mbedtls_version
-#define curlssl_check_cxn(x) (x=x, -1)
-#define curlssl_data_pending(x,y) Curl_mbedtls_data_pending(x, y)
-#define CURL_SSL_BACKEND CURLSSLBACKEND_MBEDTLS
-#define curlssl_sha256sum(a,b,c,d) mbedtls_sha256(a,b,c,0)
-#define curlssl_random(x,y,z) Curl_mbedtls_random(x, y, z)
+extern const struct Curl_ssl Curl_ssl_mbedtls;
#endif /* USE_MBEDTLS */
#endif /* HEADER_CURL_MBEDTLS_H */
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index d1711d6a1..c0b7e63ab 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -78,6 +78,16 @@
/* enough to fit the string "PEM Token #[0|1]" */
#define SLOTSIZE 13
+struct ssl_backend_data {
+ PRFileDesc *handle;
+ char *client_nickname;
+ struct Curl_easy *data;
+ struct curl_llist obj_list;
+ PK11GenericObject *obj_clicert;
+};
+
+#define BACKEND connssl->backend
+
static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL;
@@ -271,7 +281,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
found = PR_FALSE;
- for(i=0; i<NUM_OF_CIPHERS; i++) {
+ for(i = 0; i<NUM_OF_CIPHERS; i++) {
if(strcasecompare(cipher, cipherlist[i].name)) {
cipher_state[i] = PR_TRUE;
found = PR_TRUE;
@@ -290,7 +300,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
}
/* Finally actually enable the selected ciphers */
- for(i=0; i<NUM_OF_CIPHERS; i++) {
+ for(i = 0; i<NUM_OF_CIPHERS; i++) {
if(!cipher_state[i])
continue;
@@ -311,7 +321,7 @@ static bool any_cipher_enabled(void)
{
unsigned int i;
- for(i=0; i<NUM_OF_CIPHERS; i++) {
+ for(i = 0; i<NUM_OF_CIPHERS; i++) {
PRInt32 policy = 0;
SSL_CipherPolicyGet(cipherlist[i].num, &policy);
if(policy)
@@ -396,7 +406,7 @@ static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
/* 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,
+static CURLcode nss_create_object(struct ssl_connect_data *connssl,
CK_OBJECT_CLASS obj_class,
const char *filename, bool cacert)
{
@@ -435,14 +445,14 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
if(!obj)
return result;
- if(insert_wrapped_ptr(&ssl->obj_list, obj) != CURLE_OK) {
+ if(insert_wrapped_ptr(&BACKEND->obj_list, obj) != CURLE_OK) {
PK11_DestroyGenericObject(obj);
return CURLE_OUT_OF_MEMORY;
}
if(!cacert && CKO_CERTIFICATE == obj_class)
/* store reference to a client certificate */
- ssl->obj_clicert = obj;
+ BACKEND->obj_clicert = obj;
return CURLE_OK;
}
@@ -992,7 +1002,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock,
char *issuer_nickname)
{
CERTCertificate *cert, *cert_issuer, *issuer;
- SECStatus res=SECSuccess;
+ SECStatus res = SECSuccess;
void *proto_win = NULL;
cert = SSL_PeerCertificate(sock);
@@ -1004,7 +1014,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock,
if((!cert_issuer) || (!issuer))
res = SECFailure;
else if(SECITEM_CompareItem(&cert_issuer->derCert,
- &issuer->derCert)!=SECEqual)
+ &issuer->derCert) != SECEqual)
res = SECFailure;
CERT_DestroyCertificate(cert);
@@ -1017,7 +1027,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
const char *pinnedpubkey)
{
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- struct Curl_easy *data = connssl->data;
+ struct Curl_easy *data = BACKEND->data;
CERTCertificate *cert;
if(!pinnedpubkey)
@@ -1025,7 +1035,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
return CURLE_OK;
/* get peer certificate */
- cert = SSL_PeerCertificate(connssl->handle);
+ cert = SSL_PeerCertificate(BACKEND->handle);
if(cert) {
/* extract public key from peer certificate */
SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert);
@@ -1069,11 +1079,11 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct SECKEYPrivateKeyStr **pRetKey)
{
struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
- struct Curl_easy *data = connssl->data;
- const char *nickname = connssl->client_nickname;
+ struct Curl_easy *data = BACKEND->data;
+ const char *nickname = BACKEND->client_nickname;
static const char pem_slotname[] = "PEM Token #1";
- if(connssl->obj_clicert) {
+ if(BACKEND->obj_clicert) {
/* use the cert/key provided by PEM reader */
SECItem cert_der = { 0, NULL, 0 };
void *proto_win = SSL_RevealPinArg(sock);
@@ -1086,7 +1096,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
return SECFailure;
}
- if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
+ if(PK11_ReadRawAttribute(PK11_TypeGeneric, BACKEND->obj_clicert, CKA_VALUE,
&cert_der) != SECSuccess) {
failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
PK11_FreeSlot(slot);
@@ -1351,7 +1361,7 @@ static CURLcode nss_init(struct Curl_easy *data)
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
-int Curl_nss_init(void)
+static int Curl_nss_init(void)
{
/* curl_global_init() is not thread-safe so this test is ok */
if(nss_initlock == NULL) {
@@ -1386,7 +1396,7 @@ CURLcode Curl_nss_force_init(struct Curl_easy *data)
}
/* Global cleanup */
-void Curl_nss_cleanup(void)
+static void Curl_nss_cleanup(void)
{
/* This function isn't required to be threadsafe and this is only done
* as a safety feature.
@@ -1426,14 +1436,14 @@ void Curl_nss_cleanup(void)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-int
-Curl_nss_check_cxn(struct connectdata *conn)
+static int Curl_nss_check_cxn(struct connectdata *conn)
{
+ struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
int rc;
char buf;
rc =
- PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
+ PR_Recv(BACKEND->handle, (void *)&buf, 1, PR_MSG_PEEK,
PR_SecondsToInterval(1));
if(rc > 0)
return 1; /* connection still in place */
@@ -1447,48 +1457,49 @@ Curl_nss_check_cxn(struct connectdata *conn)
static void nss_close(struct ssl_connect_data *connssl)
{
/* before the cleanup, check whether we are using a client certificate */
- const bool client_cert = (connssl->client_nickname != NULL)
- || (connssl->obj_clicert != NULL);
+ const bool client_cert = (BACKEND->client_nickname != NULL)
+ || (BACKEND->obj_clicert != NULL);
- free(connssl->client_nickname);
- connssl->client_nickname = NULL;
+ free(BACKEND->client_nickname);
+ BACKEND->client_nickname = NULL;
/* destroy all NSS objects in order to avoid failure of NSS shutdown */
- Curl_llist_destroy(&connssl->obj_list, NULL);
- connssl->obj_clicert = NULL;
+ Curl_llist_destroy(&BACKEND->obj_list, NULL);
+ BACKEND->obj_clicert = NULL;
- if(connssl->handle) {
+ if(BACKEND->handle) {
if(client_cert)
/* 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);
+ SSL_InvalidateSession(BACKEND->handle);
- PR_Close(connssl->handle);
- connssl->handle = NULL;
+ PR_Close(BACKEND->handle);
+ BACKEND->handle = NULL;
}
}
/*
* This function is called when an SSL connection is closed.
*/
-void Curl_nss_close(struct connectdata *conn, int sockindex)
+static void Curl_nss_close(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
- if(connssl->handle || connssl_proxy->handle) {
+ if(BACKEND->handle || connssl_proxy->backend->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->handle)
- /* nss_close(connssl) will transitively close also connssl_proxy->handle
- if both are used. Clear it to avoid a double close leading to crash. */
- connssl_proxy->handle = NULL;
+ if(BACKEND->handle)
+ /* nss_close(connssl) will transitively close also
+ connssl_proxy->backend->handle if both are used. Clear it to avoid
+ a double close leading to crash. */
+ connssl_proxy->backend->handle = NULL;
nss_close(connssl);
nss_close(connssl_proxy);
@@ -1732,7 +1743,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
}
/* cleanup on connection failure */
- Curl_llist_destroy(&connssl->obj_list, NULL);
+ Curl_llist_destroy(&BACKEND->obj_list, NULL);
return curlerr;
}
@@ -1746,7 +1757,7 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
sock_opt.option = PR_SockOpt_Nonblocking;
sock_opt.value.non_blocking = !blocking;
- if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
+ if(PR_SetSocketOption(BACKEND->handle, &sock_opt) != PR_SUCCESS)
return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
return CURLE_OK;
@@ -1770,10 +1781,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
SSL_LIBRARY_VERSION_TLS_1_0 /* max */
};
- connssl->data = data;
+ BACKEND->data = data;
/* list of all NSS objects we need to destroy in Curl_nss_close() */
- Curl_llist_init(&connssl->obj_list, nss_destroy_object);
+ Curl_llist_init(&BACKEND->obj_list, nss_destroy_object);
/* FIXME. NSS doesn't support multiple databases open at the same time. */
PR_Lock(nss_initlock);
@@ -1882,7 +1893,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
if(nickname) {
/* we are not going to use libnsspem.so to read the client cert */
- connssl->obj_clicert = NULL;
+ BACKEND->obj_clicert = NULL;
}
else {
CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
@@ -1895,10 +1906,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
}
/* store the nickname for SelectClientCert() called during handshake */
- connssl->client_nickname = nickname;
+ BACKEND->client_nickname = nickname;
}
else
- connssl->client_nickname = NULL;
+ BACKEND->client_nickname = NULL;
if(SSL_GetClientAuthDataHook(model, SelectClientCert,
(void *)connssl) != SECSuccess) {
@@ -1908,8 +1919,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
if(conn->proxy_ssl[sockindex].use) {
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
- DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
- nspr_io = conn->proxy_ssl[sockindex].handle;
+ DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL);
+ nspr_io = conn->proxy_ssl[sockindex].backend->handle;
second_layer = TRUE;
}
else {
@@ -1939,8 +1950,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
}
/* import our model socket onto the current I/O stack */
- connssl->handle = SSL_ImportFD(model, nspr_io);
- if(!connssl->handle) {
+ BACKEND->handle = SSL_ImportFD(model, nspr_io);
+ if(!BACKEND->handle) {
if(!second_layer)
PR_Close(nspr_io);
goto error;
@@ -1951,36 +1962,36 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
/* This is the password associated with the cert that we're using */
if(SSL_SET_OPTION(key_passwd)) {
- SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd));
+ SSL_SetPKCS11PinArg(BACKEND->handle, SSL_SET_OPTION(key_passwd));
}
#ifdef SSL_ENABLE_OCSP_STAPLING
if(SSL_CONN_CONFIG(verifystatus)) {
- if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
+ if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
!= SECSuccess)
goto error;
}
#endif
#ifdef SSL_ENABLE_NPN
- if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
+ if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
? PR_TRUE : PR_FALSE) != SECSuccess)
goto error;
#endif
#ifdef SSL_ENABLE_ALPN
- if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
+ if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
? PR_TRUE : PR_FALSE) != SECSuccess)
goto error;
#endif
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
if(data->set.ssl.falsestart) {
- if(SSL_OptionSet(connssl->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
+ if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
!= SECSuccess)
goto error;
- if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback,
+ if(SSL_SetCanFalseStartCallback(BACKEND->handle, CanFalseStartCallback,
conn) != SECSuccess)
goto error;
}
@@ -2004,24 +2015,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
cur += ALPN_HTTP_1_1_LENGTH;
- if(SSL_SetNextProtoNego(connssl->handle, protocols, cur) != SECSuccess)
+ if(SSL_SetNextProtoNego(BACKEND->handle, protocols, cur) != SECSuccess)
goto error;
}
#endif
/* Force handshake on next I/O */
- if(SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE)
+ if(SSL_ResetHandshake(BACKEND->handle, /* asServer */ PR_FALSE)
!= SECSuccess)
goto error;
/* propagate hostname to the TLS layer */
- if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ if(SSL_SetURL(BACKEND->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name) != SECSuccess)
goto error;
/* prevent NSS from re-using the session for a different hostname */
- if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ?
+ if(SSL_SetSockPeerID(BACKEND->handle, SSL_IS_PROXY() ?
conn->http_proxy.host.name : conn->host.name)
!= SECSuccess)
goto error;
@@ -2058,7 +2069,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
/* Force the handshake now */
timeout = PR_MillisecondsToInterval((PRUint32) time_left);
- if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
+ if(SSL_ForceHandshakeWithTimeout(BACKEND->handle, timeout) != SECSuccess) {
if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
/* blocking direction is updated by nss_update_connecting_state() */
return CURLE_AGAIN;
@@ -2069,7 +2080,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
goto error;
}
- result = display_conn_info(conn, connssl->handle);
+ result = display_conn_info(conn, BACKEND->handle);
if(result)
goto error;
@@ -2078,7 +2089,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
if(nickname) {
/* we support only nicknames in case of issuercert for now */
- ret = check_issuer_cert(connssl->handle, nickname);
+ ret = check_issuer_cert(BACKEND->handle, nickname);
free(nickname);
}
@@ -2164,13 +2175,13 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
return CURLE_OK;
}
-CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+static 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)
+static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
{
return nss_connect_common(conn, sockindex, done);
}
@@ -2186,9 +2197,9 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
/* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */
- connssl->data = conn->data;
+ BACKEND->data = conn->data;
- rc = PR_Send(connssl->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
+ rc = PR_Send(BACKEND->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
if(rc < 0) {
PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR)
@@ -2223,9 +2234,9 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
/* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */
- connssl->data = conn->data;
+ BACKEND->data = conn->data;
- nread = PR_Recv(connssl->handle, buf, (int)buffersize, 0,
+ nread = PR_Recv(BACKEND->handle, buf, (int)buffersize, 0,
PR_INTERVAL_NO_WAIT);
if(nread < 0) {
/* failed SSL read */
@@ -2252,22 +2263,22 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
return nread;
}
-size_t Curl_nss_version(char *buffer, size_t size)
+static size_t Curl_nss_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
}
/* data might be NULL */
-int Curl_nss_seed(struct Curl_easy *data)
+static int Curl_nss_seed(struct Curl_easy *data)
{
/* make sure that NSS is initialized */
return !!Curl_nss_force_init(data);
}
/* data might be NULL */
-CURLcode Curl_nss_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode Curl_nss_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
Curl_nss_seed(data); /* Initiate the seed if not already done */
@@ -2278,10 +2289,10 @@ CURLcode Curl_nss_random(struct Curl_easy *data,
return CURLE_OK;
}
-void Curl_nss_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
+static CURLcode 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;
@@ -2289,12 +2300,14 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
PK11_DestroyContext(MD5pw, PR_TRUE);
+
+ return CURLE_OK;
}
-void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
unsigned int SHA256out;
@@ -2304,7 +2317,7 @@ void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
PK11_DestroyContext(SHA256pw, PR_TRUE);
}
-bool Curl_nss_cert_status_request(void)
+static bool Curl_nss_cert_status_request(void)
{
#ifdef SSL_ENABLE_OCSP_STAPLING
return TRUE;
@@ -2313,7 +2326,7 @@ bool Curl_nss_cert_status_request(void)
#endif
}
-bool Curl_nss_false_start(void)
+static bool Curl_nss_false_start(void)
{
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
return TRUE;
@@ -2322,4 +2335,46 @@ bool Curl_nss_false_start(void)
#endif
}
+static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_nss = {
+ { CURLSSLBACKEND_NSS, "nss" }, /* info */
+
+ 1, /* have_ca_path */
+ 1, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 1, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_nss_init, /* init */
+ Curl_nss_cleanup, /* cleanup */
+ Curl_nss_version, /* version */
+ Curl_nss_check_cxn, /* check_cxn */
+ /* NSS has no shutdown function provided and thus always fail */
+ Curl_none_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_nss_random, /* random */
+ Curl_nss_cert_status_request, /* cert_status_request */
+ Curl_nss_connect, /* connect */
+ Curl_nss_connect_nonblocking, /* connect_nonblocking */
+ Curl_nss_get_internals, /* get_internals */
+ Curl_nss_close, /* close */
+ Curl_none_close_all, /* close_all */
+ /* NSS has its own session ID cache */
+ Curl_none_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_nss_false_start, /* false_start */
+ Curl_nss_md5sum, /* md5sum */
+ Curl_nss_sha256sum /* sha256sum */
+};
+
#endif /* USE_NSS */
diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h
index 8c46929ff..41e51b021 100644
--- a/lib/vtls/nssg.h
+++ b/lib/vtls/nssg.h
@@ -30,79 +30,10 @@
#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);
-
-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 Curl_easy *data);
-
/* initialize NSS library if not already */
CURLcode Curl_nss_force_init(struct Curl_easy *data);
-CURLcode Curl_nss_random(struct Curl_easy *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);
-
-void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len);
-
-bool Curl_nss_cert_status_request(void);
-
-bool Curl_nss_false_start(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to NSS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 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(x) ((void)x)
-#define curlssl_close Curl_nss_close
-/* NSS has no shutdown function provided and thus always fail */
-#define curlssl_shutdown(x,y) ((void)x, (void)y, 1)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)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) ((void)x, (void)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 curlssl_sha256sum(a,b,c,d) Curl_nss_sha256sum(a,b,c,d)
-#define curlssl_cert_status_request() Curl_nss_cert_status_request()
-#define curlssl_false_start() Curl_nss_false_start()
+extern const struct Curl_ssl Curl_ssl_nss;
#endif /* USE_NSS */
#endif /* HEADER_CURL_NSSG_H */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 8c1d5a8e5..4253160aa 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -51,8 +51,10 @@
#include "strcase.h"
#include "hostcheck.h"
#include "curl_printf.h"
-
#include <openssl/ssl.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
#include <openssl/rand.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_DSA
@@ -64,6 +66,8 @@
#include <openssl/conf.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
#ifdef HAVE_OPENSSL_PKCS12_H
#include <openssl/pkcs12.h>
@@ -144,6 +148,20 @@ static unsigned long OpenSSL_version_num(void)
#define OPENSSL_load_builtin_modules(x)
#endif
+/*
+ * Whether SSL_CTX_set_keylog_callback is available.
+ * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
+ * BoringSSL: supported since d28f59c27bac (committed 2015-11-19), the
+ * BORINGSSL_201512 macro from 2016-01-21 should be close enough.
+ * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it
+ * lies and pretends to be OpenSSL 2.0.0).
+ */
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
+ !defined(LIBRESSL_VERSION_NUMBER)) || \
+ defined(BORINGSSL_201512)
+#define HAVE_KEYLOG_CALLBACK
+#endif
+
#if defined(LIBRESSL_VERSION_NUMBER)
#define OSSL_PACKAGE "LibreSSL"
#elif defined(OPENSSL_IS_BORINGSSL)
@@ -152,6 +170,38 @@ static unsigned long OpenSSL_version_num(void)
#define OSSL_PACKAGE "OpenSSL"
#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+/* up2date versions of OpenSSL maintain the default reasonably secure without
+ * breaking compatibility, so it is better not to override the default by curl
+ */
+#define DEFAULT_CIPHER_SELECTION NULL
+#else
+/* ... but it is not the case with old versions of OpenSSL */
+#define DEFAULT_CIPHER_SELECTION \
+ "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
+#endif
+
+#ifdef ENABLE_SSLKEYLOGFILE
+typedef struct ssl_tap_state {
+ int master_key_length;
+ unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+ unsigned char client_random[SSL3_RANDOM_SIZE];
+} ssl_tap_state_t;
+#endif /* ENABLE_SSLKEYLOGFILE */
+
+struct ssl_backend_data {
+ /* these ones requires specific SSL-types */
+ SSL_CTX* ctx;
+ SSL* handle;
+ X509* server_cert;
+#ifdef ENABLE_SSLKEYLOGFILE
+ /* tap_state holds the last seen master key if we're logging them */
+ ssl_tap_state_t tap_state;
+#endif
+};
+
+#define BACKEND connssl->backend
+
/*
* 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
@@ -160,6 +210,112 @@ static unsigned long OpenSSL_version_num(void)
*/
#define RAND_LOAD_LENGTH 1024
+#ifdef ENABLE_SSLKEYLOGFILE
+/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
+static FILE *keylog_file_fp;
+
+#ifdef HAVE_KEYLOG_CALLBACK
+static void ossl_keylog_callback(const SSL *ssl, const char *line)
+{
+ (void)ssl;
+
+ /* Using fputs here instead of fprintf since libcurl's fprintf replacement
+ may not be thread-safe. */
+ if(keylog_file_fp && line && *line) {
+ char stackbuf[256];
+ char *buf;
+ size_t linelen = strlen(line);
+
+ if(linelen <= sizeof(stackbuf) - 2)
+ buf = stackbuf;
+ else {
+ buf = malloc(linelen + 2);
+ if(!buf)
+ return;
+ }
+ strncpy(buf, line, linelen);
+ buf[linelen] = '\n';
+ buf[linelen + 1] = '\0';
+
+ fputs(buf, keylog_file_fp);
+ if(buf != stackbuf)
+ free(buf);
+ }
+}
+#else
+#define KEYLOG_PREFIX "CLIENT_RANDOM "
+#define KEYLOG_PREFIX_LEN (sizeof(KEYLOG_PREFIX) - 1)
+/*
+ * tap_ssl_key is called by libcurl to make the CLIENT_RANDOMs if the OpenSSL
+ * being used doesn't have native support for doing that.
+ */
+static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state)
+{
+ const char *hex = "0123456789ABCDEF";
+ int pos, i;
+ char line[KEYLOG_PREFIX_LEN + 2 * SSL3_RANDOM_SIZE + 1 +
+ 2 * SSL_MAX_MASTER_KEY_LENGTH + 1 + 1];
+ const SSL_SESSION *session = SSL_get_session(ssl);
+ unsigned char client_random[SSL3_RANDOM_SIZE];
+ unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+ int master_key_length = 0;
+
+ if(!session || !keylog_file_fp)
+ return;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that
+ * we have a valid SSL context if we have a non-NULL session. */
+ SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
+ master_key_length =
+ SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH);
+#else
+ if(ssl->s3 && session->master_key_length > 0) {
+ master_key_length = session->master_key_length;
+ memcpy(master_key, session->master_key, session->master_key_length);
+ memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ }
+#endif
+
+ if(master_key_length <= 0)
+ return;
+
+ /* Skip writing keys if there is no key or it did not change. */
+ if(state->master_key_length == master_key_length &&
+ !memcmp(state->master_key, master_key, master_key_length) &&
+ !memcmp(state->client_random, client_random, SSL3_RANDOM_SIZE)) {
+ return;
+ }
+
+ state->master_key_length = master_key_length;
+ memcpy(state->master_key, master_key, master_key_length);
+ memcpy(state->client_random, client_random, SSL3_RANDOM_SIZE);
+
+ memcpy(line, KEYLOG_PREFIX, KEYLOG_PREFIX_LEN);
+ pos = KEYLOG_PREFIX_LEN;
+
+ /* Client Random for SSLv3/TLS */
+ for(i = 0; i < SSL3_RANDOM_SIZE; i++) {
+ line[pos++] = hex[client_random[i] >> 4];
+ line[pos++] = hex[client_random[i] & 0xF];
+ }
+ line[pos++] = ' ';
+
+ /* Master Secret (size is at most SSL_MAX_MASTER_KEY_LENGTH) */
+ for(i = 0; i < master_key_length; i++) {
+ line[pos++] = hex[master_key[i] >> 4];
+ line[pos++] = hex[master_key[i] & 0xF];
+ }
+ line[pos++] = '\n';
+ line[pos] = '\0';
+
+ /* Using fputs here instead of fprintf since libcurl's fprintf replacement
+ may not be thread-safe. */
+ fputs(line, keylog_file_fp);
+}
+#endif /* !HAVE_KEYLOG_CALLBACK */
+#endif /* ENABLE_SSLKEYLOGFILE */
+
static const char *SSL_ERROR_to_str(int err)
{
switch(err) {
@@ -214,7 +370,7 @@ static int passwd_callback(char *buf, int num, int encrypting,
if(!encrypting) {
int klen = curlx_uztosi(strlen((char *)global_passwd));
if(num > klen) {
- memcpy(buf, global_passwd, klen+1);
+ memcpy(buf, global_passwd, klen + 1);
return klen;
}
}
@@ -305,7 +461,7 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data)
} while(!rand_enough());
/* generates a default path for the random seed file */
- fname[0]=0; /* blank it first */
+ fname[0] = 0; /* blank it first */
RAND_file_name(fname, sizeof(fname));
if(fname[0]) {
/* we got a file name to try */
@@ -393,6 +549,7 @@ int cert_stuff(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
char error_buffer[256];
+ bool check_privkey = TRUE;
int file_type = do_file_type(cert_type);
@@ -601,7 +758,7 @@ int cert_stuff(struct connectdata *conn,
break;
if(!key_file)
/* cert & key can only be in PEM case in the same file */
- key_file=cert_file;
+ key_file = cert_file;
/* FALLTHROUGH */
case SSL_FILETYPE_ASN1:
if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
@@ -664,13 +821,13 @@ int cert_stuff(struct connectdata *conn,
return 0;
}
- ssl=SSL_new(ctx);
+ ssl = SSL_new(ctx);
if(!ssl) {
failf(data, "unable to create an SSL structure");
return 0;
}
- x509=SSL_get_certificate(ssl);
+ x509 = SSL_get_certificate(ssl);
/* This version was provided by Evan Jordan and is supposed to not
leak memory as the previous version: */
@@ -680,17 +837,32 @@ int cert_stuff(struct connectdata *conn,
EVP_PKEY_free(pktmp);
}
+#ifndef OPENSSL_NO_RSA
+ {
+ /* If RSA is used, don't check the private key if its flags indicate
+ * it doesn't support it. */
+ EVP_PKEY *priv_key = SSL_get_privatekey(ssl);
+ if(EVP_PKEY_id(priv_key) == EVP_PKEY_RSA) {
+ RSA *rsa = EVP_PKEY_get1_RSA(priv_key);
+ if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK)
+ check_privkey = FALSE;
+ RSA_free(rsa); /* Decrement reference count */
+ }
+ }
+#endif
+
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;
+ if(check_privkey == TRUE) {
+ /* 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;
+ }
}
}
return 1;
@@ -718,7 +890,7 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
size--; /* don't overwrite the buffer end */
memcpy(buf, biomem->data, size);
- buf[size]=0;
+ buf[size] = 0;
BIO_free(bio_out);
@@ -732,8 +904,12 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
-int Curl_ossl_init(void)
+static int Curl_ossl_init(void)
{
+#ifdef ENABLE_SSLKEYLOGFILE
+ const char *keylog_file_name;
+#endif
+
OPENSSL_load_builtin_modules();
#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
@@ -770,11 +946,24 @@ int Curl_ossl_init(void)
OpenSSL_add_all_algorithms();
#endif
+#ifdef ENABLE_SSLKEYLOGFILE
+ keylog_file_name = curl_getenv("SSLKEYLOGFILE");
+ if(keylog_file_name && !keylog_file_fp) {
+ keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
+ if(keylog_file_fp) {
+ if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) {
+ fclose(keylog_file_fp);
+ keylog_file_fp = NULL;
+ }
+ }
+ }
+#endif
+
return 1;
}
/* Global cleanup */
-void Curl_ossl_cleanup(void)
+static void Curl_ossl_cleanup(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
!defined(LIBRESSL_VERSION_NUMBER)
@@ -806,6 +995,13 @@ void Curl_ossl_cleanup(void)
SSL_COMP_free_compression_methods();
#endif
#endif
+
+#ifdef ENABLE_SSLKEYLOGFILE
+ if(keylog_file_fp) {
+ fclose(keylog_file_fp);
+ keylog_file_fp = NULL;
+ }
+#endif
}
/*
@@ -816,7 +1012,7 @@ void Curl_ossl_cleanup(void)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-int Curl_ossl_check_cxn(struct connectdata *conn)
+static int Curl_ossl_check_cxn(struct connectdata *conn)
{
/* SSL_peek takes data out of the raw recv buffer without peeking so we use
recv MSG_PEEK instead. Bug #795 */
@@ -862,7 +1058,8 @@ int Curl_ossl_check_cxn(struct connectdata *conn)
/* Selects an OpenSSL crypto engine
*/
-CURLcode Curl_ossl_set_engine(struct Curl_easy *data, const char *engine)
+static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
+ const char *engine)
{
#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
ENGINE *e;
@@ -907,7 +1104,7 @@ CURLcode Curl_ossl_set_engine(struct Curl_easy *data, const char *engine)
/* Sets engine as default for all SSL operations
*/
-CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
+static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
{
#ifdef HAVE_OPENSSL_ENGINE_H
if(data->state.engine) {
@@ -929,7 +1126,7 @@ CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
/* Return list of OpenSSL crypto engine names.
*/
-struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
+static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
{
struct curl_slist *list = NULL;
#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
@@ -952,23 +1149,23 @@ struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
static void ossl_close(struct ssl_connect_data *connssl)
{
- if(connssl->handle) {
- (void)SSL_shutdown(connssl->handle);
- SSL_set_connect_state(connssl->handle);
+ if(BACKEND->handle) {
+ (void)SSL_shutdown(BACKEND->handle);
+ SSL_set_connect_state(BACKEND->handle);
- SSL_free(connssl->handle);
- connssl->handle = NULL;
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
}
- if(connssl->ctx) {
- SSL_CTX_free(connssl->ctx);
- connssl->ctx = NULL;
+ if(BACKEND->ctx) {
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = NULL;
}
}
/*
* This function is called when an SSL connection is closed.
*/
-void Curl_ossl_close(struct connectdata *conn, int sockindex)
+static void Curl_ossl_close(struct connectdata *conn, int sockindex)
{
ossl_close(&conn->ssl[sockindex]);
ossl_close(&conn->proxy_ssl[sockindex]);
@@ -978,7 +1175,7 @@ void Curl_ossl_close(struct connectdata *conn, int sockindex)
* 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)
+static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -997,9 +1194,9 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
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);
+ (void)SSL_shutdown(BACKEND->handle);
- if(connssl->handle) {
+ if(BACKEND->handle) {
buffsize = (int)sizeof(buf);
while(!done) {
int what = SOCKET_READABLE(conn->sock[sockindex],
@@ -1009,9 +1206,8 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
/* 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);
+ nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize);
+ err = SSL_get_error(BACKEND->handle, (int)nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
@@ -1056,7 +1252,7 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
if(data->set.verbose) {
#ifdef HAVE_SSL_GET_SHUTDOWN
- switch(SSL_get_shutdown(connssl->handle)) {
+ switch(SSL_get_shutdown(BACKEND->handle)) {
case SSL_SENT_SHUTDOWN:
infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
break;
@@ -1071,13 +1267,13 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
#endif
}
- SSL_free(connssl->handle);
- connssl->handle = NULL;
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
}
return retval;
}
-void Curl_ossl_session_free(void *ptr)
+static void Curl_ossl_session_free(void *ptr)
{
/* free the ID */
SSL_SESSION_free(ptr);
@@ -1087,7 +1283,7 @@ void Curl_ossl_session_free(void *ptr)
* This function is called when the 'data' struct is going away. Close
* down everything and free all resources!
*/
-void Curl_ossl_close_all(struct Curl_easy *data)
+static void Curl_ossl_close_all(struct Curl_easy *data)
{
#ifdef HAVE_OPENSSL_ENGINE_H
if(data->state.engine) {
@@ -1179,7 +1375,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
numalts = sk_GENERAL_NAME_num(altnames);
/* loop through all alternatives - until a dnsmatch */
- for(i=0; (i < numalts) && !dnsmatched; i++) {
+ for(i = 0; (i < numalts) && !dnsmatched; i++) {
/* get a handle to alternative name number i */
const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
@@ -1248,7 +1444,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
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;
+ int j, i = -1;
/* The following is done because of a bug in 0.9.6b */
@@ -1257,14 +1453,14 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
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;
+ 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) {
+ if(i >= 0) {
ASN1_STRING *tmp =
X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
@@ -1277,7 +1473,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
j = ASN1_STRING_length(tmp);
if(j >= 0) {
- peer_CN = OPENSSL_malloc(j+1);
+ peer_CN = OPENSSL_malloc(j + 1);
if(peer_CN) {
memcpy(peer_CN, ASN1_STRING_get0_data(tmp), j);
peer_CN[j] = '\0';
@@ -1300,7 +1496,8 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
peer_CN = NULL;
else {
/* convert peer_CN from UTF8 */
- CURLcode rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN));
+ CURLcode rc = Curl_convert_from_utf8(data, (char *)peer_CN,
+ strlen((char *)peer_CN));
/* Curl_convert_from_utf8 calls failf if unsuccessful */
if(rc) {
OPENSSL_free(peer_CN);
@@ -1346,7 +1543,7 @@ static CURLcode verifystatus(struct connectdata *conn,
X509_STORE *st = NULL;
STACK_OF(X509) *ch = NULL;
- long len = SSL_get_tlsext_status_ocsp_resp(connssl->handle, &p);
+ long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &p);
if(!p) {
failf(data, "No OCSP response received");
@@ -1376,8 +1573,8 @@ static CURLcode verifystatus(struct connectdata *conn,
goto end;
}
- ch = SSL_get_peer_cert_chain(connssl->handle);
- st = SSL_CTX_get_cert_store(connssl->ctx);
+ ch = SSL_get_peer_cert_chain(BACKEND->handle);
+ st = SSL_CTX_get_cert_store(BACKEND->ctx);
#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
(defined(LIBRESSL_VERSION_NUMBER) && \
@@ -1768,7 +1965,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
#ifdef TLS1_3_VERSION
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
+ SSL_CTX_set_max_proto_version(BACKEND->ctx, TLS1_3_VERSION);
*ctx_options |= SSL_OP_NO_TLSv1_2;
}
#else
@@ -1919,25 +2116,25 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
}
- if(connssl->ctx)
- SSL_CTX_free(connssl->ctx);
- connssl->ctx = SSL_CTX_new(req_method);
+ if(BACKEND->ctx)
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = SSL_CTX_new(req_method);
- if(!connssl->ctx) {
+ if(!BACKEND->ctx) {
failf(data, "SSL: couldn't create a context: %s",
ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
return CURLE_OUT_OF_MEMORY;
}
#ifdef SSL_MODE_RELEASE_BUFFERS
- SSL_CTX_set_mode(connssl->ctx, SSL_MODE_RELEASE_BUFFERS);
+ SSL_CTX_set_mode(BACKEND->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 */
- SSL_CTX_set_msg_callback(connssl->ctx, ssl_tls_trace);
- SSL_CTX_set_msg_callback_arg(connssl->ctx, conn);
+ SSL_CTX_set_msg_callback(BACKEND->ctx, ssl_tls_trace);
+ SSL_CTX_set_msg_callback_arg(BACKEND->ctx, conn);
}
#endif
@@ -2054,11 +2251,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
}
- SSL_CTX_set_options(connssl->ctx, ctx_options);
+ SSL_CTX_set_options(BACKEND->ctx, ctx_options);
#ifdef HAS_NPN
if(conn->bits.tls_enable_npn)
- SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, conn);
+ SSL_CTX_set_next_proto_select_cb(BACKEND->ctx, select_next_proto_cb, conn);
#endif
#ifdef HAS_ALPN
@@ -2086,12 +2283,12 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* expects length prefixed preference ordered list of protocols in wire
* format
*/
- SSL_CTX_set_alpn_protos(connssl->ctx, protocols, cur);
+ SSL_CTX_set_alpn_protos(BACKEND->ctx, protocols, cur);
}
#endif
if(ssl_cert || ssl_cert_type) {
- if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type,
+ if(!cert_stuff(conn, BACKEND->ctx, ssl_cert, ssl_cert_type,
SSL_SET_OPTION(key), SSL_SET_OPTION(key_type),
SSL_SET_OPTION(key_passwd))) {
/* failf() is already done in cert_stuff() */
@@ -2102,11 +2299,13 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
ciphers = SSL_CONN_CONFIG(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;
+ if(ciphers) {
+ if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
+ failf(data, "failed setting cipher list: %s", ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+ infof(data, "Cipher selection: %s\n", ciphers);
}
- infof(data, "Cipher selection: %s\n", ciphers);
#ifdef USE_TLS_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP) {
@@ -2114,18 +2313,18 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
infof(data, "Using TLS-SRP username: %s\n", ssl_username);
- if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) {
+ if(!SSL_CTX_set_srp_username(BACKEND->ctx, ssl_username)) {
failf(data, "Unable to set SRP user name");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) {
+ if(!SSL_CTX_set_srp_password(BACKEND->ctx, SSL_SET_OPTION(password))) {
failf(data, "failed setting SRP password");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
if(!SSL_CONN_CONFIG(cipher_list)) {
infof(data, "Setting cipher list SRP\n");
- if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
+ if(!SSL_CTX_set_cipher_list(BACKEND->ctx, "SRP")) {
failf(data, "failed setting SRP cipher list");
return CURLE_SSL_CIPHER;
}
@@ -2136,7 +2335,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(ssl_cafile || 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, ssl_cafile, ssl_capath)) {
+ if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) {
if(verifypeer) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:\n"
@@ -2164,14 +2363,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
else if(verifypeer) {
/* verfying the peer without any CA certificates won't
work so use openssl's built in default as fallback */
- SSL_CTX_set_default_verify_paths(connssl->ctx);
+ SSL_CTX_set_default_verify_paths(BACKEND->ctx);
}
#endif
if(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),
+ lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(BACKEND->ctx),
X509_LOOKUP_file());
if(!lookup ||
(!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
@@ -2180,7 +2379,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
}
/* Everything is fine. */
infof(data, "successfully load CRL file:\n");
- X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
+ X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx),
X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
infof(data, " CRLfile: %s\n", ssl_crlfile);
@@ -2195,7 +2394,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
*/
#if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
if(verifypeer) {
- X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
+ X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx),
X509_V_FLAG_TRUSTED_FIRST);
}
#endif
@@ -2204,12 +2403,19 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
* 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,
+ SSL_CTX_set_verify(BACKEND->ctx,
verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
+ /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */
+#if defined(ENABLE_SSLKEYLOGFILE) && defined(HAVE_KEYLOG_CALLBACK)
+ if(keylog_file) {
+ SSL_CTX_set_keylog_callback(connssl->ctx, ossl_keylog_callback);
+ }
+#endif
+
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
- result = (*data->set.ssl.fsslctx)(data, connssl->ctx,
+ result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
data->set.ssl.fsslctxp);
if(result) {
failf(data, "error signaled by ssl ctx callback");
@@ -2218,10 +2424,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
}
/* Lets make an SSL structure */
- if(connssl->handle)
- SSL_free(connssl->handle);
- connssl->handle = SSL_new(connssl->ctx);
- if(!connssl->handle) {
+ if(BACKEND->handle)
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = SSL_new(BACKEND->ctx);
+ if(!BACKEND->handle) {
failf(data, "SSL: couldn't create a context (handle)!");
return CURLE_OUT_OF_MEMORY;
}
@@ -2229,19 +2435,19 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
if(SSL_CONN_CONFIG(verifystatus))
- SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
+ SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp);
#endif
- SSL_set_connect_state(connssl->handle);
+ SSL_set_connect_state(BACKEND->handle);
- connssl->server_cert = 0x0;
+ BACKEND->server_cert = 0x0;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
#ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
#endif
sni &&
- !SSL_set_tlsext_host_name(connssl->handle, hostname))
+ !SSL_set_tlsext_host_name(BACKEND->handle, hostname))
infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n");
#endif
@@ -2253,7 +2459,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
- if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
+ if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSL_set_session failed: %s",
ossl_strerror(ERR_get_error(), error_buffer,
@@ -2268,13 +2474,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(conn->proxy_ssl[sockindex].use) {
BIO *const bio = BIO_new(BIO_f_ssl());
+ SSL *handle = conn->proxy_ssl[sockindex].backend->handle;
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
- DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
+ DEBUGASSERT(handle != NULL);
DEBUGASSERT(bio != NULL);
- BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE);
- SSL_set_bio(connssl->handle, bio, bio);
+ BIO_set_ssl(bio, handle, FALSE);
+ SSL_set_bio(BACKEND->handle, bio, bio);
}
- else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+ else if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) {
/* pass the raw socket into the SSL layers */
failf(data, "SSL: SSL_set_fd failed: %s",
ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
@@ -2299,13 +2506,18 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
ERR_clear_error();
- err = SSL_connect(connssl->handle);
+ err = SSL_connect(BACKEND->handle);
+ /* If keylogging is enabled but the keylog callback is not supported then log
+ secrets here, immediately after SSL_connect by using tap_ssl_key. */
+#if defined(ENABLE_SSLKEYLOGFILE) && !defined(HAVE_KEYLOG_CALLBACK)
+ tap_ssl_key(BACKEND->handle, &BACKEND->tap_state);
+#endif
/* 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);
+ int detail = SSL_get_error(BACKEND->handle, err);
if(SSL_ERROR_WANT_READ == detail) {
connssl->connecting_state = ssl_connect_2_reading;
@@ -2339,7 +2551,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
(reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
result = CURLE_SSL_CACERT;
- lerr = SSL_get_verify_result(connssl->handle);
+ lerr = SSL_get_verify_result(BACKEND->handle);
if(lerr != X509_V_OK) {
*certverifyresult = lerr;
snprintf(error_buffer, sizeof(error_buffer),
@@ -2383,8 +2595,8 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
/* Informational message */
infof(data, "SSL connection using %s / %s\n",
- get_ssl_version_txt(connssl->handle),
- SSL_get_cipher(connssl->handle));
+ get_ssl_version_txt(BACKEND->handle),
+ SSL_get_cipher(BACKEND->handle));
#ifdef HAS_ALPN
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
@@ -2393,7 +2605,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
if(conn->bits.tls_enable_alpn) {
const unsigned char *neg_protocol;
unsigned int len;
- SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
+ SSL_get0_alpn_selected(BACKEND->handle, &neg_protocol, &len);
if(len != 0) {
infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
@@ -2438,7 +2650,7 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
do { \
long info_len = BIO_get_mem_data(mem, &ptr); \
Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
- if(1!=BIO_reset(mem)) \
+ if(1 != BIO_reset(mem)) \
break; \
} WHILE_FALSE
@@ -2486,12 +2698,12 @@ static int X509V3_ext(struct Curl_easy *data,
/* no extensions, bail out */
return 1;
- for(i=0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
+ for(i = 0; i < (int)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 *ptr = buf;
char namebuf[128];
BIO *bio_out = BIO_new(BIO_s_mem());
@@ -2508,16 +2720,16 @@ static int X509V3_ext(struct Curl_easy *data,
BIO_get_mem_ptr(bio_out, &biomem);
for(j = 0; j < (size_t)biomem->length; j++) {
- const char *sep="";
+ const char *sep = "";
if(biomem->data[j] == '\n') {
- sep=", ";
+ 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]);
+ ptr += snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
+ biomem->data[j]);
}
Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
@@ -2539,7 +2751,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
int numcerts;
BIO *mem;
- sk = SSL_get_peer_cert_chain(connssl->handle);
+ sk = SSL_get_peer_cert_chain(BACKEND->handle);
if(!sk) {
return CURLE_OUT_OF_MEMORY;
}
@@ -2556,7 +2768,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
for(i = 0; i < numcerts; i++) {
ASN1_INTEGER *num;
X509 *x = sk_X509_value(sk, i);
- EVP_PKEY *pubkey=NULL;
+ EVP_PKEY *pubkey = NULL;
int j;
char *ptr;
const ASN1_BIT_STRING *psig = NULL;
@@ -2829,8 +3041,8 @@ static CURLcode servercert(struct connectdata *conn,
/* 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) {
+ BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
+ if(!BACKEND->server_cert) {
BIO_free(mem);
if(!strict)
return CURLE_OK;
@@ -2841,16 +3053,16 @@ static CURLcode servercert(struct connectdata *conn,
infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
- rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
+ rc = x509_name_oneline(X509_get_subject_name(BACKEND->server_cert),
buffer, sizeof(buffer));
infof(data, " subject: %s\n", rc?"[NONE]":buffer);
- ASN1_TIME_print(mem, X509_get0_notBefore(connssl->server_cert));
+ ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert));
len = BIO_get_mem_data(mem, (char **) &ptr);
infof(data, " start date: %.*s\n", len, ptr);
rc = BIO_reset(mem);
- ASN1_TIME_print(mem, X509_get0_notAfter(connssl->server_cert));
+ ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert));
len = BIO_get_mem_data(mem, (char **) &ptr);
infof(data, " expire date: %.*s\n", len, ptr);
rc = BIO_reset(mem);
@@ -2858,15 +3070,15 @@ static CURLcode servercert(struct connectdata *conn,
BIO_free(mem);
if(SSL_CONN_CONFIG(verifyhost)) {
- result = verifyhost(conn, connssl->server_cert);
+ result = verifyhost(conn, BACKEND->server_cert);
if(result) {
- X509_free(connssl->server_cert);
- connssl->server_cert = NULL;
+ X509_free(BACKEND->server_cert);
+ BACKEND->server_cert = NULL;
return result;
}
}
- rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert),
+ rc = x509_name_oneline(X509_get_issuer_name(BACKEND->server_cert),
buffer, sizeof(buffer));
if(rc) {
if(strict)
@@ -2886,8 +3098,8 @@ static CURLcode servercert(struct connectdata *conn,
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(connssl->server_cert);
- connssl->server_cert = NULL;
+ X509_free(BACKEND->server_cert);
+ BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
@@ -2896,7 +3108,7 @@ static CURLcode servercert(struct connectdata *conn,
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(connssl->server_cert);
+ X509_free(BACKEND->server_cert);
X509_free(issuer);
fclose(fp);
return CURLE_SSL_ISSUER_ERROR;
@@ -2904,13 +3116,13 @@ static CURLcode servercert(struct connectdata *conn,
fclose(fp);
- if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
+ if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(connssl->server_cert);
+ X509_free(BACKEND->server_cert);
X509_free(issuer);
- connssl->server_cert = NULL;
+ BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
@@ -2919,7 +3131,7 @@ static CURLcode servercert(struct connectdata *conn,
X509_free(issuer);
}
- lerr = *certverifyresult = SSL_get_verify_result(connssl->handle);
+ lerr = *certverifyresult = SSL_get_verify_result(BACKEND->handle);
if(*certverifyresult != X509_V_OK) {
if(SSL_CONN_CONFIG(verifypeer)) {
@@ -2944,8 +3156,8 @@ static CURLcode servercert(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifystatus)) {
result = verifystatus(conn, connssl);
if(result) {
- X509_free(connssl->server_cert);
- connssl->server_cert = NULL;
+ X509_free(BACKEND->server_cert);
+ BACKEND->server_cert = NULL;
return result;
}
}
@@ -2958,13 +3170,13 @@ static CURLcode servercert(struct connectdata *conn,
ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
if(!result && ptr) {
- result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr);
+ result = pkp_pin_peer_pubkey(data, BACKEND->server_cert, ptr);
if(result)
failf(data, "SSL: public key does not match pinned public key!");
}
- X509_free(connssl->server_cert);
- connssl->server_cert = NULL;
+ X509_free(BACKEND->server_cert);
+ BACKEND->server_cert = NULL;
connssl->connecting_state = ssl_connect_done;
return result;
@@ -2983,7 +3195,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
- our_ssl_sessionid = SSL_get1_session(connssl->handle);
+ our_ssl_sessionid = SSL_get1_session(BACKEND->handle);
/* SSL_get1_session() will increment the reference count and the session
will stay in memory until explicitly freed with SSL_SESSION_free(3),
@@ -3088,9 +3300,9 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
if(connssl->connecting_state == ssl_connect_2_reading ||
connssl->connecting_state == ssl_connect_2_writing) {
- curl_socket_t writefd = 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==
+ curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -3148,14 +3360,14 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static 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)
+static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -3169,17 +3381,22 @@ CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex)
+static bool Curl_ossl_data_pending(const struct connectdata *conn,
+ int connindex)
{
- if(conn->ssl[connindex].handle)
+ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
+ const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
+ if(BACKEND->handle)
/* SSL is in use */
- return (0 != SSL_pending(conn->ssl[connindex].handle) ||
- (conn->proxy_ssl[connindex].handle &&
- 0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
+ return (0 != SSL_pending(BACKEND->handle) ||
+ (proxyssl->backend->handle &&
+ 0 != SSL_pending(proxyssl->backend->handle))) ?
TRUE : FALSE;
return FALSE;
}
+static size_t Curl_ossl_version(char *buffer, size_t size);
+
static ssize_t ossl_send(struct connectdata *conn,
int sockindex,
const void *mem,
@@ -3193,14 +3410,15 @@ static ssize_t ossl_send(struct connectdata *conn,
unsigned long sslerror;
int memlen;
int rc;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
ERR_clear_error();
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
- rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+ rc = SSL_write(BACKEND->handle, mem, memlen);
if(rc <= 0) {
- err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+ err = SSL_get_error(BACKEND->handle, rc);
switch(err) {
case SSL_ERROR_WANT_READ:
@@ -3254,14 +3472,15 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
unsigned long sslerror;
ssize_t nread;
int buffsize;
+ struct ssl_connect_data *connssl = &conn->ssl[num];
ERR_clear_error();
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
- nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
+ nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize);
if(nread <= 0) {
/* failed SSL_read */
- int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
+ int err = SSL_get_error(BACKEND->handle, (int)nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
@@ -3293,7 +3512,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
return nread;
}
-size_t Curl_ossl_version(char *buffer, size_t size)
+static size_t Curl_ossl_version(char *buffer, size_t size)
{
#ifdef OPENSSL_IS_BORINGSSL
return snprintf(buffer, size, OSSL_PACKAGE);
@@ -3302,9 +3521,9 @@ size_t Curl_ossl_version(char *buffer, size_t size)
unsigned long ssleay_value;
sub[2]='\0';
sub[1]='\0';
- ssleay_value=OpenSSL_version_num();
+ ssleay_value = OpenSSL_version_num();
if(ssleay_value < 0x906000) {
- ssleay_value=SSLEAY_VERSION_NUMBER;
+ ssleay_value = SSLEAY_VERSION_NUMBER;
sub[0]='\0';
}
else {
@@ -3333,8 +3552,8 @@ size_t Curl_ossl_version(char *buffer, size_t size)
}
/* can be called with data == NULL */
-CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length)
+static CURLcode Curl_ossl_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
int rc;
if(data) {
@@ -3350,23 +3569,24 @@ CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
}
-void Curl_ossl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum /* output */,
- size_t unused)
+static CURLcode 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);
+ return CURLE_OK;
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
+static void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
{
SHA256_CTX SHA256pw;
(void)unused;
@@ -3376,7 +3596,7 @@ void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
}
#endif
-bool Curl_ossl_cert_status_request(void)
+static bool Curl_ossl_cert_status_request(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
@@ -3385,4 +3605,50 @@ bool Curl_ossl_cert_status_request(void)
return FALSE;
#endif
}
+
+static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info)
+{
+ /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
+ return info == CURLINFO_TLS_SESSION ?
+ (void *)BACKEND->ctx : (void *)BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_openssl = {
+ { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
+
+ 1, /* have_ca_path */
+ 1, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 1, /* have_ssl_ctx */
+ 1, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_ossl_init, /* init */
+ Curl_ossl_cleanup, /* cleanup */
+ Curl_ossl_version, /* version */
+ Curl_ossl_check_cxn, /* check_cxn */
+ Curl_ossl_shutdown, /* shutdown */
+ Curl_ossl_data_pending, /* data_pending */
+ Curl_ossl_random, /* random */
+ Curl_ossl_cert_status_request, /* cert_status_request */
+ Curl_ossl_connect, /* connect */
+ Curl_ossl_connect_nonblocking, /* connect_nonblocking */
+ Curl_ossl_get_internals, /* get_internals */
+ Curl_ossl_close, /* close */
+ Curl_ossl_close_all, /* close_all */
+ Curl_ossl_session_free, /* session_free */
+ Curl_ossl_set_engine, /* set_engine */
+ Curl_ossl_set_engine_default, /* set_engine_default */
+ Curl_ossl_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_ossl_md5sum, /* md5sum */
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
+ Curl_ossl_sha256sum /* sha256sum */
+#else
+ NULL /* sha256sum */
+#endif
+};
+
#endif /* USE_OPENSSL */
diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h
index b9648d514..114dc4bae 100644
--- a/lib/vtls/openssl.h
+++ b/lib/vtls/openssl.h
@@ -31,96 +31,7 @@
#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) */
-void Curl_ossl_close_all(struct Curl_easy *data);
-
-/* Sets an OpenSSL engine */
-CURLcode Curl_ossl_set_engine(struct Curl_easy *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 Curl_easy *data);
-
-/* Build list of OpenSSL engines */
-struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *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 */
-CURLcode Curl_ossl_random(struct Curl_easy *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);
-void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused);
-
-bool Curl_ossl_cert_status_request(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to OpenSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 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)
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-#define curlssl_sha256sum(a,b,c,d) Curl_ossl_sha256sum(a,b,c,d)
-#endif
-#define curlssl_cert_status_request() Curl_ossl_cert_status_request()
-
-#define DEFAULT_CIPHER_SELECTION \
- "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
+extern const struct Curl_ssl Curl_ssl_openssl;
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index 669091cb5..fc0644f89 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -30,7 +30,6 @@
#include "curl_setup.h"
#ifdef USE_POLARSSL
-
#include <polarssl/net.h>
#include <polarssl/ssl.h>
#include <polarssl/certs.h>
@@ -70,6 +69,19 @@
#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
+struct ssl_backend_data {
+ ctr_drbg_context ctr_drbg;
+ entropy_context entropy;
+ ssl_context ssl;
+ int server_fd;
+ x509_crt cacert;
+ x509_crt clicert;
+ x509_crl crl;
+ rsa_context rsa;
+};
+
+#define BACKEND connssl->backend
+
/* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
#define THREADING_SUPPORT
@@ -197,8 +209,8 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
return result;
}
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
+ ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
+ ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
return result;
}
@@ -215,7 +227,7 @@ polarssl_connect_step1(struct connectdata *conn,
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
int ret = -1;
char errorbuf[128];
- errorbuf[0]=0;
+ errorbuf[0] = 0;
/* PolarSSL only supports SSLv3 and TLSv1 */
if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
@@ -226,16 +238,16 @@ polarssl_connect_step1(struct connectdata *conn,
#ifdef THREADING_SUPPORT
entropy_init_mutex(&entropy);
- if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
+ if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy,
NULL, 0)) != 0) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
-ret, errorbuf);
}
#else
- entropy_init(&connssl->entropy);
+ entropy_init(&BACKEND->entropy);
- if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
+ if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy,
NULL, 0)) != 0) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
@@ -244,10 +256,10 @@ polarssl_connect_step1(struct connectdata *conn,
#endif /* THREADING_SUPPORT */
/* Load the trusted CA */
- memset(&connssl->cacert, 0, sizeof(x509_crt));
+ memset(&BACKEND->cacert, 0, sizeof(x509_crt));
if(SSL_CONN_CONFIG(CAfile)) {
- ret = x509_crt_parse_file(&connssl->cacert,
+ ret = x509_crt_parse_file(&BACKEND->cacert,
SSL_CONN_CONFIG(CAfile));
if(ret<0) {
@@ -261,7 +273,7 @@ polarssl_connect_step1(struct connectdata *conn,
}
if(capath) {
- ret = x509_crt_parse_path(&connssl->cacert, capath);
+ ret = x509_crt_parse_path(&BACKEND->cacert, capath);
if(ret<0) {
error_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -274,10 +286,10 @@ polarssl_connect_step1(struct connectdata *conn,
}
/* Load the client certificate */
- memset(&connssl->clicert, 0, sizeof(x509_crt));
+ memset(&BACKEND->clicert, 0, sizeof(x509_crt));
if(SSL_SET_OPTION(cert)) {
- ret = x509_crt_parse_file(&connssl->clicert,
+ ret = x509_crt_parse_file(&BACKEND->clicert,
SSL_SET_OPTION(cert));
if(ret) {
@@ -298,9 +310,9 @@ polarssl_connect_step1(struct connectdata *conn,
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));
+ rsa_copy(&BACKEND->rsa, pk_rsa(pk));
else
- rsa_free(&connssl->rsa);
+ rsa_free(&BACKEND->rsa);
pk_free(&pk);
if(ret) {
@@ -313,10 +325,10 @@ polarssl_connect_step1(struct connectdata *conn,
}
/* Load the CRL */
- memset(&connssl->crl, 0, sizeof(x509_crl));
+ memset(&BACKEND->crl, 0, sizeof(x509_crl));
if(SSL_SET_OPTION(CRLfile)) {
- ret = x509_crl_parse_file(&connssl->crl,
+ ret = x509_crl_parse_file(&BACKEND->crl,
SSL_SET_OPTION(CRLfile));
if(ret) {
@@ -330,7 +342,7 @@ polarssl_connect_step1(struct connectdata *conn,
infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
- if(ssl_init(&connssl->ssl)) {
+ if(ssl_init(&BACKEND->ssl)) {
failf(data, "PolarSSL: ssl_init failed");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -338,13 +350,13 @@ polarssl_connect_step1(struct connectdata *conn,
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
SSL_MINOR_VERSION_1);
break;
case CURL_SSLVERSION_SSLv3:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
SSL_MINOR_VERSION_0);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+ ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
SSL_MINOR_VERSION_0);
infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
break;
@@ -363,16 +375,16 @@ polarssl_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
- ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
- ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
+ ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT);
+ ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL);
- ssl_set_rng(&connssl->ssl, ctr_drbg_random,
- &connssl->ctr_drbg);
- ssl_set_bio(&connssl->ssl,
+ ssl_set_rng(&BACKEND->ssl, ctr_drbg_random,
+ &BACKEND->ctr_drbg);
+ ssl_set_bio(&BACKEND->ssl,
net_recv, &conn->sock[sockindex],
net_send, &conn->sock[sockindex]);
- ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
+ ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites());
/* Check if there's a cached ID we can/should use here! */
if(SSL_SET_OPTION(primary.sessionid)) {
@@ -380,7 +392,7 @@ polarssl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
- ret = ssl_set_session(&connssl->ssl, old_session);
+ ret = ssl_set_session(&BACKEND->ssl, old_session);
if(ret) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "ssl_set_session returned -0x%x", -ret);
@@ -391,15 +403,15 @@ polarssl_connect_step1(struct connectdata *conn,
Curl_ssl_sessionid_unlock(conn);
}
- ssl_set_ca_chain(&connssl->ssl,
- &connssl->cacert,
- &connssl->crl,
+ ssl_set_ca_chain(&BACKEND->ssl,
+ &BACKEND->cacert,
+ &BACKEND->crl,
hostname);
- ssl_set_own_cert_rsa(&connssl->ssl,
- &connssl->clicert, &connssl->rsa);
+ ssl_set_own_cert_rsa(&BACKEND->ssl,
+ &BACKEND->clicert, &BACKEND->rsa);
- if(ssl_set_hostname(&connssl->ssl, hostname)) {
+ if(ssl_set_hostname(&BACKEND->ssl, hostname)) {
/* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
to set in the SNI extension. So even if curl connects to a host
specified as an IP address, this function must be used. */
@@ -424,12 +436,12 @@ polarssl_connect_step1(struct connectdata *conn,
protocols[cur] = NULL;
- ssl_set_alpn_protocols(&connssl->ssl, protocols);
+ ssl_set_alpn_protocols(&BACKEND->ssl, protocols);
}
#endif
#ifdef POLARSSL_DEBUG
- ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
+ ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data);
#endif
connssl->connecting_state = ssl_connect_2;
@@ -456,7 +468,7 @@ polarssl_connect_step2(struct connectdata *conn,
conn->recv[sockindex] = polarssl_recv;
conn->send[sockindex] = polarssl_send;
- ret = ssl_handshake(&connssl->ssl);
+ ret = ssl_handshake(&BACKEND->ssl);
switch(ret) {
case 0:
@@ -478,9 +490,9 @@ polarssl_connect_step2(struct connectdata *conn,
}
infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
- ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) );
+ ssl_get_ciphersuite(&BACKEND->ssl) );
- ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+ ret = ssl_get_verify_result(&BACKEND->ssl);
if(ret && SSL_CONN_CONFIG(verifypeer)) {
if(ret & BADCERT_EXPIRED)
@@ -500,12 +512,12 @@ polarssl_connect_step2(struct connectdata *conn,
return CURLE_PEER_FAILED_VERIFICATION;
}
- if(ssl_get_peer_cert(&(connssl->ssl))) {
+ if(ssl_get_peer_cert(&(BACKEND->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)
+ ssl_get_peer_cert(&(BACKEND->ssl))) != -1)
infof(data, "Dumping cert info:\n%s\n", buffer);
}
@@ -517,7 +529,7 @@ polarssl_connect_step2(struct connectdata *conn,
unsigned char pubkey[PUB_DER_MAX_BYTES];
const x509_crt *peercert;
- peercert = ssl_get_peer_cert(&connssl->ssl);
+ peercert = ssl_get_peer_cert(&BACKEND->ssl);
if(!peercert || !peercert->raw.p || !peercert->raw.len) {
failf(data, "Failed due to missing peer certificate");
@@ -566,7 +578,7 @@ polarssl_connect_step2(struct connectdata *conn,
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
- const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl);
+ const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl);
if(next_protocol != NULL) {
infof(data, "ALPN, server accepted to use %s\n", next_protocol);
@@ -614,7 +626,7 @@ polarssl_connect_step3(struct connectdata *conn,
memset(our_ssl_sessionid, 0, sizeof(ssl_session));
- ret = ssl_get_session(&connssl->ssl, our_ssl_sessionid);
+ ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
if(ret) {
failf(data, "ssl_get_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
@@ -645,9 +657,10 @@ static ssize_t polarssl_send(struct connectdata *conn,
size_t len,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
int ret = -1;
- ret = ssl_write(&conn->ssl[sockindex].ssl,
+ ret = ssl_write(&BACKEND->ssl,
(unsigned char *)mem, len);
if(ret < 0) {
@@ -659,13 +672,14 @@ static ssize_t polarssl_send(struct connectdata *conn,
return ret;
}
-void Curl_polarssl_close(struct connectdata *conn, int sockindex)
+static 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);
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ rsa_free(&BACKEND->rsa);
+ x509_crt_free(&BACKEND->clicert);
+ x509_crt_free(&BACKEND->cacert);
+ x509_crl_free(&BACKEND->crl);
+ ssl_free(&BACKEND->ssl);
}
static ssize_t polarssl_recv(struct connectdata *conn,
@@ -674,11 +688,12 @@ static ssize_t polarssl_recv(struct connectdata *conn,
size_t buffersize,
CURLcode *curlcode)
{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
int ret = -1;
ssize_t len = -1;
memset(buf, 0, buffersize);
- ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
+ ret = ssl_read(&BACKEND->ssl, (unsigned char *)buf, buffersize);
if(ret <= 0) {
if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
@@ -694,7 +709,7 @@ static ssize_t polarssl_recv(struct connectdata *conn,
return len;
}
-void Curl_polarssl_session_free(void *ptr)
+static void Curl_polarssl_session_free(void *ptr)
{
ssl_session_free(ptr);
free(ptr);
@@ -703,7 +718,7 @@ void Curl_polarssl_session_free(void *ptr)
/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
higher) will be mbed TLS branded.. */
-size_t Curl_polarssl_version(char *buffer, size_t size)
+static size_t Curl_polarssl_version(char *buffer, size_t size)
{
unsigned int version = version_get_number();
return snprintf(buffer, size, "%s/%d.%d.%d",
@@ -762,9 +777,9 @@ polarssl_connect_common(struct connectdata *conn,
if(connssl->connecting_state == ssl_connect_2_reading ||
connssl->connecting_state == ssl_connect_2_writing) {
- curl_socket_t writefd = 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==
+ curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -825,18 +840,14 @@ polarssl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-CURLcode
-Curl_polarssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static 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)
+static CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -854,20 +865,73 @@ Curl_polarssl_connect(struct connectdata *conn,
* return 0 error initializing SSL
* return 1 SSL initialized successfully
*/
-int Curl_polarssl_init(void)
+static int Curl_polarssl_init(void)
{
return Curl_polarsslthreadlock_thread_setup();
}
-void Curl_polarssl_cleanup(void)
+static void Curl_polarssl_cleanup(void)
{
(void)Curl_polarsslthreadlock_thread_cleanup();
}
+static bool Curl_polarssl_data_pending(const struct connectdata *conn,
+ int sockindex)
+{
+ const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ return ssl_get_bytes_avail(&BACKEND->ssl) != 0;
+}
+
+static void Curl_polarssl_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
+{
+ (void)sha256len;
+ sha256(input, inputlen, sha256sum, 0);
+}
-int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex)
+static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
- return ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
+ (void)info;
+ return &BACKEND->ssl;
}
+const struct Curl_ssl Curl_ssl_polarssl = {
+ { CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
+
+ 1, /* have_ca_path */
+ 0, /* have_certinfo */
+ 1, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_polarssl_init, /* init */
+ Curl_polarssl_cleanup, /* cleanup */
+ Curl_polarssl_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_none_shutdown, /* shutdown */
+ Curl_polarssl_data_pending, /* data_pending */
+ /* This might cause libcurl to use a weeker random!
+ * TODO: use Polarssl's CTR-DRBG or HMAC-DRBG
+ */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_polarssl_connect, /* connect */
+ Curl_polarssl_connect_nonblocking, /* connect_nonblocking */
+ Curl_polarssl_get_internals, /* get_internals */
+ Curl_polarssl_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_polarssl_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ Curl_polarssl_sha256sum /* sha256sum */
+};
+
#endif /* USE_POLARSSL */
diff --git a/lib/vtls/polarssl.h b/lib/vtls/polarssl.h
index 47af7b417..23c3636ee 100644
--- a/lib/vtls/polarssl.h
+++ b/lib/vtls/polarssl.h
@@ -26,57 +26,7 @@
#ifdef USE_POLARSSL
-#include <polarssl/sha256.h>
-
-/* Called on first use PolarSSL, setup threading if supported */
-int Curl_polarssl_init(void);
-void Curl_polarssl_cleanup(void);
-int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex);
-
-
-CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done);
-
- /* 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);
-
-/* Set the API backend definition to PolarSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for PolarSSL */
-#define curlssl_init() Curl_polarssl_init()
-#define curlssl_cleanup() Curl_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(x) ((void)x)
-#define curlssl_close Curl_polarssl_close
-#define curlssl_shutdown(x,y) 0
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_polarssl_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) Curl_polarssl_data_pending(x, y)
-#define curlssl_sha256sum(a,b,c,d) sha256(a,b,c,0)
-
-/* 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) ((void)x, (void)y, (void)z, CURLE_NOT_BUILT_IN)
+extern const struct Curl_ssl Curl_ssl_polarssl;
#endif /* USE_POLARSSL */
#endif /* HEADER_CURL_POLARSSL_H */
diff --git a/lib/vtls/polarssl_threadlock.c b/lib/vtls/polarssl_threadlock.c
index b1eb7b746..dd5fbd7ec 100644
--- a/lib/vtls/polarssl_threadlock.c
+++ b/lib/vtls/polarssl_threadlock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013-2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013-2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -114,7 +114,7 @@ int Curl_polarsslthreadlock_lock_function(int n)
}
#elif defined(HAVE_PROCESS_H)
if(n < NUMT) {
- ret = (WaitForSingleObject(mutex_buf[n], INFINITE)==WAIT_FAILED?1:0);
+ ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0);
if(ret) {
DEBUGF(fprintf(stderr,
"Error: polarsslthreadlock_lock_function failed\n"));
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 94603018b..9ca1431bd 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -46,6 +46,8 @@
# error "Can't compile SCHANNEL support without SSPI."
#endif
+#include <schnlsp.h>
+#include <schannel.h>
#include "curl_sspi.h"
#include "schannel.h"
#include "vtls.h"
@@ -74,11 +76,92 @@
# define HAS_ALPN 1
#endif
+#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
+
+/* Both schannel buffer sizes must be > 0 */
+#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
+#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
+
/* Uncomment to force verbose output
* #define infof(x, y, ...) printf(y, __VA_ARGS__)
* #define failf(x, y, ...) printf(y, __VA_ARGS__)
*/
+/* Structs to store Schannel handles */
+struct curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ int refcount;
+};
+
+struct curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+
+struct ssl_backend_data {
+ struct curl_schannel_cred *cred;
+ struct curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another Curl_read_plain (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
+ unsigned long req_flags, ret_flags;
+ CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+ bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+ bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool use_alpn; /* true if ALPN is used for this connection */
+};
+
+#define BACKEND connssl->backend
+
static Curl_recv schannel_recv;
static Curl_send schannel_send;
@@ -176,33 +259,33 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_ALPN
/* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
Also it doesn't seem to be supported for Wine, see curl bug #983. */
- connssl->use_alpn = conn->bits.tls_enable_alpn &&
+ BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
!GetProcAddress(GetModuleHandleA("ntdll"),
"wine_get_version") &&
Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL);
#else
- connssl->use_alpn = false;
+ BACKEND->use_alpn = false;
#endif
- connssl->cred = NULL;
+ BACKEND->cred = NULL;
/* check for an existing re-usable credential handle */
if(SSL_SET_OPTION(primary.sessionid)) {
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
- connssl->cred = old_cred;
+ BACKEND->cred = old_cred;
infof(data, "schannel: re-using existing credential handle\n");
/* increment the reference counter of the credential/session handle */
- connssl->cred->refcount++;
+ BACKEND->cred->refcount++;
infof(data, "schannel: incremented credential handle refcount = %d\n",
- connssl->cred->refcount);
+ BACKEND->cred->refcount);
}
Curl_ssl_sessionid_unlock(conn);
}
- if(!connssl->cred) {
+ if(!BACKEND->cred) {
/* setup Schannel API options */
memset(&schannel_cred, 0, sizeof(schannel_cred));
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
@@ -272,14 +355,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
/* allocate memory for the re-usable credential handle */
- connssl->cred = (struct curl_schannel_cred *)
+ BACKEND->cred = (struct curl_schannel_cred *)
malloc(sizeof(struct curl_schannel_cred));
- if(!connssl->cred) {
+ if(!BACKEND->cred) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
- memset(connssl->cred, 0, sizeof(struct curl_schannel_cred));
- connssl->cred->refcount = 1;
+ memset(BACKEND->cred, 0, sizeof(struct curl_schannel_cred));
+ BACKEND->cred->refcount = 1;
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
*/
@@ -287,8 +370,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
SECPKG_CRED_OUTBOUND, NULL,
&schannel_cred, NULL, NULL,
- &connssl->cred->cred_handle,
- &connssl->cred->time_stamp);
+ &BACKEND->cred->cred_handle,
+ &BACKEND->cred->time_stamp);
if(sspi_status != SEC_E_OK) {
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
@@ -297,7 +380,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
else
failf(data, "schannel: AcquireCredentialsHandle failed: %s",
Curl_sspi_strerror(conn, sspi_status));
- Curl_safefree(connssl->cred);
+ Curl_safefree(BACKEND->cred);
return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -312,7 +395,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
#ifdef HAS_ALPN
- if(connssl->use_alpn) {
+ if(BACKEND->use_alpn) {
int cur = 0;
int list_start_index = 0;
unsigned int *extension_len = NULL;
@@ -370,18 +453,18 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
/* setup request flags */
- connssl->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
+ BACKEND->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 *)
+ BACKEND->ctxt = (struct curl_schannel_ctxt *)
malloc(sizeof(struct curl_schannel_ctxt));
- if(!connssl->ctxt) {
+ if(!BACKEND->ctxt) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
- memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
+ memset(BACKEND->ctxt, 0, sizeof(struct curl_schannel_ctxt));
host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
@@ -395,10 +478,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
us problems with inbuf regardless. https://github.com/curl/curl/issues/983
*/
sspi_status = s_pSecFn->InitializeSecurityContext(
- &connssl->cred->cred_handle, NULL, host_name, connssl->req_flags, 0, 0,
- (connssl->use_alpn ? &inbuf_desc : NULL),
- 0, &connssl->ctxt->ctxt_handle,
- &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+ &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0,
+ (BACKEND->use_alpn ? &inbuf_desc : NULL),
+ 0, &BACKEND->ctxt->ctxt_handle,
+ &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name);
@@ -409,7 +492,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
else
failf(data, "schannel: initial InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
- Curl_safefree(connssl->ctxt);
+ Curl_safefree(BACKEND->ctxt);
return CURLE_SSL_CONNECT_ERROR;
}
@@ -429,10 +512,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
infof(data, "schannel: sent initial handshake data: "
"sent %zd bytes\n", written);
- connssl->recv_unrecoverable_err = CURLE_OK;
- connssl->recv_sspi_close_notify = false;
- connssl->recv_connection_closed = false;
- connssl->encdata_is_incomplete = false;
+ BACKEND->recv_unrecoverable_err = CURLE_OK;
+ BACKEND->recv_sspi_close_notify = false;
+ BACKEND->recv_connection_closed = false;
+ BACKEND->encdata_is_incomplete = false;
/* continue to second handshake step */
connssl->connecting_state = ssl_connect_2;
@@ -465,39 +548,39 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
hostname, conn->remote_port);
- if(!connssl->cred || !connssl->ctxt)
+ if(!BACKEND->cred || !BACKEND->ctxt)
return CURLE_SSL_CONNECT_ERROR;
/* 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) {
+ if(BACKEND->decdata_buffer == NULL) {
+ BACKEND->decdata_offset = 0;
+ BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+ BACKEND->decdata_buffer = malloc(BACKEND->decdata_length);
+ if(BACKEND->decdata_buffer == NULL) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
}
/* buffer to store previously received and encrypted data */
- if(connssl->encdata_buffer == NULL) {
- connssl->encdata_is_incomplete = false;
- connssl->encdata_offset = 0;
- connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
- connssl->encdata_buffer = malloc(connssl->encdata_length);
- if(connssl->encdata_buffer == NULL) {
+ if(BACKEND->encdata_buffer == NULL) {
+ BACKEND->encdata_is_incomplete = false;
+ BACKEND->encdata_offset = 0;
+ BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+ BACKEND->encdata_buffer = malloc(BACKEND->encdata_length);
+ if(BACKEND->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 <
+ if(BACKEND->encdata_length - BACKEND->encdata_offset <
CURL_SCHANNEL_BUFFER_FREE_SIZE) {
/* increase internal encrypted data buffer */
- reallocated_length = connssl->encdata_offset +
+ reallocated_length = BACKEND->encdata_offset +
CURL_SCHANNEL_BUFFER_FREE_SIZE;
- reallocated_buffer = realloc(connssl->encdata_buffer,
+ reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length);
if(reallocated_buffer == NULL) {
@@ -505,8 +588,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
return CURLE_OUT_OF_MEMORY;
}
else {
- connssl->encdata_buffer = reallocated_buffer;
- connssl->encdata_length = reallocated_length;
+ BACKEND->encdata_buffer = reallocated_buffer;
+ BACKEND->encdata_length = reallocated_length;
}
}
@@ -514,10 +597,10 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
if(doread) {
/* read encrypted handshake data from socket */
result = Curl_read_plain(conn->sock[sockindex],
- (char *) (connssl->encdata_buffer +
- connssl->encdata_offset),
- connssl->encdata_length -
- connssl->encdata_offset,
+ (char *) (BACKEND->encdata_buffer +
+ BACKEND->encdata_offset),
+ BACKEND->encdata_length -
+ BACKEND->encdata_offset,
&nread);
if(result == CURLE_AGAIN) {
if(connssl->connecting_state != ssl_connect_2_writing)
@@ -533,17 +616,17 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
}
/* increase encrypted data buffer offset */
- connssl->encdata_offset += nread;
- connssl->encdata_is_incomplete = false;
+ BACKEND->encdata_offset += nread;
+ BACKEND->encdata_is_incomplete = false;
infof(data, "schannel: encrypted data got %zd\n", nread);
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
/* setup input buffers */
- InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset),
- curlx_uztoul(connssl->encdata_offset));
+ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset),
+ curlx_uztoul(BACKEND->encdata_offset));
InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, inbuf, 2);
@@ -559,8 +642,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
}
/* copy received handshake data into input buffer */
- memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
- connssl->encdata_offset);
+ memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer,
+ BACKEND->encdata_offset);
host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
@@ -569,9 +652,9 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* https://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);
+ &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle,
+ host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL,
+ &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name);
@@ -580,7 +663,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* check if the handshake was incomplete */
if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
- connssl->encdata_is_incomplete = true;
+ BACKEND->encdata_is_incomplete = true;
connssl->connecting_state = ssl_connect_2_reading;
infof(data, "schannel: received incomplete message, need more data\n");
return CURLE_OK;
@@ -590,8 +673,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
the handshake without one. This will allow connections to servers which
request a client certificate but do not require it. */
if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS &&
- !(connssl->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
- connssl->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
+ !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
+ BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
connssl->connecting_state = ssl_connect_2_writing;
infof(data, "schannel: a client certificate has been requested\n");
return CURLE_OK;
@@ -631,7 +714,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
failf(data, "schannel: next InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
return sspi_status == SEC_E_UNTRUSTED_ROOT ?
- CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CONNECT_ERROR;
+ CURLE_SSL_CACERT : CURLE_SSL_CONNECT_ERROR;
}
/* check if there was additional remaining encrypted data */
@@ -649,11 +732,11 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
*/
/* 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) -
+ if(BACKEND->encdata_offset > inbuf[1].cbBuffer) {
+ memmove(BACKEND->encdata_buffer,
+ (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
inbuf[1].cbBuffer, inbuf[1].cbBuffer);
- connssl->encdata_offset = inbuf[1].cbBuffer;
+ BACKEND->encdata_offset = inbuf[1].cbBuffer;
if(sspi_status == SEC_I_CONTINUE_NEEDED) {
doread = FALSE;
continue;
@@ -661,7 +744,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
}
}
else {
- connssl->encdata_offset = 0;
+ BACKEND->encdata_offset = 0;
}
break;
}
@@ -709,27 +792,27 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
hostname, conn->remote_port);
- if(!connssl->cred)
+ if(!BACKEND->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))
+ if(BACKEND->ret_flags != BACKEND->req_flags) {
+ if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT))
failf(data, "schannel: failed to setup sequence detection");
- if(!(connssl->ret_flags & ISC_RET_REPLAY_DETECT))
+ if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT))
failf(data, "schannel: failed to setup replay detection");
- if(!(connssl->ret_flags & ISC_RET_CONFIDENTIALITY))
+ if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY))
failf(data, "schannel: failed to setup confidentiality");
- if(!(connssl->ret_flags & ISC_RET_ALLOCATED_MEMORY))
+ if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY))
failf(data, "schannel: failed to setup memory allocation");
- if(!(connssl->ret_flags & ISC_RET_STREAM))
+ if(!(BACKEND->ret_flags & ISC_RET_STREAM))
failf(data, "schannel: failed to setup stream orientation");
return CURLE_SSL_CONNECT_ERROR;
}
#ifdef HAS_ALPN
- if(connssl->use_alpn) {
- sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+ if(BACKEND->use_alpn) {
+ sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result);
if(sspi_status != SEC_E_OK) {
@@ -771,7 +854,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
sockindex));
if(incache) {
- if(old_cred != connssl->cred) {
+ if(old_cred != BACKEND->cred) {
infof(data, "schannel: old credential handle is stale, removing\n");
/* we're not taking old_cred ownership here, no refcount++ is needed */
Curl_ssl_delsessionid(conn, (void *)old_cred);
@@ -779,7 +862,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
+ result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred,
sizeof(struct curl_schannel_cred),
sockindex);
if(result) {
@@ -789,7 +872,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
else {
/* this cred session is now also referenced by sessionid cache */
- connssl->cred->refcount++;
+ BACKEND->cred->refcount++;
infof(data, "schannel: stored credential handle in session cache\n");
}
}
@@ -797,7 +880,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
if(data->set.ssl.certinfo) {
- sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+ sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
@@ -951,11 +1034,11 @@ schannel_send(struct connectdata *conn, int sockindex,
CURLcode result;
/* check if the maximum stream sizes were queried */
- if(connssl->stream_sizes.cbMaximumMessage == 0) {
+ if(BACKEND->stream_sizes.cbMaximumMessage == 0) {
sspi_status = s_pSecFn->QueryContextAttributes(
- &connssl->ctxt->ctxt_handle,
+ &BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_STREAM_SIZES,
- &connssl->stream_sizes);
+ &BACKEND->stream_sizes);
if(sspi_status != SEC_E_OK) {
*err = CURLE_SEND_ERROR;
return -1;
@@ -963,14 +1046,13 @@ schannel_send(struct connectdata *conn, int sockindex,
}
/* check if the buffer is longer than the maximum message length */
- if(len > connssl->stream_sizes.cbMaximumMessage) {
- *err = CURLE_SEND_ERROR;
- return -1;
+ if(len > BACKEND->stream_sizes.cbMaximumMessage) {
+ len = BACKEND->stream_sizes.cbMaximumMessage;
}
/* calculate the complete message length and allocate a buffer for it */
- data_len = connssl->stream_sizes.cbHeader + len +
- connssl->stream_sizes.cbTrailer;
+ data_len = BACKEND->stream_sizes.cbHeader + len +
+ BACKEND->stream_sizes.cbTrailer;
data = (unsigned char *) malloc(data_len);
if(data == NULL) {
*err = CURLE_OUT_OF_MEMORY;
@@ -979,12 +1061,12 @@ schannel_send(struct connectdata *conn, int sockindex,
/* setup output buffers (header, data, trailer, empty) */
InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
- data, connssl->stream_sizes.cbHeader);
+ data, BACKEND->stream_sizes.cbHeader);
InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
- data + connssl->stream_sizes.cbHeader, curlx_uztoul(len));
+ data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
- data + connssl->stream_sizes.cbHeader + len,
- connssl->stream_sizes.cbTrailer);
+ data + BACKEND->stream_sizes.cbHeader + len,
+ BACKEND->stream_sizes.cbTrailer);
InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 4);
@@ -992,7 +1074,7 @@ schannel_send(struct connectdata *conn, int sockindex,
memcpy(outbuf[1].pvBuffer, buf, len);
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */
- sspi_status = s_pSecFn->EncryptMessage(&connssl->ctxt->ctxt_handle, 0,
+ sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0,
&outbuf_desc, 0);
/* check if the message was encrypted */
@@ -1102,7 +1184,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
/****************************************************************************
- * Don't return or set connssl->recv_unrecoverable_err unless in the cleanup.
+ * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup.
* The pattern for return error is set *err, optional infof, goto cleanup.
*
* Our priority is to always return as much decrypted data to the caller as
@@ -1114,16 +1196,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: client wants to read %zu bytes\n", len);
*err = CURLE_OK;
- if(len && len <= connssl->decdata_offset) {
+ if(len && len <= BACKEND->decdata_offset) {
infof(data, "schannel: enough decrypted data is already available\n");
goto cleanup;
}
- else if(connssl->recv_unrecoverable_err) {
- *err = connssl->recv_unrecoverable_err;
+ else if(BACKEND->recv_unrecoverable_err) {
+ *err = BACKEND->recv_unrecoverable_err;
infof(data, "schannel: an unrecoverable error occurred in a prior call\n");
goto cleanup;
}
- else if(connssl->recv_sspi_close_notify) {
+ else if(BACKEND->recv_sspi_close_notify) {
/* once a server has indicated shutdown there is no more encrypted data */
infof(data, "schannel: server indicated shutdown in a prior call\n");
goto cleanup;
@@ -1135,17 +1217,17 @@ schannel_recv(struct connectdata *conn, int sockindex,
*/
; /* do nothing */
}
- else if(!connssl->recv_connection_closed) {
+ else if(!BACKEND->recv_connection_closed) {
/* increase enc buffer in order to fit the requested amount of data */
- size = connssl->encdata_length - connssl->encdata_offset;
+ size = BACKEND->encdata_length - BACKEND->encdata_offset;
if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
- connssl->encdata_length < min_encdata_length) {
- reallocated_length = connssl->encdata_offset +
+ BACKEND->encdata_length < min_encdata_length) {
+ reallocated_length = BACKEND->encdata_offset +
CURL_SCHANNEL_BUFFER_FREE_SIZE;
if(reallocated_length < min_encdata_length) {
reallocated_length = min_encdata_length;
}
- reallocated_buffer = realloc(connssl->encdata_buffer,
+ reallocated_buffer = realloc(BACKEND->encdata_buffer,
reallocated_length);
if(reallocated_buffer == NULL) {
*err = CURLE_OUT_OF_MEMORY;
@@ -1153,20 +1235,20 @@ schannel_recv(struct connectdata *conn, int sockindex,
goto cleanup;
}
- connssl->encdata_buffer = reallocated_buffer;
- connssl->encdata_length = reallocated_length;
- size = connssl->encdata_length - connssl->encdata_offset;
+ BACKEND->encdata_buffer = reallocated_buffer;
+ BACKEND->encdata_length = reallocated_length;
+ size = BACKEND->encdata_length - BACKEND->encdata_offset;
infof(data, "schannel: encdata_buffer resized %zu\n",
- connssl->encdata_length);
+ BACKEND->encdata_length);
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
/* read encrypted data from socket */
*err = Curl_read_plain(conn->sock[sockindex],
- (char *)(connssl->encdata_buffer +
- connssl->encdata_offset),
+ (char *)(BACKEND->encdata_buffer +
+ BACKEND->encdata_offset),
size, &nread);
if(*err) {
nread = -1;
@@ -1178,26 +1260,26 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: Curl_read_plain returned error %d\n", *err);
}
else if(nread == 0) {
- connssl->recv_connection_closed = true;
+ BACKEND->recv_connection_closed = true;
infof(data, "schannel: server closed the connection\n");
}
else if(nread > 0) {
- connssl->encdata_offset += (size_t)nread;
- connssl->encdata_is_incomplete = false;
+ BACKEND->encdata_offset += (size_t)nread;
+ BACKEND->encdata_is_incomplete = false;
infof(data, "schannel: encrypted data got %zd\n", nread);
}
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
/* decrypt loop */
- while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK &&
- (!len || connssl->decdata_offset < len ||
- connssl->recv_connection_closed)) {
+ while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK &&
+ (!len || BACKEND->decdata_offset < len ||
+ BACKEND->recv_connection_closed)) {
/* prepare data buffer for DecryptMessage call */
- InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer,
- curlx_uztoul(connssl->encdata_offset));
+ InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer,
+ curlx_uztoul(BACKEND->encdata_offset));
/* we need 3 more empty input buffers for possible output */
InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
@@ -1207,7 +1289,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx
*/
- sspi_status = s_pSecFn->DecryptMessage(&connssl->ctxt->ctxt_handle,
+ sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle,
&inbuf_desc, 0, NULL);
/* check if everything went fine (server may want to renegotiate
@@ -1223,36 +1305,36 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* 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;
- if(connssl->decdata_length - connssl->decdata_offset < size ||
- connssl->decdata_length < len) {
+ if(BACKEND->decdata_length - BACKEND->decdata_offset < size ||
+ BACKEND->decdata_length < len) {
/* increase internal decrypted data buffer */
- reallocated_length = connssl->decdata_offset + size;
+ reallocated_length = BACKEND->decdata_offset + size;
/* make sure that the requested amount of data fits */
if(reallocated_length < len) {
reallocated_length = len;
}
- reallocated_buffer = realloc(connssl->decdata_buffer,
+ reallocated_buffer = realloc(BACKEND->decdata_buffer,
reallocated_length);
if(reallocated_buffer == NULL) {
*err = CURLE_OUT_OF_MEMORY;
failf(data, "schannel: unable to re-allocate memory");
goto cleanup;
}
- connssl->decdata_buffer = reallocated_buffer;
- connssl->decdata_length = reallocated_length;
+ BACKEND->decdata_buffer = reallocated_buffer;
+ BACKEND->decdata_length = reallocated_length;
}
/* copy decrypted data to internal buffer */
size = inbuf[1].cbBuffer;
if(size) {
- memcpy(connssl->decdata_buffer + connssl->decdata_offset,
+ memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset,
inbuf[1].pvBuffer, size);
- connssl->decdata_offset += size;
+ BACKEND->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);
+ BACKEND->decdata_offset, BACKEND->decdata_length);
}
/* check for remaining encrypted data */
@@ -1263,21 +1345,21 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* 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) {
+ if(BACKEND->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) -
+ memmove(BACKEND->encdata_buffer,
+ (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
inbuf[3].cbBuffer, inbuf[3].cbBuffer);
- connssl->encdata_offset = inbuf[3].cbBuffer;
+ BACKEND->encdata_offset = inbuf[3].cbBuffer;
}
infof(data, "schannel: encrypted data cached: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
}
else {
/* reset encrypted buffer offset, because there is no data remaining */
- connssl->encdata_offset = 0;
+ BACKEND->encdata_offset = 0;
}
/* check if server wants to renegotiate the connection context */
@@ -1287,7 +1369,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: can't renogotiate, an error is pending\n");
goto cleanup;
}
- if(connssl->encdata_offset) {
+ if(BACKEND->encdata_offset) {
*err = CURLE_RECV_ERROR;
infof(data, "schannel: can't renogotiate, "
"encrypted data available\n");
@@ -1311,16 +1393,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
else if(sspi_status == SEC_I_CONTEXT_EXPIRED) {
/* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not
returned so we have to work around that in cleanup. */
- connssl->recv_sspi_close_notify = true;
- if(!connssl->recv_connection_closed) {
- connssl->recv_connection_closed = true;
+ BACKEND->recv_sspi_close_notify = true;
+ if(!BACKEND->recv_connection_closed) {
+ BACKEND->recv_connection_closed = true;
infof(data, "schannel: server closed the connection\n");
}
goto cleanup;
}
}
else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
- connssl->encdata_is_incomplete = true;
+ BACKEND->encdata_is_incomplete = true;
if(!*err)
*err = CURLE_AGAIN;
infof(data, "schannel: failed to decrypt data, need more data\n");
@@ -1335,10 +1417,10 @@ schannel_recv(struct connectdata *conn, int sockindex,
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
- connssl->encdata_offset, connssl->encdata_length);
+ BACKEND->encdata_offset, BACKEND->encdata_length);
infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
- connssl->decdata_offset, connssl->decdata_length);
+ BACKEND->decdata_offset, BACKEND->decdata_length);
cleanup:
/* Warning- there is no guarantee the encdata state is valid at this point */
@@ -1352,13 +1434,13 @@ cleanup:
return close_notify. In that case if the connection was closed we assume it
was graceful (close_notify) since there doesn't seem to be a way to tell.
*/
- if(len && !connssl->decdata_offset && connssl->recv_connection_closed &&
- !connssl->recv_sspi_close_notify) {
+ if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
+ !BACKEND->recv_sspi_close_notify) {
bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT,
VERSION_EQUAL);
if(isWin2k && sspi_status == SEC_E_OK)
- connssl->recv_sspi_close_notify = true;
+ BACKEND->recv_sspi_close_notify = true;
else {
*err = CURLE_RECV_ERROR;
infof(data, "schannel: server closed abruptly (missing close_notify)\n");
@@ -1367,23 +1449,23 @@ cleanup:
/* Any error other than CURLE_AGAIN is an unrecoverable error. */
if(*err && *err != CURLE_AGAIN)
- connssl->recv_unrecoverable_err = *err;
+ BACKEND->recv_unrecoverable_err = *err;
- size = len < connssl->decdata_offset ? len : connssl->decdata_offset;
+ size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset;
if(size) {
- memcpy(buf, connssl->decdata_buffer, size);
- memmove(connssl->decdata_buffer, connssl->decdata_buffer + size,
- connssl->decdata_offset - size);
- connssl->decdata_offset -= size;
+ memcpy(buf, BACKEND->decdata_buffer, size);
+ memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size,
+ BACKEND->decdata_offset - size);
+ BACKEND->decdata_offset -= size;
infof(data, "schannel: decrypted data returned %zu\n", size);
infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
- connssl->decdata_offset, connssl->decdata_length);
+ BACKEND->decdata_offset, BACKEND->decdata_length);
*err = CURLE_OK;
return (ssize_t)size;
}
- if(!*err && !connssl->recv_connection_closed)
+ if(!*err && !BACKEND->recv_connection_closed)
*err = CURLE_AGAIN;
/* It's debatable what to return when !len. We could return whatever error we
@@ -1395,15 +1477,13 @@ cleanup:
return *err ? -1 : 0;
}
-CURLcode
-Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex,
- bool *done)
+static 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)
+static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
@@ -1417,25 +1497,38 @@ Curl_schannel_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
+static 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->decdata_offset > 0 ||
- (connssl->encdata_offset > 0 && !connssl->encdata_is_incomplete));
+ return (BACKEND->decdata_offset > 0 ||
+ (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete));
else
return FALSE;
}
-void Curl_schannel_close(struct connectdata *conn, int sockindex)
+static 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)
+static void Curl_schannel_session_free(void *ptr)
+{
+ /* this is expected to be called under sessionid lock */
+ struct curl_schannel_cred *cred = ptr;
+
+ cred->refcount--;
+ if(cred->refcount == 0) {
+ s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+ Curl_safefree(cred);
+ }
+}
+
+static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
{
/* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
* Shutting Down an Schannel Connection
@@ -1448,7 +1541,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
hostname, conn->remote_port);
- if(connssl->cred && connssl->ctxt) {
+ if(BACKEND->cred && BACKEND->ctxt) {
SecBufferDesc BuffDesc;
SecBuffer Buffer;
SECURITY_STATUS sspi_status;
@@ -1461,7 +1554,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
InitSecBufferDesc(&BuffDesc, &Buffer, 1);
- sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle,
+ sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle,
&BuffDesc);
if(sspi_status != SEC_E_OK)
@@ -1477,18 +1570,18 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
sspi_status = s_pSecFn->InitializeSecurityContext(
- &connssl->cred->cred_handle,
- &connssl->ctxt->ctxt_handle,
+ &BACKEND->cred->cred_handle,
+ &BACKEND->ctxt->ctxt_handle,
host_name,
- connssl->req_flags,
+ BACKEND->req_flags,
0,
0,
NULL,
0,
- &connssl->ctxt->ctxt_handle,
+ &BACKEND->ctxt->ctxt_handle,
&outbuf_desc,
- &connssl->ret_flags,
- &connssl->ctxt->time_stamp);
+ &BACKEND->ret_flags,
+ &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name);
@@ -1507,71 +1600,62 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
}
/* free SSPI Schannel API security context handle */
- if(connssl->ctxt) {
+ if(BACKEND->ctxt) {
infof(data, "schannel: clear security context handle\n");
- s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle);
- Curl_safefree(connssl->ctxt);
+ s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
+ Curl_safefree(BACKEND->ctxt);
}
/* free SSPI Schannel API credential handle */
- if(connssl->cred) {
+ if(BACKEND->cred) {
Curl_ssl_sessionid_lock(conn);
- Curl_schannel_session_free(connssl->cred);
+ Curl_schannel_session_free(BACKEND->cred);
Curl_ssl_sessionid_unlock(conn);
- connssl->cred = NULL;
+ BACKEND->cred = NULL;
}
/* 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;
- connssl->encdata_is_incomplete = false;
+ if(BACKEND->encdata_buffer != NULL) {
+ Curl_safefree(BACKEND->encdata_buffer);
+ BACKEND->encdata_length = 0;
+ BACKEND->encdata_offset = 0;
+ BACKEND->encdata_is_incomplete = false;
}
/* 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;
+ if(BACKEND->decdata_buffer != NULL) {
+ Curl_safefree(BACKEND->decdata_buffer);
+ BACKEND->decdata_length = 0;
+ BACKEND->decdata_offset = 0;
}
return CURLE_OK;
}
-void Curl_schannel_session_free(void *ptr)
-{
- /* this is expected to be called under sessionid lock */
- struct curl_schannel_cred *cred = ptr;
-
- cred->refcount--;
- if(cred->refcount == 0) {
- s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
- Curl_safefree(cred);
- }
-}
-
-int Curl_schannel_init(void)
+static int Curl_schannel_init(void)
{
return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
}
-void Curl_schannel_cleanup(void)
+static void Curl_schannel_cleanup(void)
{
Curl_sspi_global_cleanup();
}
-size_t Curl_schannel_version(char *buffer, size_t size)
+static size_t Curl_schannel_version(char *buffer, size_t size)
{
size = snprintf(buffer, size, "WinSSL");
return size;
}
-CURLcode Curl_schannel_random(unsigned char *entropy, size_t length)
+static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
{
HCRYPTPROV hCryptProv = 0;
+ (void)data;
+
if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return CURLE_FAILED_INIT;
@@ -1598,7 +1682,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
conn->http_proxy.host.name :
conn->host.name;
- status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+ status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT,
&pCertContextServer);
@@ -1725,4 +1809,44 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
}
#endif /* _WIN32_WCE */
+static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return &BACKEND->ctxt->ctxt_handle;
+}
+
+const struct Curl_ssl Curl_ssl_schannel = {
+ { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
+
+ 0, /* have_ca_path */
+ 1, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_schannel_init, /* init */
+ Curl_schannel_cleanup, /* cleanup */
+ Curl_schannel_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_schannel_shutdown, /* shutdown */
+ Curl_schannel_data_pending, /* data_pending */
+ Curl_schannel_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_schannel_connect, /* connect */
+ Curl_schannel_connect_nonblocking, /* connect_nonblocking */
+ Curl_schannel_get_internals, /* get_internals */
+ Curl_schannel_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_schannel_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ NULL /* sha256sum */
+};
+
#endif /* USE_SCHANNEL */
diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h
index 8627c63c9..932103da4 100644
--- a/lib/vtls/schannel.h
+++ b/lib/vtls/schannel.h
@@ -28,94 +28,7 @@
#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
-
-/* Both schannel buffer sizes must be > 0 */
-#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
-#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
-
-
-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);
-
-CURLcode Curl_schannel_random(unsigned char *entropy, size_t length);
-
-/* Set the API backend definition to Schannel */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* 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) ((void)x)
-#define curlssl_close Curl_schannel_close
-#define curlssl_shutdown Curl_schannel_shutdown
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_schannel_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending Curl_schannel_data_pending
-#define curlssl_random(x,y,z) ((void)x, Curl_schannel_random(y,z))
+extern const struct Curl_ssl Curl_ssl_schannel;
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index d5d0971c4..1be646e8e 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -28,17 +28,9 @@
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_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.
+
+ Note that this source code uses the functions of the configured SSL
+ backend via the global Curl_ssl instance.
"SSL/TLS Strong Encryption: An Introduction"
https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
@@ -98,9 +90,12 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
(data->version_max == needle->version_max) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
+ (data->verifystatus == needle->verifystatus) &&
Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
+ Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
+ Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
return TRUE;
@@ -111,17 +106,19 @@ bool
Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
struct ssl_primary_config *dest)
{
- dest->verifyhost = source->verifyhost;
- dest->verifypeer = source->verifypeer;
dest->version = source->version;
dest->version_max = source->version_max;
+ dest->verifypeer = source->verifypeer;
+ dest->verifyhost = source->verifyhost;
+ dest->verifystatus = source->verifystatus;
+ dest->sessionid = source->sessionid;
- CLONE_STRING(CAfile);
CLONE_STRING(CApath);
- CLONE_STRING(cipher_list);
- CLONE_STRING(egdsocket);
- CLONE_STRING(random_file);
+ CLONE_STRING(CAfile);
CLONE_STRING(clientcert);
+ CLONE_STRING(random_file);
+ CLONE_STRING(egdsocket);
+ CLONE_STRING(cipher_list);
/* Disable dest sessionid cache if a client cert is used, CVE-2016-5419. */
dest->sessionid = (dest->clientcert ? false : source->sessionid);
@@ -130,23 +127,32 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
{
- Curl_safefree(sslc->CAfile);
Curl_safefree(sslc->CApath);
- Curl_safefree(sslc->cipher_list);
- Curl_safefree(sslc->egdsocket);
- Curl_safefree(sslc->random_file);
+ Curl_safefree(sslc->CAfile);
Curl_safefree(sslc->clientcert);
+ Curl_safefree(sslc->random_file);
+ Curl_safefree(sslc->egdsocket);
+ Curl_safefree(sslc->cipher_list);
}
+#ifdef USE_SSL
+static int multissl_init(const struct Curl_ssl *backend);
+#endif
+
int Curl_ssl_backend(void)
{
- return (int)CURL_SSL_BACKEND;
+#ifdef USE_SSL
+ multissl_init(NULL);
+ return Curl_ssl->info.id;
+#else
+ return (int)CURLSSLBACKEND_NONE;
+#endif
}
#ifdef USE_SSL
/* "global" init done? */
-static bool init_ssl=FALSE;
+static bool init_ssl = FALSE;
/**
* Global SSL init
@@ -161,7 +167,7 @@ int Curl_ssl_init(void)
return 1;
init_ssl = TRUE; /* never again */
- return curlssl_init();
+ return Curl_ssl->init();
}
@@ -170,7 +176,7 @@ void Curl_ssl_cleanup(void)
{
if(init_ssl) {
/* only cleanup if we did a previous init */
- curlssl_cleanup();
+ Curl_ssl->cleanup();
init_ssl = FALSE;
}
}
@@ -205,12 +211,20 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
if(ssl_connection_complete == conn->ssl[sockindex].state &&
!conn->proxy_ssl[sockindex].use) {
-#if defined(HTTPS_PROXY_SUPPORT)
+ struct ssl_backend_data *pbdata;
+
+ if(!Curl_ssl->support_https_proxy)
+ return CURLE_NOT_BUILT_IN;
+
+ /* The pointers to the ssl backend data, which is opaque here, are swapped
+ rather than move the contents. */
+ pbdata = conn->proxy_ssl[sockindex].backend;
conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
+
memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
-#else
- return CURLE_NOT_BUILT_IN;
-#endif
+ memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data);
+
+ conn->ssl[sockindex].backend = pbdata;
}
return CURLE_OK;
}
@@ -233,7 +247,7 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
conn->ssl[sockindex].use = TRUE;
conn->ssl[sockindex].state = ssl_connection_negotiating;
- result = curlssl_connect(conn, sockindex);
+ result = Curl_ssl->connect(conn, sockindex);
if(!result)
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
@@ -257,12 +271,7 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
/* mark this is being ssl requested from here on. */
conn->ssl[sockindex].use = TRUE;
-#ifdef curlssl_connect_nonblocking
- result = curlssl_connect_nonblocking(conn, sockindex, done);
-#else
- *done = TRUE; /* fallback to BLOCKING */
- result = curlssl_connect(conn, sockindex);
-#endif /* non-blocking connect support */
+ result = Curl_ssl->connect_nonblocking(conn, sockindex, done);
if(!result && *done)
Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
return result;
@@ -361,7 +370,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
/* defensive check */
/* free the ID the SSL-layer specific way */
- curlssl_session_free(session->sessionid);
+ Curl_ssl->session_free(session->sessionid);
session->sessionid = NULL;
session->age = 0; /* fresh */
@@ -379,7 +388,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
{
size_t i;
- struct Curl_easy *data=conn->data;
+ struct Curl_easy *data = conn->data;
for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
struct curl_ssl_session *check = &data->state.session[i];
@@ -403,9 +412,9 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
int sockindex)
{
size_t i;
- struct Curl_easy *data=conn->data; /* the mother of all structs */
+ struct Curl_easy *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 */
+ long oldest_age = data->state.session[0].age; /* zero if unused */
char *clone_host;
char *clone_conn_to_host;
int conn_to_port;
@@ -499,7 +508,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
Curl_safefree(data->state.session);
}
- curlssl_close_all(data);
+ Curl_ssl->close_all(data);
}
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
@@ -542,12 +551,12 @@ int Curl_ssl_getsock(struct connectdata *conn,
void Curl_ssl_close(struct connectdata *conn, int sockindex)
{
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- curlssl_close(conn, sockindex);
+ Curl_ssl->close(conn, sockindex);
}
CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
{
- if(curlssl_shutdown(conn, sockindex))
+ if(Curl_ssl->shutdown(conn, sockindex))
return CURLE_SSL_SHUTDOWN_FAILED;
conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
@@ -563,20 +572,20 @@ CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
*/
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
{
- return curlssl_set_engine(data, engine);
+ return Curl_ssl->set_engine(data, engine);
}
/* Selects the default SSL crypto engine
*/
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data)
{
- return curlssl_set_engine_default(data);
+ return Curl_ssl->set_engine_default(data);
}
/* Return list of OpenSSL crypto engine names. */
struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
{
- return curlssl_engines_list(data);
+ return Curl_ssl->engines_list(data);
}
/*
@@ -602,9 +611,15 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
return CURLE_OK;
}
+static size_t Curl_multissl_version(char *buffer, size_t size);
+
size_t Curl_ssl_version(char *buffer, size_t size)
{
- return curlssl_version(buffer, size);
+#ifdef CURL_WITH_MULTI_SSL
+ return Curl_multissl_version(buffer, size);
+#else
+ return Curl_ssl->version(buffer, size);
+#endif
}
/*
@@ -617,13 +632,13 @@ size_t Curl_ssl_version(char *buffer, size_t size)
*/
int Curl_ssl_check_cxn(struct connectdata *conn)
{
- return curlssl_check_cxn(conn);
+ return Curl_ssl->check_cxn(conn);
}
bool Curl_ssl_data_pending(const struct connectdata *conn,
int connindex)
{
- return curlssl_data_pending(conn, connindex);
+ return Curl_ssl->data_pending(conn, connindex);
}
void Curl_ssl_free_certinfo(struct Curl_easy *data)
@@ -633,7 +648,7 @@ void Curl_ssl_free_certinfo(struct Curl_easy *data)
if(ci->num_of_certs) {
/* free all individual lists used */
- for(i=0; i<ci->num_of_certs; i++) {
+ for(i = 0; i<ci->num_of_certs; i++) {
curl_slist_free_all(ci->certinfo[i]);
ci->certinfo[i] = NULL;
}
@@ -687,7 +702,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
snprintf(output, outlen, "%s:", label);
/* memcpy the value (it might not be zero terminated) */
- memcpy(&output[labellen+1], value, valuelen);
+ memcpy(&output[labellen + 1], value, valuelen);
/* zero terminate the output */
output[labellen + 1 + valuelen] = 0;
@@ -721,7 +736,7 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
unsigned char *entropy,
size_t length)
{
- return curlssl_random(data, entropy, length);
+ return Curl_ssl->random(data, entropy, length);
}
/*
@@ -796,12 +811,10 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
size_t size, pem_len;
CURLcode pem_read;
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-#ifdef curlssl_sha256sum
CURLcode encode;
size_t encodedlen, pinkeylen;
char *encoded, *pinkeycopy, *begin_pos, *end_pos;
unsigned char *sha256sumdigest = NULL;
-#endif
/* if a path wasn't specified, don't pin */
if(!pinnedpubkey)
@@ -811,15 +824,20 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
/* only do this if pinnedpubkey starts with "sha256//", length 8 */
if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
-#ifdef curlssl_sha256sum
+ if(!Curl_ssl->sha256sum) {
+ /* without sha256 support, this cannot match */
+ return result;
+ }
+
/* compute sha256sum of public key */
- sha256sumdigest = malloc(SHA256_DIGEST_LENGTH);
+ sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
if(!sha256sumdigest)
return CURLE_OUT_OF_MEMORY;
- curlssl_sha256sum(pubkey, pubkeylen,
- sha256sumdigest, SHA256_DIGEST_LENGTH);
+ Curl_ssl->sha256sum(pubkey, pubkeylen,
+ sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
encode = Curl_base64_encode(data, (char *)sha256sumdigest,
- SHA256_DIGEST_LENGTH, &encoded, &encodedlen);
+ CURL_SHA256_DIGEST_LENGTH, &encoded,
+ &encodedlen);
Curl_safefree(sha256sumdigest);
if(encode)
@@ -864,10 +882,6 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
} while(end_pos && begin_pos);
Curl_safefree(encoded);
Curl_safefree(pinkeycopy);
-#else
- /* without sha256 support, this cannot match */
- (void)data;
-#endif
return result;
}
@@ -943,20 +957,7 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
unsigned char *md5sum, /* output */
size_t md5len)
{
-#ifdef curlssl_md5sum
- curlssl_md5sum(tmp, tmplen, md5sum, md5len);
-#else
- MD5_context *MD5pw;
-
- (void) md5len;
-
- MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
- if(!MD5pw)
- return CURLE_OUT_OF_MEMORY;
- Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen));
- Curl_MD5_final(MD5pw, md5sum);
-#endif
- return CURLE_OK;
+ return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len);
}
#endif
@@ -965,11 +966,7 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
*/
bool Curl_ssl_cert_status_request(void)
{
-#ifdef curlssl_cert_status_request
- return curlssl_cert_status_request();
-#else
- return FALSE;
-#endif
+ return Curl_ssl->cert_status_request();
}
/*
@@ -977,11 +974,341 @@ bool Curl_ssl_cert_status_request(void)
*/
bool Curl_ssl_false_start(void)
{
-#ifdef curlssl_false_start
- return curlssl_false_start();
-#else
+ return Curl_ssl->false_start();
+}
+
+/*
+ * Default implementations for unsupported functions.
+ */
+
+int Curl_none_init(void)
+{
+ return 1;
+}
+
+void Curl_none_cleanup(void)
+{ }
+
+int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
+ int sockindex UNUSED_PARAM)
+{
+ (void)conn;
+ (void)sockindex;
+ return 0;
+}
+
+int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
+{
+ (void)conn;
+ return -1;
+}
+
+CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy UNUSED_PARAM,
+ size_t length UNUSED_PARAM)
+{
+ (void)data;
+ (void)entropy;
+ (void)length;
+ return CURLE_NOT_BUILT_IN;
+}
+
+void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+}
+
+void Curl_none_session_free(void *ptr UNUSED_PARAM)
+{
+ (void)ptr;
+}
+
+bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM,
+ int connindex UNUSED_PARAM)
+{
+ (void)conn;
+ (void)connindex;
+ return 0;
+}
+
+bool Curl_none_cert_status_request(void)
+{
return FALSE;
+}
+
+CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM,
+ const char *engine UNUSED_PARAM)
+{
+ (void)data;
+ (void)engine;
+ return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+ return CURLE_NOT_BUILT_IN;
+}
+
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM)
+{
+ (void)data;
+ return (struct curl_slist *)NULL;
+}
+
+bool Curl_none_false_start(void)
+{
+ return FALSE;
+}
+
+CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
+ unsigned char *md5sum, size_t md5len UNUSED_PARAM)
+{
+ MD5_context *MD5pw;
+
+ (void)md5len;
+
+ MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
+ if(!MD5pw)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen));
+ Curl_MD5_final(MD5pw, md5sum);
+ return CURLE_OK;
+}
+
+static int Curl_multissl_init(void)
+{
+ if(multissl_init(NULL))
+ return 1;
+ return Curl_ssl->init();
+}
+
+static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
+{
+ if(multissl_init(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->connect(conn, sockindex);
+}
+
+static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
+{
+ if(multissl_init(NULL))
+ return CURLE_FAILED_INIT;
+ return Curl_ssl->connect_nonblocking(conn, sockindex, done);
+}
+
+static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info)
+{
+ if(multissl_init(NULL))
+ return NULL;
+ return Curl_ssl->get_internals(connssl, info);
+}
+
+static void Curl_multissl_close(struct connectdata *conn, int sockindex)
+{
+ if(multissl_init(NULL))
+ return;
+ Curl_ssl->close(conn, sockindex);
+}
+
+static const struct Curl_ssl Curl_ssl_multi = {
+ { CURLSSLBACKEND_NONE, "multi" }, /* info */
+
+ 0, /* have_ca_path */
+ 0, /* have_certinfo */
+ 0, /* have_pinnedpubkey */
+ 0, /* have_ssl_ctx */
+ 0, /* support_https_proxy */
+
+ (size_t)-1, /* something insanely large to be on the safe side */
+
+ Curl_multissl_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ Curl_multissl_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_none_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_multissl_connect, /* connect */
+ Curl_multissl_connect_nonblocking, /* connect_nonblocking */
+ Curl_multissl_get_internals, /* get_internals */
+ Curl_multissl_close, /* close */
+ Curl_none_close_all, /* close_all */
+ Curl_none_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ NULL /* sha256sum */
+};
+
+const struct Curl_ssl *Curl_ssl =
+#if defined(CURL_WITH_MULTI_SSL)
+ &Curl_ssl_multi;
+#elif defined(USE_AXTLS)
+ &Curl_ssl_axtls;
+#elif defined(USE_CYASSL)
+ &Curl_ssl_cyassl;
+#elif defined(USE_DARWINSSL)
+ &Curl_ssl_darwinssl;
+#elif defined(USE_GNUTLS)
+ &Curl_ssl_gnutls;
+#elif defined(USE_GSKIT)
+ &Curl_ssl_gskit;
+#elif defined(USE_MBEDTLS)
+ &Curl_ssl_mbedtls;
+#elif defined(USE_NSS)
+ &Curl_ssl_nss;
+#elif defined(USE_OPENSSL)
+ &Curl_ssl_openssl;
+#elif defined(USE_POLARSSL)
+ &Curl_ssl_polarssl;
+#elif defined(USE_SCHANNEL)
+ &Curl_ssl_schannel;
+#else
+#error "Missing struct Curl_ssl for selected SSL backend"
+#endif
+
+static const struct Curl_ssl *available_backends[] = {
+#if defined(USE_AXTLS)
+ &Curl_ssl_axtls,
+#endif
+#if defined(USE_CYASSL)
+ &Curl_ssl_cyassl,
#endif
+#if defined(USE_DARWINSSL)
+ &Curl_ssl_darwinssl,
+#endif
+#if defined(USE_GNUTLS)
+ &Curl_ssl_gnutls,
+#endif
+#if defined(USE_GSKIT)
+ &Curl_ssl_gskit,
+#endif
+#if defined(USE_MBEDTLS)
+ &Curl_ssl_mbedtls,
+#endif
+#if defined(USE_NSS)
+ &Curl_ssl_nss,
+#endif
+#if defined(USE_OPENSSL)
+ &Curl_ssl_openssl,
+#endif
+#if defined(USE_POLARSSL)
+ &Curl_ssl_polarssl,
+#endif
+#if defined(USE_SCHANNEL)
+ &Curl_ssl_schannel,
+#endif
+ NULL
+};
+
+static size_t Curl_multissl_version(char *buffer, size_t size)
+{
+ static const struct Curl_ssl *selected;
+ static char backends[200];
+ static size_t total;
+ const struct Curl_ssl *current;
+
+ current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
+
+ if(current != selected) {
+ char *p = backends;
+ int i;
+
+ selected = current;
+
+ for(i = 0; available_backends[i]; i++) {
+ if(i)
+ *(p++) = ' ';
+ if(selected != available_backends[i])
+ *(p++) = '(';
+ p += available_backends[i]->version(p, backends + sizeof(backends) - p);
+ if(selected != available_backends[i])
+ *(p++) = ')';
+ }
+ *p = '\0';
+ total = p - backends;
+ }
+
+ if(size < total)
+ memcpy(buffer, backends, total + 1);
+ else {
+ memcpy(buffer, backends, size - 1);
+ buffer[size - 1] = '\0';
+ }
+
+ return total;
+}
+
+static int multissl_init(const struct Curl_ssl *backend)
+{
+ const char *env;
+ int i;
+
+ if(Curl_ssl != &Curl_ssl_multi)
+ return 1;
+
+ if(backend) {
+ Curl_ssl = backend;
+ return 0;
+ }
+
+ if(!available_backends[0])
+ return 1;
+
+ env = getenv("CURL_SSL_BACKEND");
+#ifdef CURL_DEFAULT_SSL_BACKEND
+ if(!env)
+ env = CURL_DEFAULT_SSL_BACKEND;
+#endif
+ if(env) {
+ for(i = 0; available_backends[i]; i++) {
+ if(strcasecompare(env, available_backends[i]->info.name)) {
+ Curl_ssl = available_backends[i];
+ return 0;
+ }
+ }
+ }
+
+ /* Fall back to first available backend */
+ Curl_ssl = available_backends[0];
+ return 0;
+}
+
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
+{
+ int i;
+
+ if(Curl_ssl != &Curl_ssl_multi)
+ return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
+
+ for(i = 0; available_backends[i]; i++) {
+ if(available_backends[i]->info.id == id ||
+ (name && strcasecompare(available_backends[i]->info.name, name))) {
+ multissl_init(available_backends[i]);
+ return CURLSSLSET_OK;
+ }
+ }
+
+ if(avail)
+ *avail = (const curl_ssl_backend **)&available_backends;
+ return CURLSSLSET_UNKNOWN_BACKEND;
+}
+
+#else /* USE_SSL */
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail)
+{
+ (void)id;
+ (void)name;
+ (void)avail;
+ return CURLSSLSET_NO_BACKENDS;
}
-#endif /* USE_SSL */
+#endif /* !USE_SSL */
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index 2aabeda20..f1a11ea58 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,6 +23,80 @@
***************************************************************************/
#include "curl_setup.h"
+struct connectdata;
+struct ssl_connect_data;
+
+struct Curl_ssl {
+ /*
+ * This *must* be the first entry to allow returning the list of available
+ * backends in curl_global_sslset().
+ */
+ curl_ssl_backend info;
+
+ unsigned have_ca_path:1; /* supports CAPATH */
+ unsigned have_certinfo:1; /* supports CURLOPT_CERTINFO */
+ unsigned have_pinnedpubkey:1; /* supports CURLOPT_PINNEDPUBLICKEY */
+ unsigned have_ssl_ctx:1; /* supports CURLOPT_SSL_CTX_* */
+
+ unsigned support_https_proxy:1; /* supports access via HTTPS proxies */
+
+ size_t sizeof_ssl_backend_data;
+
+ int (*init)(void);
+ void (*cleanup)(void);
+
+ size_t (*version)(char *buffer, size_t size);
+ int (*check_cxn)(struct connectdata *cxn);
+ int (*shutdown)(struct connectdata *conn, int sockindex);
+ bool (*data_pending)(const struct connectdata *conn,
+ int connindex);
+
+ /* return 0 if a find random is filled in */
+ CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy,
+ size_t length);
+ bool (*cert_status_request)(void);
+
+ CURLcode (*connect)(struct connectdata *conn, int sockindex);
+ CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex,
+ bool *done);
+ void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
+ void (*close)(struct connectdata *conn, int sockindex);
+ void (*close_all)(struct Curl_easy *data);
+ void (*session_free)(void *ptr);
+
+ CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
+ CURLcode (*set_engine_default)(struct Curl_easy *data);
+ struct curl_slist *(*engines_list)(struct Curl_easy *data);
+
+ bool (*false_start)(void);
+
+ CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
+ unsigned char *md5sum, size_t md5sumlen);
+ void (*sha256sum)(const unsigned char *input, size_t inputlen,
+ unsigned char *sha256sum, size_t sha256sumlen);
+};
+
+#ifdef USE_SSL
+extern const struct Curl_ssl *Curl_ssl;
+#endif
+
+int Curl_none_init(void);
+void Curl_none_cleanup(void);
+int Curl_none_shutdown(struct connectdata *conn, int sockindex);
+int Curl_none_check_cxn(struct connectdata *conn);
+CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
+ size_t length);
+void Curl_none_close_all(struct Curl_easy *data);
+void Curl_none_session_free(void *ptr);
+bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
+bool Curl_none_cert_status_request(void);
+CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
+bool Curl_none_false_start(void);
+CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
+ unsigned char *md5sum, size_t md5len);
+
#include "openssl.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
#include "nssg.h" /* NSS versions */
@@ -42,8 +116,8 @@
#define MD5_DIGEST_LENGTH 16 /* fixed size */
#endif
-#ifndef SHA256_DIGEST_LENGTH
-#define SHA256_DIGEST_LENGTH 32 /* fixed size */
+#ifndef CURL_SHA256_DIGEST_LENGTH
+#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#endif
/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
@@ -172,8 +246,6 @@ bool Curl_ssl_false_start(void);
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
#else
-/* Set the API backend definition to none */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_NONE
/* When SSL support is not present, just define away these function calls */
#define Curl_ssl_init() 1
diff --git a/lib/warnless.c b/lib/warnless.c
index fb085c86d..05d9038dc 100644
--- a/lib/warnless.c
+++ b/lib/warnless.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -69,36 +69,36 @@
# error "SIZEOF_INT not defined"
#endif
-#if (CURL_SIZEOF_LONG == 2)
+#if (SIZEOF_LONG == 2)
# define CURL_MASK_SLONG 0x7FFFL
# define CURL_MASK_ULONG 0xFFFFUL
-#elif (CURL_SIZEOF_LONG == 4)
+#elif (SIZEOF_LONG == 4)
# define CURL_MASK_SLONG 0x7FFFFFFFL
# define CURL_MASK_ULONG 0xFFFFFFFFUL
-#elif (CURL_SIZEOF_LONG == 8)
+#elif (SIZEOF_LONG == 8)
# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL
# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL
-#elif (CURL_SIZEOF_LONG == 16)
+#elif (SIZEOF_LONG == 16)
# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL
# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL
#else
-# error "CURL_SIZEOF_LONG not defined"
+# error "SIZEOF_LONG not defined"
#endif
-#if (CURL_SIZEOF_CURL_OFF_T == 2)
+#if (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)
+#elif (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)
+#elif (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)
+#elif (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"
+# error "SIZEOF_CURL_OFF_T not defined"
#endif
#if (SIZEOF_SIZE_T == SIZEOF_SHORT)
@@ -107,10 +107,10 @@
#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)
+#elif (SIZEOF_SIZE_T == 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)
+#elif (SIZEOF_SIZE_T == SIZEOF_CURL_OFF_T)
# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT
# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT
#else
@@ -226,7 +226,7 @@ unsigned long curlx_uztoul(size_t uznum)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif
-#if (CURL_SIZEOF_LONG < SIZEOF_SIZE_T)
+#if (SIZEOF_LONG < SIZEOF_SIZE_T)
DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG);
#endif
return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG);
@@ -269,7 +269,7 @@ int curlx_sltosi(long slnum)
#endif
DEBUGASSERT(slnum >= 0);
-#if (SIZEOF_INT < CURL_SIZEOF_LONG)
+#if (SIZEOF_INT < SIZEOF_LONG)
DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT);
#endif
return (int)(slnum & (long) CURL_MASK_SINT);
@@ -291,7 +291,7 @@ unsigned int curlx_sltoui(long slnum)
#endif
DEBUGASSERT(slnum >= 0);
-#if (SIZEOF_INT < CURL_SIZEOF_LONG)
+#if (SIZEOF_INT < SIZEOF_LONG)
DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT);
#endif
return (unsigned int)(slnum & (long) CURL_MASK_UINT);
diff --git a/lib/wildcard.h b/lib/wildcard.h
index 89d965ccf..198b70b86 100644
--- a/lib/wildcard.h
+++ b/lib/wildcard.h
@@ -26,6 +26,8 @@
#include "llist.h"
+#include "llist.h"
+
/* list of wildcard process states */
typedef enum {
CURLWC_CLEAR = 0,
diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4
index 3c87efa09..422946e26 100644
--- a/m4/curl-compilers.m4
+++ b/m4/curl-compilers.m4
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -89,7 +89,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_CLANG], [
if test -z "$clangver"; then
if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then
dnl Starting with XCode 7 / clang 3.7, Apple clang won't tell its upstream version
- clangver=`3.7`
+ clangver="3.7"
else
clangver=`echo $fullclangver | "$SED" 's/.*version \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'`
fi
@@ -922,6 +922,11 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
dnl Only clang 3.9 or later
if test "$compiler_num" -ge "309"; then
tmp_CFLAGS="$tmp_CFLAGS -Wcomma"
+ # avoid the varargs warning, fixed in 4.0
+ # https://bugs.llvm.org/show_bug.cgi?id=29140
+ if test "$compiler_num" -lt "400"; then
+ tmp_CFLAGS="$tmp_CFLAGS -Wno-varargs"
+ fi
fi
fi
;;
diff --git a/m4/curl-confopts.m4 b/m4/curl-confopts.m4
index d77a884d5..6dcd0f1a6 100644
--- a/m4/curl-confopts.m4
+++ b/m4/curl-confopts.m4
@@ -37,14 +37,14 @@ AC_HELP_STRING([--enable-threaded-resolver],[Enable threaded resolver])
AC_HELP_STRING([--disable-threaded-resolver],[Disable threaded resolver]),
OPT_THRES=$enableval)
case "$OPT_THRES" in
- *)
- dnl configure option not specified
- want_thres="yes"
- ;;
no)
dnl --disable-threaded-resolver option used
want_thres="no"
;;
+ *)
+ dnl configure option not specified
+ want_thres="yes"
+ ;;
esac
AC_MSG_RESULT([$want_thres])
])
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index e4d2d30ca..ff5e28eec 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -129,6 +129,8 @@
d c X'00100000'
d CURL_VERSION_HTTPS_PROXY...
d c X'00200000'
+ d CURL_VERSION_MULTI_SSL...
+ d c X'00400000'
*
d CURL_HTTPPOST_FILENAME...
d c X'00000001'
@@ -1312,6 +1314,8 @@
d c 10264
d CURLOPT_SUPPRESS_CONNECT_HEADERS...
d c 00265
+ d CURLOPT_SSH_COMPRESSION...
+ d c 00268
*
/if not defined(CURL_NO_OLDIES)
d CURLOPT_FILE c 10001
diff --git a/projects/build-openssl.bat b/projects/build-openssl.bat
index 0773e07db..33da17401 100644
--- a/projects/build-openssl.bat
+++ b/projects/build-openssl.bat
@@ -138,6 +138,9 @@ rem ***************************************************************************
rem Check the start directory exists
if not exist "%START_DIR%" goto noopenssl
+ rem Check that OpenSSL is not unsupported version 1.1.0
+ if not exist "%START_DIR%\ms\do_ms.bat" goto unsupported
+
:configure
if "%BUILD_PLATFORM%" == "" (
if "%VC_VER%" == "6.0" (
@@ -355,6 +358,14 @@ rem ***************************************************************************
echo Error: Cannot locate OpenSSL source directory
goto error
+:unsupported
+ echo.
+ echo Error: Unsupported OpenSSL version.
+ echo The pre-generated project files and this build script only support the
+ echo LTS version of OpenSSL ^(v1.0.2^). The next version of this build script
+ echo will support OpenSSL v1.1.0.
+ goto error
+
:error
if "%OS%" == "Windows_NT" endlocal
exit /B 1
diff --git a/scripts/contributors.sh b/scripts/contributors.sh
index fcaaff878..db7aab8e0 100755
--- a/scripts/contributors.sh
+++ b/scripts/contributors.sh
@@ -44,7 +44,7 @@ fi
# sort all unique names
# awk them into RELEASE-NOTES format
(
-git log $start..HEAD | \
+git log --use-mailmap $start..HEAD | \
egrep -ai '(^Author|^Commit|by):' | \
cut -d: -f2- | \
cut '-d(' -f1 | \
diff --git a/scripts/contrithanks.sh b/scripts/contrithanks.sh
index 4d6d47a80..d3dad3e90 100755
--- a/scripts/contrithanks.sh
+++ b/scripts/contrithanks.sh
@@ -35,7 +35,7 @@ fi
cat ./docs/THANKS
(
-git log $start..HEAD | \
+git log --use-mailmap $start..HEAD | \
egrep -ai '(^Author|^Commit|by):' | \
cut -d: -f2- | \
cut '-d(' -f1 | \
diff --git a/scripts/updatemanpages.pl b/scripts/updatemanpages.pl
index e144bad11..6a58dbd42 100755
--- a/scripts/updatemanpages.pl
+++ b/scripts/updatemanpages.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/env perl
+#!/usr/bin/perl
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
diff --git a/scripts/zsh.pl b/scripts/zsh.pl
index 5b5ad13e7..fbafde164 100755
--- a/scripts/zsh.pl
+++ b/scripts/zsh.pl
@@ -54,10 +54,11 @@ sub parse_main_opts {
$option .= '}' if defined $short;
$option .= '\'[' . trim($desc) . ']\'' if defined $desc;
- $option .= ":$arg" if defined $arg;
+ $option .= ":'$arg'" if defined $arg;
$option .= ':_files'
- if defined $arg and ($arg eq 'FILE' || $arg eq 'DIR');
+ if defined $arg and ($arg eq '<file>' || $arg eq '<filename>'
+ || $arg eq '<dir>');
push @list, $option;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index a6bab6bdc..f436524bd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,8 @@ bin_PROGRAMS = gnurl
SUBDIRS = ../docs
+SUBDIRS = ../docs
+
if USE_CPPFLAG_CURL_STATICLIB
AM_CPPFLAGS += -DCURL_STATICLIB
endif
@@ -95,7 +97,6 @@ EXTRA_DIST = mkhelp.pl makefile.dj Makefile.b32 \
# Use absolute directory to disable VPATH
MANPAGE=$(abs_top_builddir)/docs/gnurl.1
-
README=$(top_srcdir)/docs/MANUAL
MKHELP=$(top_srcdir)/src/mkhelp.pl
HUGE=tool_hugehelp.c
diff --git a/src/Makefile.inc b/src/Makefile.inc
index 5074f8fc6..45b4967f6 100644
--- a/src/Makefile.inc
+++ b/src/Makefile.inc
@@ -45,7 +45,6 @@ CURL_CFILES = \
tool_libinfo.c \
tool_main.c \
tool_metalink.c \
- tool_mfiles.c \
tool_msgs.c \
tool_operate.c \
tool_operhlp.c \
@@ -86,7 +85,6 @@ CURL_HFILES = \
tool_libinfo.h \
tool_main.h \
tool_metalink.h \
- tool_mfiles.h \
tool_msgs.h \
tool_operate.h \
tool_operhlp.h \
diff --git a/src/Makefile.m32 b/src/Makefile.m32
index 22e11e8e0..836fa2738 100644
--- a/src/Makefile.m32
+++ b/src/Makefile.m32
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1999 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1999 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -62,9 +62,9 @@ endif
ifndef LIBXML2_PATH
LIBXML2_PATH = ../../libxml2-2.9.2
endif
-# Edit the path below to point to the base of your libidn package.
-ifndef LIBIDN_PATH
-LIBIDN_PATH = ../../libidn-1.32
+# Edit the path below to point to the base of your libidn2 package.
+ifndef LIBIDN2_PATH
+LIBIDN2_PATH = ../../libidn2-2.0.3
endif
# Edit the path below to point to the base of your MS IDN package.
# Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1
@@ -168,9 +168,7 @@ ZLIB = 1
endif
ifeq ($(findstring -ssh2,$(CFG)),-ssh2)
SSH2 = 1
-ifneq ($(findstring -winssl,$(CFG)),-winssl)
SSL = 1
-endif
ZLIB = 1
endif
ifeq ($(findstring -ssl,$(CFG)),-ssl)
@@ -179,8 +177,8 @@ endif
ifeq ($(findstring -zlib,$(CFG)),-zlib)
ZLIB = 1
endif
-ifeq ($(findstring -idn,$(CFG)),-idn)
-IDN = 1
+ifeq ($(findstring -idn2,$(CFG)),-idn2)
+IDN2 = 1
endif
ifeq ($(findstring -winidn,$(CFG)),-winidn)
WINIDN = 1
@@ -206,6 +204,11 @@ NGHTTP2 = 1
endif
INCLUDES = -I. -I../include -I../lib
+ifdef SSL
+ ifdef WINSSL
+ CFLAGS += -DCURL_WITH_MULTI_SSL
+ endif
+endif
ifdef DYN
curl_DEPENDENCIES = $(PROOT)/lib/libgnurldll.a $(PROOT)/lib/libgnurl.dll
@@ -274,19 +277,19 @@ ifdef SSL
INCLUDES += -I"$(OPENSSL_INCLUDE)"
CFLAGS += -DUSE_OPENSSL
curl_LDADD += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS)
-else
+endif
ifdef WINSSL
+ CFLAGS += -DUSE_SCHANNEL
curl_LDADD += -lcrypt32
endif
-endif
ifdef ZLIB
INCLUDES += -I"$(ZLIB_PATH)"
CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
curl_LDADD += -L"$(ZLIB_PATH)" -lz
endif
-ifdef IDN
- CFLAGS += -DUSE_LIBIDN
- curl_LDADD += -L"$(LIBIDN_PATH)/lib" -lidn
+ifdef IDN2
+ CFLAGS += -DUSE_LIBIDN2
+ curl_LDADD += -L"$(LIBIDN2_PATH)/lib" -lidn2
else
ifdef WINIDN
CFLAGS += -DUSE_WIN32_IDN
@@ -307,9 +310,6 @@ ifdef METALINK
endif
ifdef SSPI
CFLAGS += -DUSE_WINDOWS_SSPI
- ifdef WINSSL
- CFLAGS += -DUSE_SCHANNEL
- endif
endif
ifdef IPV6
CFLAGS += -DENABLE_IPV6 -D_WIN32_WINNT=0x0501
diff --git a/src/tool_cb_dbg.c b/src/tool_cb_dbg.c
index b4fbe0bb9..aa1ef857c 100644
--- a/src/tool_cb_dbg.c
+++ b/src/tool_cb_dbg.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -238,37 +238,40 @@ static void dump(const char *timebuf, const char *text,
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]);
+ if(i + c < size)
+ fprintf(stream, "%02x ", ptr[i + c]);
else
fputs(" ", stream);
}
- for(c = 0; (c < width) && (i+c < size); c++) {
+ 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);
+ (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);
+ (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]));
+ 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);
+ 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);
+ (i + c + 2 < size) && (ptr[i + c + 1] == 0x0D) &&
+ (ptr[i + c + 2] == 0x0A)) {
+ i += (c + 3 - width);
break;
}
}
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
index 0e13eec50..bb982d2e4 100644
--- a/src/tool_cb_hdr.c
+++ b/src/tool_cb_hdr.c
@@ -146,7 +146,7 @@ static char *parse_filename(const char *ptr, size_t len)
char stop = '\0';
/* simple implementation of strndup() */
- copy = malloc(len+1);
+ copy = malloc(len + 1);
if(!copy)
return NULL;
memcpy(copy, ptr, len);
diff --git a/src/tool_cb_prg.c b/src/tool_cb_prg.c
index d4ecb3cef..992b96d97 100644
--- a/src/tool_cb_prg.c
+++ b/src/tool_cb_prg.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,7 +44,7 @@ int tool_progress_cb(void *clientp,
/* 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 line[MAX_BARLENGTH + 1];
char format[40];
double frac;
double percent;
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index 675e88b45..755195ced 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -140,11 +140,11 @@ static void free_config_fields(struct OperationConfig *config)
curl_slist_free_all(config->headers);
curl_slist_free_all(config->proxyheaders);
- if(config->httppost) {
- curl_formfree(config->httppost);
- config->httppost = NULL;
+ if(config->mimepost) {
+ curl_mime_free(config->mimepost);
+ config->mimepost = NULL;
}
- config->last_post = NULL;
+ config->mimecurrent = NULL;
curl_slist_free_all(config->telnet_options);
curl_slist_free_all(config->resolve);
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 254805c8c..23943fe7b 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -170,8 +170,8 @@ struct OperationConfig {
time_t condtime;
struct curl_slist *headers;
struct curl_slist *proxyheaders;
- struct curl_httppost *httppost;
- struct curl_httppost *last_post;
+ curl_mime *mimepost;
+ curl_mime *mimecurrent;
struct curl_slist *telnet_options;
struct curl_slist *resolve;
struct curl_slist *connect_to;
@@ -247,6 +247,7 @@ struct OperationConfig {
from user callbacks */
curl_error synthetic_error; /* if non-zero, it overrides any libcurl
error */
+ bool ssh_compression; /* enable/disable SSH compression */
struct GlobalConfig *global;
struct OperationConfig *prev;
struct OperationConfig *next; /* Always last in the struct */
diff --git a/src/tool_easysrc.c b/src/tool_easysrc.c
index e3c9d1aa1..fc6600261 100644
--- a/src/tool_easysrc.c
+++ b/src/tool_easysrc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,7 +42,7 @@ struct slist_wc *easysrc_data = NULL; /* Build slists, forms etc. */
struct slist_wc *easysrc_code = NULL; /* Setopt calls */
struct slist_wc *easysrc_toohard = NULL; /* Unconvertible setopt */
struct slist_wc *easysrc_clean = NULL; /* Clean up allocated data */
-int easysrc_form_count = 0;
+int easysrc_mime_count = 0;
int easysrc_slist_count = 0;
static const char *const srchead[]={
@@ -141,11 +141,11 @@ CURLcode easysrc_perform(void)
const char *c;
CHKRET(easysrc_add(&easysrc_code, ""));
/* Preamble comment */
- for(i=0; ((c = srchard[i]) != NULL); i++)
+ for(i = 0; ((c = srchard[i]) != NULL); i++)
CHKRET(easysrc_add(&easysrc_code, c));
/* Each unconverted option */
if(easysrc_toohard) {
- for(ptr=easysrc_toohard->first; ptr; ptr = ptr->next)
+ for(ptr = easysrc_toohard->first; ptr; ptr = ptr->next)
CHKRET(easysrc_add(&easysrc_code, ptr->data));
}
CHKRET(easysrc_add(&easysrc_code, ""));
@@ -189,12 +189,12 @@ void dumpeasysrc(struct GlobalConfig *config)
int i;
const char *c;
- for(i=0; ((c = srchead[i]) != NULL); i++)
+ for(i = 0; ((c = srchead[i]) != NULL); i++)
fprintf(out, "%s\n", c);
/* Declare variables used for complex setopt values */
if(easysrc_decl) {
- for(ptr=easysrc_decl->first; ptr; ptr = ptr->next)
+ for(ptr = easysrc_decl->first; ptr; ptr = ptr->next)
fprintf(out, " %s\n", ptr->data);
}
@@ -202,13 +202,13 @@ void dumpeasysrc(struct GlobalConfig *config)
if(easysrc_data) {
fprintf(out, "\n");
- for(ptr=easysrc_data->first; ptr; ptr = ptr->next)
+ for(ptr = easysrc_data->first; ptr; ptr = ptr->next)
fprintf(out, " %s\n", ptr->data);
}
fprintf(out, "\n");
if(easysrc_code) {
- for(ptr=easysrc_code->first; ptr; ptr = ptr->next) {
+ for(ptr = easysrc_code->first; ptr; ptr = ptr->next) {
if(ptr->data[0]) {
fprintf(out, " %s\n", ptr->data);
}
@@ -219,11 +219,11 @@ void dumpeasysrc(struct GlobalConfig *config)
}
if(easysrc_clean) {
- for(ptr=easysrc_clean->first; ptr; ptr = ptr->next)
+ for(ptr = easysrc_clean->first; ptr; ptr = ptr->next)
fprintf(out, " %s\n", ptr->data);
}
- for(i=0; ((c = srcend[i]) != NULL); i++)
+ for(i = 0; ((c = srcend[i]) != NULL); i++)
fprintf(out, "%s\n", c);
if(fopened)
diff --git a/src/tool_easysrc.h b/src/tool_easysrc.h
index 54607b861..fd799ab84 100644
--- a/src/tool_easysrc.h
+++ b/src/tool_easysrc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,7 +32,7 @@ extern struct slist_wc *easysrc_code; /* Setopt calls etc. */
extern struct slist_wc *easysrc_toohard; /* Unconvertible setopt */
extern struct slist_wc *easysrc_clean; /* Clean up (reverse order) */
-extern int easysrc_form_count; /* Number of curl_httppost variables */
+extern int easysrc_mime_count; /* Number of curl_mime variables */
extern int easysrc_slist_count; /* Number of curl_slist variables */
extern CURLcode easysrc_init(void);
diff --git a/src/tool_formparse.c b/src/tool_formparse.c
index 952377c49..4645a761e 100644
--- a/src/tool_formparse.c
+++ b/src/tool_formparse.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,6 +21,7 @@
***************************************************************************/
#include "tool_setup.h"
+#include "mime.h"
#include "strcase.h"
#define ENABLE_CURLX_PRINTF
@@ -29,7 +30,6 @@
#include "tool_cfgable.h"
#include "tool_convert.h"
-#include "tool_mfiles.h"
#include "tool_msgs.h"
#include "tool_formparse.h"
@@ -77,10 +77,10 @@ static char *get_param_word(char **str, char **end_pos)
while(ptr < *end_pos);
*end_pos = ptr2;
}
- while(*ptr && NULL==strchr(end_chars, *ptr))
+ while(*ptr && NULL == strchr(end_chars, *ptr))
++ptr;
*str = ptr;
- return word_begin+1;
+ return word_begin + 1;
}
++ptr;
}
@@ -88,12 +88,303 @@ static char *get_param_word(char **str, char **end_pos)
ptr = word_begin;
}
- while(*ptr && NULL==strchr(end_chars, *ptr))
+ while(*ptr && NULL == strchr(end_chars, *ptr))
++ptr;
*str = *end_pos = ptr;
return word_begin;
}
+/* Append slist item and return -1 if failed. */
+static int slist_append(struct curl_slist **plist, const char *data)
+{
+ struct curl_slist *s = curl_slist_append(*plist, data);
+
+ if(!s)
+ return -1;
+
+ *plist = s;
+ return 0;
+}
+
+/* Read headers from a file and append to list. */
+static int read_field_headers(struct OperationConfig *config,
+ const char *filename, FILE *fp,
+ struct curl_slist **pheaders)
+{
+ size_t hdrlen = 0;
+ size_t pos = 0;
+ int c;
+ bool incomment = FALSE;
+ int lineno = 1;
+ char hdrbuf[999]; /* Max. header length + 1. */
+
+ for(;;) {
+ c = getc(fp);
+ if(c == EOF || (!pos && !ISSPACE(c))) {
+ /* Strip and flush the current header. */
+ while(hdrlen && ISSPACE(hdrbuf[hdrlen - 1]))
+ hdrlen--;
+ if(hdrlen) {
+ hdrbuf[hdrlen] = '\0';
+ if(slist_append(pheaders, hdrbuf)) {
+ fprintf(config->global->errors,
+ "Out of memory for field headers!\n");
+ return -1;
+ }
+ hdrlen = 0;
+ }
+ }
+
+ switch(c) {
+ case EOF:
+ if(ferror(fp)) {
+ fprintf(config->global->errors,
+ "Header file %s read error: %s\n", filename, strerror(errno));
+ return -1;
+ }
+ return 0; /* Done. */
+ case '\r':
+ continue; /* Ignore. */
+ case '\n':
+ pos = 0;
+ incomment = FALSE;
+ lineno++;
+ continue;
+ case '#':
+ if(!pos)
+ incomment = TRUE;
+ break;
+ }
+
+ pos++;
+ if(!incomment) {
+ if(hdrlen == sizeof hdrbuf - 1) {
+ warnf(config->global, "File %s line %d: header too long (truncated)\n",
+ filename, lineno);
+ c = ' ';
+ }
+ if(hdrlen <= sizeof hdrbuf - 1)
+ hdrbuf[hdrlen++] = (char) c;
+ }
+ }
+ /* NOTREACHED */
+}
+
+static int get_param_part(struct OperationConfig *config, char **str,
+ char **pdata, char **ptype, char **pfilename,
+ char **pencoder, struct curl_slist **pheaders)
+{
+ char *p = *str;
+ char *type = NULL;
+ char *filename = NULL;
+ char *encoder = NULL;
+ char *endpos;
+ char *tp;
+ char sep;
+ char type_major[128] = "";
+ char type_minor[128] = "";
+ char *endct = NULL;
+ struct curl_slist *headers = NULL;
+
+ if(ptype)
+ *ptype = NULL;
+ if(pfilename)
+ *pfilename = NULL;
+ if(pheaders)
+ *pheaders = NULL;
+ if(pencoder)
+ *pencoder = NULL;
+ while(ISSPACE(*p))
+ p++;
+ tp = p;
+ *pdata = get_param_word(&p, &endpos);
+ /* If not quoted, strip trailing spaces. */
+ if(*pdata == tp)
+ while(endpos > *pdata && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ while(sep == ';') {
+ while(ISSPACE(*++p))
+ ;
+
+ if(!endct && checkprefix("type=", p)) {
+ for(p += 5; ISSPACE(*p); p++)
+ ;
+ /* set type pointer */
+ type = p;
+
+ /* verify that this is a fine type specifier */
+ if(2 != sscanf(type, "%127[^/ ]/%127[^;, \n]", type_major, type_minor)) {
+ warnf(config->global, "Illegally formatted content-type field!\n");
+ curl_slist_free_all(headers);
+ return -1; /* illegal content-type syntax! */
+ }
+
+ /* now point beyond the content-type specifier */
+ endpos = type + strlen(type_major) + strlen(type_minor) + 1;
+ for(p = endpos; ISSPACE(*p); p++)
+ ;
+ while(*p && *p != ';' && *p != ',')
+ p++;
+ endct = p;
+ sep = *p;
+ }
+ else if(checkprefix("filename=", p)) {
+ if(endct) {
+ *endct = '\0';
+ endct = NULL;
+ }
+ for(p += 9; ISSPACE(*p); p++)
+ ;
+ tp = p;
+ filename = get_param_word(&p, &endpos);
+ /* If not quoted, strip trailing spaces. */
+ if(filename == tp)
+ while(endpos > filename && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ }
+ else if(checkprefix("headers=", p)) {
+ if(endct) {
+ *endct = '\0';
+ endct = NULL;
+ }
+ p += 8;
+ if(*p == '@' || *p == '<') {
+ char *hdrfile;
+ FILE *fp;
+ /* Read headers from a file. */
+
+ do {
+ p++;
+ } while(ISSPACE(*p));
+ tp = p;
+ hdrfile = get_param_word(&p, &endpos);
+ /* If not quoted, strip trailing spaces. */
+ if(hdrfile == tp)
+ while(endpos > hdrfile && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ /* TODO: maybe special fopen for VMS? */
+ fp = fopen(hdrfile, FOPEN_READTEXT);
+ if(!fp)
+ warnf(config->global, "Cannot read from %s: %s\n", hdrfile,
+ strerror(errno));
+ else {
+ int i = read_field_headers(config, hdrfile, fp, &headers);
+
+ fclose(fp);
+ if(i) {
+ curl_slist_free_all(headers);
+ return -1;
+ }
+ }
+ }
+ else {
+ char *hdr;
+
+ while(ISSPACE(*p))
+ p++;
+ tp = p;
+ hdr = get_param_word(&p, &endpos);
+ /* If not quoted, strip trailing spaces. */
+ if(hdr == tp)
+ while(endpos > hdr && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ if(slist_append(&headers, hdr)) {
+ fprintf(config->global->errors, "Out of memory for field header!\n");
+ curl_slist_free_all(headers);
+ return -1;
+ }
+ }
+ }
+ else if(checkprefix("encoder=", p)) {
+ if(endct) {
+ *endct = '\0';
+ endct = NULL;
+ }
+ for(p += 8; ISSPACE(*p); p++)
+ ;
+ tp = p;
+ encoder = get_param_word(&p, &endpos);
+ /* If not quoted, strip trailing spaces. */
+ if(encoder == tp)
+ while(endpos > encoder && ISSPACE(endpos[-1]))
+ endpos--;
+ sep = *p;
+ *endpos = '\0';
+ }
+ else {
+ /* unknown prefix, skip to next block */
+ char *unknown = get_param_word(&p, &endpos);
+
+ sep = *p;
+ if(endct)
+ endct = p;
+ else {
+ *endpos = '\0';
+ if(*unknown)
+ warnf(config->global, "skip unknown form field: %s\n", unknown);
+ }
+ }
+ }
+
+ /* Terminate and strip content type. */
+ if(type) {
+ if(!endct)
+ endct = type + strlen(type);
+ while(endct > type && ISSPACE(endct[-1]))
+ endct--;
+ *endct = '\0';
+ }
+
+ if(ptype)
+ *ptype = type;
+ else if(type)
+ warnf(config->global, "Field content type not allowed here: %s\n", type);
+
+ if(pfilename)
+ *pfilename = filename;
+ else if(filename)
+ warnf(config->global,
+ "Field file name not allowed here: %s\n", filename);
+
+ if(pencoder)
+ *pencoder = encoder;
+ else if(encoder)
+ warnf(config->global,
+ "Field encoder not allowed here: %s\n", encoder);
+
+ if(pheaders)
+ *pheaders = headers;
+ else if(headers) {
+ warnf(config->global,
+ "Field headers not allowed here: %s\n", headers->data);
+ curl_slist_free_all(headers);
+ }
+
+ *str = p;
+ return sep & 0xFF;
+}
+
+/* Check if file is "-". If so, use a callback to read OUR stdin (to
+ * workaround Windows DLL file handle caveat).
+ * Else use curl_mime_filedata(). */
+static CURLcode file_or_stdin(curl_mimepart *part, const char *file)
+{
+ if(strcmp(file, "-"))
+ return curl_mime_filedata(part, file);
+
+ return curl_mime_data_cb(part, -1, (curl_read_callback) fread,
+ (curl_seek_callback) fseek, NULL, stdin);
+}
+
+
/***************************************************************************
*
* formparse()
@@ -143,219 +434,315 @@ static char *get_param_word(char **str, char **end_pos)
int formparse(struct OperationConfig *config,
const char *input,
- struct curl_httppost **httppost,
- struct curl_httppost **last_post,
+ curl_mime **mimepost,
+ curl_mime **mimecurrent,
bool literal_value)
{
- /* nextarg MUST be a string in the format 'name=contents' and we'll
+ /* input MUST be a string in the format 'name=contents' and we'll
build a linked list with the info */
- char name[256];
+ char *name = NULL;
char *contents = NULL;
- char type_major[128] = "";
- char type_minor[128] = "";
char *contp;
+ char *data;
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");
+ char *filename = NULL;
+ char *encoder = NULL;
+ struct curl_slist *headers = NULL;
+ curl_mimepart *part = NULL;
+ CURLcode res;
+ int sep = '\0';
+
+ /* Allocate the main mime structure if needed. */
+ if(!*mimepost) {
+ *mimepost = curl_mime_init(config->easy);
+ if(!*mimepost) {
+ warnf(config->global, "curl_mime_init failed!\n");
return 1;
}
- contp = contents;
+ *mimecurrent = *mimepost;
+ }
- if('@' == contp[0] && !literal_value) {
+ /* Make a copy we can overwrite. */
+ contents = strdup(input);
+ if(!contents) {
+ fprintf(config->global->errors, "out of memory\n");
+ return 2;
+ }
- /* we use the @-letter to indicate file name(s) */
+ /* Scan for the end of the name. */
+ contp = strchr(contents, '=');
+ if(contp) {
+ if(contp > contents)
+ name = contents;
+ *contp++ = '\0';
+
+ if(*contp == '(' && !literal_value) {
+ curl_mime *subparts;
+
+ /* Starting a multipart. */
+ sep = get_param_part(config, &contp, &data, &type, NULL, NULL, &headers);
+ if(sep < 0) {
+ Curl_safefree(contents);
+ return 3;
+ }
+ subparts = curl_mime_init(config->easy);
+ if(!subparts) {
+ warnf(config->global, "curl_mime_init failed!\n");
+ curl_slist_free_all(headers);
+ Curl_safefree(contents);
+ return 4;
+ }
+ part = curl_mime_addpart(*mimecurrent);
+ if(!part) {
+ warnf(config->global, "curl_mime_addpart failed!\n");
+ curl_mime_free(subparts);
+ curl_slist_free_all(headers);
+ Curl_safefree(contents);
+ return 5;
+ }
+ if(curl_mime_subparts(part, subparts)) {
+ warnf(config->global, "curl_mime_subparts failed!\n");
+ curl_mime_free(subparts);
+ curl_slist_free_all(headers);
+ Curl_safefree(contents);
+ return 6;
+ }
+ *mimecurrent = subparts;
+ if(curl_mime_headers(part, headers, 1)) {
+ warnf(config->global, "curl_mime_headers failed!\n");
+ curl_slist_free_all(headers);
+ Curl_safefree(contents);
+ return 7;
+ }
+ if(curl_mime_type(part, type)) {
+ warnf(config->global, "curl_mime_type failed!\n");
+ Curl_safefree(contents);
+ return 8;
+ }
+ }
+ else if(!name && !strcmp(contp, ")") && !literal_value) {
+ /* Ending a mutipart. */
+ if(*mimecurrent == *mimepost) {
+ warnf(config->global, "no multipart to terminate!\n");
+ Curl_safefree(contents);
+ return 9;
+ }
+ *mimecurrent = (*mimecurrent)->parent->parent;
+ }
+ else if('@' == contp[0] && !literal_value) {
- struct multi_files *multi_start = NULL;
- struct multi_files *multi_current = NULL;
+ /* we use the @-letter to indicate file name(s) */
- char *ptr = contp;
- char *end = ptr + strlen(ptr);
+ curl_mime *subparts = NULL;
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->global,
- "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 = 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;
+ ++contp;
+ sep = get_param_part(config, &contp,
+ &data, &type, &filename, &encoder, &headers);
+ if(sep < 0) {
+ if(subparts != *mimecurrent)
+ curl_mime_free(subparts);
+ Curl_safefree(contents);
+ return 10;
+ }
- 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';
- }
+ /* now contp point to comma or string end.
+ If more files to come, make sure we have multiparts. */
+ if(!subparts) {
+ if(sep != ',') /* If there is a single file. */
+ subparts = *mimecurrent;
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->global, "skip unknown form field: %s\n", unknown);
+ subparts = curl_mime_init(config->easy);
+ if(!subparts) {
+ warnf(config->global, "curl_mime_init failed!\n");
+ curl_slist_free_all(headers);
+ Curl_safefree(contents);
+ return 11;
}
}
}
- /* now ptr point to comma or string end */
+ /* Allocate a part for that file. */
+ part = curl_mime_addpart(subparts);
+ if(!part) {
+ warnf(config->global, "curl_mime_addpart failed!\n");
+ if(subparts != *mimecurrent)
+ curl_mime_free(subparts);
+ curl_slist_free_all(headers);
+ Curl_safefree(contents);
+ return 12;
+ }
- /* if type == NULL curl_formadd takes care of the problem */
+ /* Set part headers. */
+ if(curl_mime_headers(part, headers, 1)) {
+ warnf(config->global, "curl_mime_headers failed!\n");
+ if(subparts != *mimecurrent)
+ curl_mime_free(subparts);
+ curl_slist_free_all(headers);
+ Curl_safefree(contents);
+ return 13;
+ }
- if(*contp && !AddMultiFiles(contp, type, filename, &multi_start,
- &multi_current)) {
- warnf(config->global, "Error building form post!\n");
+ /* Setup file in part. */
+ res = file_or_stdin(part, data);
+ if(res) {
+ warnf(config->global, "setting file %s failed!\n", data);
+ if(res != CURLE_READ_ERROR) {
+ if(subparts != *mimecurrent)
+ curl_mime_free(subparts);
+ Curl_safefree(contents);
+ return 14;
+ }
+ }
+ if(filename && curl_mime_filename(part, filename)) {
+ warnf(config->global, "curl_mime_filename failed!\n");
+ if(subparts != *mimecurrent)
+ curl_mime_free(subparts);
Curl_safefree(contents);
- FreeMultiInfo(&multi_start, &multi_current);
- return 3;
+ return 15;
+ }
+ if(curl_mime_type(part, type)) {
+ warnf(config->global, "curl_mime_type failed!\n");
+ if(subparts != *mimecurrent)
+ curl_mime_free(subparts);
+ Curl_safefree(contents);
+ return 16;
+ }
+ if(curl_mime_encoder(part, encoder)) {
+ warnf(config->global, "curl_mime_encoder failed!\n");
+ if(subparts != *mimecurrent)
+ curl_mime_free(subparts);
+ Curl_safefree(contents);
+ return 17;
}
- /* *ptr could be '\0', so we just check with the string end */
- } while(ptr < end); /* loop if there's another file name */
+ /* *contp could be '\0', so we just check with the delimiter */
+ } while(sep); /* 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");
+ if(subparts != *mimecurrent) {
+ part = curl_mime_addpart(*mimecurrent);
+ if(!part) {
+ warnf(config->global, "curl_mime_addpart failed!\n");
+ curl_mime_free(subparts);
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;
+ return 18;
}
- 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->global, "curl_formadd failed!\n");
- Curl_safefree(forms);
+ if(curl_mime_subparts(part, subparts)) {
+ warnf(config->global, "curl_mime_subparts failed!\n");
+ curl_mime_free(subparts);
Curl_safefree(contents);
- return 5;
+ return 19;
}
- 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 */
- }
+ /* Allocate a mime part. */
+ part = curl_mime_addpart(*mimecurrent);
+ if(!part) {
+ warnf(config->global, "curl_mime_addpart failed!\n");
+ Curl_safefree(contents);
+ return 20;
+ }
- if(contp[0]=='<' && !literal_value) {
- info[i].option = CURLFORM_FILECONTENT;
- info[i].value = contp+1;
- i++;
- info[i].option = CURLFORM_END;
+ if(*contp == '<' && !literal_value) {
+ ++contp;
+ sep = get_param_part(config, &contp,
+ &data, &type, &filename, &encoder, &headers);
+ if(sep < 0) {
+ Curl_safefree(contents);
+ return 21;
+ }
- if(curl_formadd(httppost, last_post,
- CURLFORM_ARRAY, info, CURLFORM_END) != 0) {
- warnf(config->global, "curl_formadd failed, possibly the file %s is "
- "bad!\n", contp + 1);
+ /* Set part headers. */
+ if(curl_mime_headers(part, headers, 1)) {
+ warnf(config->global, "curl_mime_headers failed!\n");
+ curl_slist_free_all(headers);
Curl_safefree(contents);
- return 6;
+ return 22;
+ }
+
+ /* Setup file in part. */
+ res = file_or_stdin(part, data);
+ if(res) {
+ warnf(config->global, "setting file %s failed!\n", data);
+ if(res != CURLE_READ_ERROR) {
+ Curl_safefree(contents);
+ return 23;
+ }
}
}
else {
+ if(literal_value)
+ data = contp;
+ else {
+ sep = get_param_part(config, &contp,
+ &data, &type, &filename, &encoder, &headers);
+ if(sep < 0) {
+ Curl_safefree(contents);
+ return 24;
+ }
+ }
+
+ /* Set part headers. */
+ if(curl_mime_headers(part, headers, 1)) {
+ warnf(config->global, "curl_mime_headers failed!\n");
+ curl_slist_free_all(headers);
+ Curl_safefree(contents);
+ return 25;
+ }
+
#ifdef CURL_DOES_CONVERSIONS
- if(convert_to_network(contp, strlen(contp))) {
+ if(convert_to_network(data, strlen(data))) {
warnf(config->global, "curl_formadd failed!\n");
Curl_safefree(contents);
- return 7;
+ return 26;
}
#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->global, "curl_formadd failed!\n");
+
+ if(curl_mime_data(part, data, CURL_ZERO_TERMINATED)) {
+ warnf(config->global, "curl_mime_data failed!\n");
Curl_safefree(contents);
- return 8;
+ return 27;
}
}
+
+ if(curl_mime_filename(part, filename)) {
+ warnf(config->global, "curl_mime_filename failed!\n");
+ Curl_safefree(contents);
+ return 28;
+ }
+ if(curl_mime_type(part, type)) {
+ warnf(config->global, "curl_mime_type failed!\n");
+ Curl_safefree(contents);
+ return 29;
+ }
+ if(curl_mime_encoder(part, encoder)) {
+ warnf(config->global, "curl_mime_encoder failed!\n");
+ Curl_safefree(contents);
+ return 30;
+ }
+
+ if(sep) {
+ *contp = (char) sep;
+ warnf(config->global,
+ "garbage at end of field specification: %s\n", contp);
+ }
}
+ /* Set part name. */
+ if(name && curl_mime_name(part, name)) {
+ warnf(config->global, "curl_mime_name failed!\n");
+ Curl_safefree(contents);
+ return 31;
+ }
}
else {
warnf(config->global, "Illegally formatted input field!\n");
- return 1;
+ Curl_safefree(contents);
+ return 32;
}
Curl_safefree(contents);
return 0;
diff --git a/src/tool_formparse.h b/src/tool_formparse.h
index ce7a29256..a52b98d39 100644
--- a/src/tool_formparse.h
+++ b/src/tool_formparse.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,8 +25,8 @@
int formparse(struct OperationConfig *config,
const char *input,
- struct curl_httppost **httppost,
- struct curl_httppost **last_post,
+ curl_mime **mimepost,
+ curl_mime **mimecurrent,
bool literal_value);
#endif /* HEADER_CURL_TOOL_FORMPARSE_H */
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index b7ee519b3..b65c45732 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -188,6 +188,7 @@ static const struct LongShort aliases[]= {
{"$W", "abstract-unix-socket", ARG_STRING},
{"$X", "tls-max", ARG_STRING},
{"$Y", "suppress-connect-headers", ARG_BOOL},
+ {"$Z", "compressed-ssh", ARG_BOOL},
{"0", "http1.0", ARG_NONE},
{"01", "http1.1", ARG_NONE},
{"02", "http2", ARG_NONE},
@@ -448,7 +449,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(('-' != flag[0]) ||
(('-' == flag[0]) && ('-' == flag[1]))) {
/* this should be a long name */
- const char *word = ('-' == flag[0]) ? flag+2 : flag;
+ const char *word = ('-' == flag[0]) ? flag + 2 : flag;
size_t fnam = strlen(word);
int numhits = 0;
@@ -491,7 +492,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(!longopt) {
letter = (char)*parse;
- subletter='\0';
+ subletter = '\0';
}
else {
letter = parse[0];
@@ -590,7 +591,11 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
{
/* We support G, M, K too */
char *unit;
- curl_off_t value = curlx_strtoofft(nextarg, &unit, 0);
+ curl_off_t value;
+ if(curlx_strtoofft(nextarg, &unit, 0, &value)) {
+ warnf(global, "unsupported rate\n");
+ return PARAM_BAD_USE;
+ }
if(!*unit)
unit = (char *)"b";
@@ -999,7 +1004,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
#ifdef USE_METALINK
int mlmaj, mlmin, mlpatch;
metalink_get_version(&mlmaj, &mlmin, &mlpatch);
- if((mlmaj*10000)+(mlmin*100)+mlpatch < CURL_REQ_LIBMETALINK_VERS) {
+ if((mlmaj*10000)+(mlmin*100) + mlpatch < CURL_REQ_LIBMETALINK_VERS) {
warnf(global,
"--metalink option cannot be used because the version of "
"the linked libmetalink library is too old. "
@@ -1072,6 +1077,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
case 'Y': /* --suppress-connect-headers */
config->suppress_connect_headers = toggle;
break;
+ case 'Z': /* --compressed-ssh */
+ config->ssh_compression = toggle;
+ break;
}
break;
case '#': /* --progress-bar */
@@ -1182,7 +1190,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
config->resume_from_current = TRUE;
config->resume_from = 0;
}
- config->use_resume=TRUE;
+ config->use_resume = TRUE;
break;
case 'd':
/* postfield data */
@@ -1346,11 +1354,11 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
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';
+ memcpy(&config->postfields[oldlen + 1], postdata, size);
+ config->postfields[oldlen + 1 + size] = '\0';
Curl_safefree(oldpost);
Curl_safefree(postdata);
- config->postfieldsize += size+1;
+ config->postfieldsize += size + 1;
}
else {
config->postfields = postdata;
@@ -1598,11 +1606,11 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
to sort this out slowly and carefully */
if(formparse(config,
nextarg,
- &config->httppost,
- &config->last_post,
- (subletter=='s')?TRUE:FALSE)) /* 's' means literal string */
+ &config->mimepost,
+ &config->mimecurrent,
+ (subletter == 's')?TRUE:FALSE)) /* 's' is literal string */
return PARAM_BAD_USE;
- if(SetHTTPrequest(config, HTTPREQ_FORMPOST, &config->httpreq))
+ if(SetHTTPrequest(config, HTTPREQ_MIMEPOST, &config->httpreq))
return PARAM_BAD_USE;
break;
@@ -1843,10 +1851,13 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
char buffer[32];
curl_off_t off;
+ if(curlx_strtoofft(nextarg, NULL, 10, &off)) {
+ warnf(global, "unsupported range point\n");
+ return PARAM_BAD_USE;
+ }
warnf(global,
"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);
@@ -2042,7 +2053,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
break;
}
now = time(NULL);
- config->condtime=curl_getdate(nextarg, &now);
+ 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;
diff --git a/src/tool_help.c b/src/tool_help.c
index 42dc77959..486f65dc8 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -54,7 +54,7 @@ static const struct helptxt helptext[] = {
"Append to target file when uploading"},
{" --basic",
"Use HTTP Basic Authentication"},
- {" --cacert <CA certificate>",
+ {" --cacert <file>",
"CA certificate to verify peer against"},
{" --capath <dir>",
"CA directory to verify peer against"},
@@ -68,6 +68,8 @@ static const struct helptxt helptext[] = {
"SSL ciphers to use"},
{" --compressed",
"Request compressed response"},
+ {" --compressed-ssh",
+ "Enable SSH compression"},
{"-K, --config <file>",
"Read config from a file"},
{" --connect-timeout <seconds>",
@@ -129,9 +131,9 @@ static const struct helptxt helptext[] = {
{" --false-start",
"Enable TLS False Start"},
{"-F, --form <name=content>",
- "Specify HTTP multipart POST data"},
+ "Specify multipart MIME data"},
{" --form-string <name=string>",
- "Specify HTTP multipart POST data"},
+ "Specify multipart MIME data"},
{" --ftp-account <data>",
"Account data string"},
{" --ftp-alternative-to-user <command>",
@@ -501,7 +503,8 @@ static const struct feat feats[] = {
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
{"HTTP2", CURL_VERSION_HTTP2},
{"UnixSockets", CURL_VERSION_UNIX_SOCKETS},
- {"HTTPS-proxy", CURL_VERSION_HTTPS_PROXY}
+ {"HTTPS-proxy", CURL_VERSION_HTTPS_PROXY},
+ {"MultiSSL", CURL_VERSION_MULTI_SSL}
};
void tool_help(void)
diff --git a/src/tool_main.c b/src/tool_main.c
index 089a317d4..4e78d3321 100644
--- a/src/tool_main.c
+++ b/src/tool_main.c
@@ -62,6 +62,15 @@
int vms_show = 0;
#endif
+#ifdef __MINGW32__
+/*
+ * There seems to be no way to escape "*" in command-line arguments with MinGW
+ * when command-line argument globbing is enabled under the MSYS shell, so turn
+ * it off.
+ */
+int _CRT_glob = 0;
+#endif /* __MINGW32__ */
+
/* if we build a static library for unit tests, there is no main() function */
#ifndef UNITTESTS
diff --git a/src/tool_metalink.c b/src/tool_metalink.c
index 3f66c7470..270345547 100644
--- a/src/tool_metalink.c
+++ b/src/tool_metalink.c
@@ -30,6 +30,8 @@
# include <fcntl.h>
#endif
+#undef HAVE_NSS_CONTEXT
+
#ifdef USE_OPENSSL
# include <openssl/md5.h>
# include <openssl/sha.h>
@@ -50,6 +52,7 @@
# define MD5_CTX void *
# define SHA_CTX void *
# define SHA256_CTX void *
+# define HAVE_NSS_CONTEXT
static NSSInitContext *nss_context;
#elif defined(USE_POLARSSL)
# include <polarssl/md5.h>
@@ -117,7 +120,9 @@ struct win32_crypto_hash {
return PARAM_NO_MEM; \
} WHILE_FALSE
-#ifdef USE_GNUTLS_NETTLE
+#if defined(USE_OPENSSL)
+/* Functions are already defined */
+#elif defined(USE_GNUTLS_NETTLE)
static int MD5_Init(MD5_CTX *ctx)
{
@@ -375,7 +380,7 @@ static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
sha256_finish(ctx, digest);
}
-#elif defined(_WIN32) && !defined(USE_OPENSSL)
+#elif defined(_WIN32)
static void win32_crypto_final(struct win32_crypto_hash *ctx,
unsigned char *digest,
@@ -678,7 +683,7 @@ static metalink_checksum *new_metalink_checksum_from_hex_digest
return 0;
for(i = 0; i < len; i += 2) {
- digest[i/2] = hex_to_uint(hex_digest+i);
+ digest[i/2] = hex_to_uint(hex_digest + i);
}
chksum = malloc(sizeof(metalink_checksum));
if(chksum) {
@@ -880,7 +885,7 @@ size_t metalink_write_cb(void *buffer, size_t sz, size_t nmemb,
if(!config)
return failure;
- rv = metalink_parse_update(outs->metalink_parser, buffer, sz *nmemb);
+ rv = metalink_parse_update(outs->metalink_parser, buffer, sz * nmemb);
if(rv == 0)
return sz * nmemb;
else {
@@ -901,8 +906,8 @@ static int check_content_type(const char *content_type, const char *media_type)
return 0;
}
return curl_strnequal(ptr, media_type, media_type_len) &&
- (*(ptr+media_type_len) == '\0' || *(ptr+media_type_len) == ' ' ||
- *(ptr+media_type_len) == '\t' || *(ptr+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)
@@ -965,7 +970,7 @@ void clean_metalink(struct OperationConfig *config)
void metalink_cleanup(void)
{
-#ifdef USE_NSS
+#ifdef HAVE_NSS_CONTEXT
if(nss_context) {
NSS_ShutdownContext(nss_context);
nss_context = NULL;
diff --git a/src/tool_mfiles.c b/src/tool_mfiles.c
deleted file mode 100644
index d862d4140..000000000
--- a/src/tool_mfiles.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * 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 https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under 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/src/tool_msgs.c b/src/tool_msgs.c
index d06708a18..07bf81292 100644
--- a/src/tool_msgs.c
+++ b/src/tool_msgs.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -63,7 +63,7 @@ static void voutf(struct GlobalConfig *config,
(void)fwrite(ptr, cut + 1, 1, config->errors);
fputs("\n", config->errors);
- ptr += cut+1; /* skip the space too */
+ ptr += cut + 1; /* skip the space too */
len -= cut;
}
else {
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 1e8d0073c..5401955af 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -92,21 +92,12 @@ CURLcode curl_easy_perform_ev(CURL *easy);
# define O_BINARY 0
#endif
-#define CURL_CA_CERT_ERRORMSG1 \
- "More details here: https://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"
+#define CURL_CA_CERT_ERRORMSG \
+ "More details here: https://curl.haxx.se/docs/sslcerts.html\n\n" \
+ "curl failed to verify the legitimacy of the server and therefore " \
+ "could not\nestablish a secure connection to it. To learn more about " \
+ "this situation and\nhow to fix it, please visit the web page mentioned " \
+ "above.\n"
static bool is_fatal_error(CURLcode code)
{
@@ -184,7 +175,7 @@ static curl_off_t VmsSpecialSize(const char *name,
#endif /* __VMS */
#if defined(HAVE_UTIME) || \
- (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8))
+ (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
static void setfiletime(long filetime, const char *filename,
FILE *error_stream)
{
@@ -192,10 +183,10 @@ static void setfiletime(long filetime, const char *filename,
/* Windows utime() may attempt to adjust our unix gmt 'filetime' by a daylight
saving time offset and since it's GMT that is bad behavior. When we have
access to a 64-bit type we can bypass utime and set the times directly. */
-#if defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)
+#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
HANDLE hfile;
-#if (CURL_SIZEOF_LONG >= 8)
+#if (SIZEOF_LONG >= 8)
/* 910670515199 is the maximum unix filetime that can be used as a
Windows FILETIME without overflow: 30827-12-31T23:59:59. */
if(filetime > CURL_OFF_T_C(910670515199)) {
@@ -204,7 +195,7 @@ static void setfiletime(long filetime, const char *filename,
filetime);
return;
}
-#endif /* CURL_SIZEOF_LONG >= 8 */
+#endif /* SIZEOF_LONG >= 8 */
hfile = CreateFileA(filename, FILE_WRITE_ATTRIBUTES,
(FILE_SHARE_READ | FILE_SHARE_WRITE |
@@ -254,7 +245,7 @@ static void setfiletime(long filetime, const char *filename,
}
}
#endif /* defined(HAVE_UTIME) || \
- (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */
+ (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
#define BUFFER_SIZE (100*1024)
@@ -534,7 +525,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
urlnum = 1; /* without globbing, this is a single URL */
/* if multiple files extracted to stdout, insert separators! */
- separator= ((!outfiles || !strcmp(outfiles, "-")) && urlnum > 1);
+ separator = ((!outfiles || !strcmp(outfiles, "-")) && urlnum > 1);
/* Here's looping around each globbed URL */
for(li = 0 ; li < urlnum; li++) {
@@ -809,7 +800,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
if(urlnum > 1 && !global->mute) {
fprintf(global->errors, "\n[%lu/%lu]: %s --> %s\n",
- li+1, urlnum, this_url, outfile ? outfile : "<stdout>");
+ li + 1, urlnum, this_url, outfile ? outfile : "<stdout>");
if(separator)
printf("%s%s\n", CURLseparator, this_url);
}
@@ -831,7 +822,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
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='&';
+ sep = '&';
}
/*
* Then append ? followed by the get fields to the url.
@@ -995,6 +986,31 @@ static CURLcode operate_do(struct GlobalConfig *global,
my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
+ 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_MIMEPOST:
+ my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
+ break;
+ default:
+ break;
+ }
+
+ /* new in libcurl 7.10.6 (default is Basic) */
+ if(config->authtype)
+ my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype);
+
+ my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
+
+ if(built_in_protos & (CURLPROTO_HTTP | CURLPROTO_RTSP)) {
+ my_setopt_str(curl, CURLOPT_REFERER, config->referer);
+ my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
+ }
+
if(built_in_protos & CURLPROTO_HTTP) {
long postRedir = 0;
@@ -1004,24 +1020,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
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_FORMPOST:
- 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) {
@@ -1038,10 +1037,6 @@ static CURLcode operate_do(struct GlobalConfig *global,
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
}
- /* 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)
@@ -1091,6 +1086,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
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);
+
+ /* new in libcurl 7.56.0 */
+ if(config->ssh_compression)
+ my_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L);
}
if(config->cacert)
@@ -1673,6 +1672,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
retry_sleep = RETRY_SLEEP_MAX;
}
if(outs.bytes && outs.filename && outs.stream) {
+ int rc;
/* We have written data to a output file, we truncate file
*/
if(!global->mute)
@@ -1693,14 +1693,21 @@ static CURLcode operate_do(struct GlobalConfig *global,
}
/* 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);
+ rc = 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);
+ rc = fseek(outs.stream, (long)outs.init, SEEK_SET);
#endif
+ if(rc) {
+ if(!global->mute)
+ fprintf(global->errors,
+ "failed seeking to end of file, exiting\n");
+ result = CURLE_WRITE_ERROR;
+ goto quit_urls;
+ }
outs.bytes = 0; /* clear for next round */
}
continue; /* curl_easy_perform loop */
@@ -1780,12 +1787,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
fprintf(global->errors, "curl: (%d) %s\n", result, (errorbuffer[0]) ?
errorbuffer : curl_easy_strerror(result));
if(result == CURLE_SSL_CACERT)
- fprintf(global->errors, "%s%s%s",
- CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2,
- ((curlinfo->features & CURL_VERSION_HTTPS_PROXY) ?
- "HTTPS-proxy has similar options --proxy-cacert "
- "and --proxy-insecure.\n" :
- ""));
+ fputs(CURL_CA_CERT_ERRORMSG, global->errors);
}
/* Fall through comment to 'quit_urls' label */
@@ -1840,7 +1842,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
#endif
#if defined(HAVE_UTIME) || \
- (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8))
+ (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
/* File time can only be set _after_ the file has been closed */
if(!result && config->remote_time && outs.s_isreg && outs.filename) {
/* Ask libcurl if we got a remote file time */
@@ -1850,7 +1852,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
setfiletime(filetime, outs.filename, config->global->errors);
}
#endif /* defined(HAVE_UTIME) || \
- (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */
+ (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
#ifdef USE_METALINK
if(!metalink && config->use_metalink && result == CURLE_OK) {
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
index 85c5e79a7..7cddf51ce 100644
--- a/src/tool_paramhlp.c
+++ b/src/tool_paramhlp.c
@@ -73,13 +73,13 @@ ParameterError file2string(char **bufp, FILE *file)
if(ptr)
*ptr = '\0';
buflen = strlen(buffer);
- ptr = realloc(string, stringlen+buflen+1);
+ ptr = realloc(string, stringlen + buflen + 1);
if(!ptr) {
Curl_safefree(string);
return PARAM_NO_MEM;
}
string = ptr;
- strcpy(string+stringlen, buffer);
+ strcpy(string + stringlen, buffer);
stringlen += buflen;
}
}
@@ -99,27 +99,27 @@ ParameterError file2memory(char **bufp, size_t *size, FILE *file)
do {
if(!buffer || (alloc == nused)) {
/* size_t overflow detection for huge files */
- if(alloc+1 > ((size_t)-1)/2) {
+ 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 */
- newbuf = realloc(buffer, alloc+1);
+ newbuf = realloc(buffer, alloc + 1);
if(!newbuf) {
Curl_safefree(buffer);
return PARAM_NO_MEM;
}
buffer = newbuf;
}
- nread = fread(buffer+nused, 1, alloc-nused, file);
+ 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) {
- newbuf = realloc(buffer, nused+1);
+ newbuf = realloc(buffer, nused + 1);
if(!newbuf) {
Curl_safefree(buffer);
return PARAM_NO_MEM;
@@ -242,14 +242,16 @@ static ParameterError str2double(double *val, const char *str, long max)
* data.
*/
-ParameterError str2udouble(double *val, const char *str, long max)
+ParameterError str2udouble(double *valp, const char *str, long max)
{
- ParameterError result = str2double(val, str, max);
+ double value;
+ ParameterError result = str2double(&value, str, max);
if(result != PARAM_OK)
return result;
- if(*val < 0)
+ if(value < 0)
return PARAM_NEGATIVE_NUMERIC;
+ *valp = value;
return PARAM_OK;
}
@@ -334,7 +336,7 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
}
}
- for(pp=protos; pp->name; pp++) {
+ for(pp = protos; pp->name; pp++) {
if(curl_strequal(token, pp->name)) {
switch(action) {
case deny:
@@ -399,10 +401,14 @@ ParameterError str2offset(curl_off_t *val, const char *str)
/* 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_NUMBER_TOO_LARGE;
+#if(SIZEOF_CURL_OFF_T > SIZEOF_LONG)
+ {
+ CURLofft offt = curlx_strtoofft(str, &endptr, 0, val);
+ if(CURL_OFFT_FLOW == offt)
+ return PARAM_NUMBER_TOO_LARGE;
+ else if(CURL_OFFT_INVAL == offt)
+ return PARAM_BAD_NUMERIC;
+ }
#else
errno = 0;
*val = strtol(str, &endptr, 0);
@@ -470,7 +476,7 @@ static CURLcode checkpasswd(const char *kind, /* for what purpose */
/* append the password separated with a colon */
passptr[userlen] = ':';
- memcpy(&passptr[userlen+1], passwd, passwdlen+1);
+ memcpy(&passptr[userlen + 1], passwd, passwdlen + 1);
*userpwd = passptr;
}
diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c
index 93814f454..540bdb18a 100644
--- a/src/tool_parsecfg.c
+++ b/src/tool_parsecfg.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -131,7 +131,7 @@ int parseconfig(const char *filename, struct GlobalConfig *global)
while(NULL != (aline = my_get_line(file))) {
lineno++;
line = aline;
- alloced_param=FALSE;
+ alloced_param = FALSE;
/* line with # in the first non-blank column is a comment! */
while(*line && ISSPACE(*line))
diff --git a/src/tool_sdecls.h b/src/tool_sdecls.h
index a56390e59..48dd4aed9 100644
--- a/src/tool_sdecls.h
+++ b/src/tool_sdecls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -135,7 +135,7 @@ typedef enum {
HTTPREQ_UNSPEC, /* first in list */
HTTPREQ_GET,
HTTPREQ_HEAD,
- HTTPREQ_FORMPOST,
+ HTTPREQ_MIMEPOST,
HTTPREQ_SIMPLEPOST
} HttpReq;
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
index 694d3ffa5..fb2cb66d3 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,9 @@
#include "tool_cfgable.h"
#include "tool_easysrc.h"
#include "tool_setopt.h"
+#include "tool_convert.h"
+#include "mime.h"
#include "memdebug.h" /* keep this as LAST include */
/* Lookup tables for converting setopt values back to symbols */
@@ -208,37 +210,43 @@ static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
/* 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)
+static char *c_escape(const char *str, size_t len)
{
- size_t len = 0;
const char *s;
unsigned char c;
char *escaped, *e;
+
+ if(len == CURL_ZERO_TERMINATED)
+ len = strlen(str);
+
+ /* Check for possible overflow. */
+ if(len > (~(size_t) 0) / 4)
+ return NULL;
+
/* 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') {
+ for(s = str; (c = *s) != '\0'; s++) {
+ if(c == '\n') {
strcpy(e, "\\n");
e += 2;
}
- else if(c=='\r') {
+ else if(c == '\r') {
strcpy(e, "\\r");
e += 2;
}
- else if(c=='\t') {
+ else if(c == '\t') {
strcpy(e, "\\t");
e += 2;
}
- else if(c=='\\') {
+ else if(c == '\\') {
strcpy(e, "\\\\");
e += 2;
}
- else if(c=='"') {
+ else if(c == '"') {
strcpy(e, "\\\"");
e += 2;
}
@@ -268,7 +276,7 @@ CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
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++) {
+ for(nv = nvlist; nv->name; nv++) {
if(nv->value == lval) break; /* found it */
}
if(! nv->name) {
@@ -305,7 +313,7 @@ CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
const NameValue *nv = NULL;
snprintf(preamble, sizeof(preamble),
"curl_easy_setopt(hnd, %s, ", name);
- for(nv=nvlist; nv->name; nv++) {
+ for(nv = nvlist; nv->name; nv++) {
if((nv->value & ~ rest) == 0) {
/* all value flags contained in rest */
rest &= ~ nv->value; /* remove bits handled here */
@@ -348,7 +356,7 @@ CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
const NameValueUnsigned *nv = NULL;
snprintf(preamble, sizeof(preamble),
"curl_easy_setopt(hnd, %s, ", name);
- for(nv=nvlist; nv->name; nv++) {
+ for(nv = nvlist; nv->name; nv++) {
if((nv->value & ~ rest) == 0) {
/* all value flags contained in rest */
rest &= ~ nv->value; /* remove bits handled here */
@@ -371,118 +379,225 @@ CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
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)
+/* Generate code for a struct curl_slist. */
+static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
{
CURLcode ret = CURLE_OK;
char *escaped = NULL;
- bool skip = FALSE;
- ret = curl_easy_setopt(curl, tag, post);
- if(!post)
- skip = TRUE;
+ /* May need several slist variables, so invent name */
+ *slistno = ++easysrc_slist_count;
+
+ DECL1("struct curl_slist *slist%d;", *slistno);
+ DATA1("slist%d = NULL;", *slistno);
+ CLEAN1("curl_slist_free_all(slist%d);", *slistno);
+ CLEAN1("slist%d = NULL;", *slistno);
+ for(; slist; slist = slist->next) {
+ Curl_safefree(escaped);
+ escaped = c_escape(slist->data, CURL_ZERO_TERMINATED);
+ if(!escaped)
+ return CURLE_OUT_OF_MEMORY;
+ DATA3("slist%d = curl_slist_append(slist%d, \"%s\");",
+ *slistno, *slistno, escaped);
+ }
- 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 */
+ nomem:
+ Curl_safefree(escaped);
+ return ret;
+}
+
+/* Generate source code for a mime structure. */
+static CURLcode libcurl_generate_mime(curl_mime *mime, int *mimeno)
+{
+ CURLcode ret = CURLE_OK;
+ int i;
+ curl_off_t size;
+ curl_mimepart *part;
+ char *filename;
+ char *escaped = NULL;
+ char *cp;
+ char *data;
+
+ /* May need several mime variables, so invent name */
+ *mimeno = ++easysrc_mime_count;
+
+ DECL1("curl_mime *mime%d;", *mimeno);
+ DATA1("mime%d = NULL;", *mimeno);
+ CODE1("mime%d = curl_mime_init(hnd);", *mimeno);
+ CLEAN1("curl_mime_free(mime%d);", *mimeno);
+ CLEAN1("mime%d = NULL;", *mimeno);
+ if(mime->firstpart) {
+ DECL1("curl_mimepart *part%d;", *mimeno);
+ for(part = mime->firstpart; part; part = part->nextpart) {
+ CODE2("part%d = curl_mime_addpart(mime%d);", *mimeno, *mimeno);
+ filename = part->filename;
+ switch(part->kind) {
+ case MIMEKIND_FILE:
Curl_safefree(escaped);
- escaped = c_escape(pp->contents);
- if(!escaped) {
- ret = CURLE_OUT_OF_MEMORY;
- goto nomem;
- }
- if(pp->flags & CURL_HTTPPOST_FILENAME) {
- /* file upload as for -F @filename */
- DATA1(" CURLFORM_FILE, \"%s\",", escaped);
+ escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
+ if(!escaped)
+ return CURLE_OUT_OF_MEMORY;
+ CODE2("curl_mime_filedata(part%d, \"%s\");", *mimeno, escaped);
+ if(!filename)
+ CODE1("curl_mime_filename(part%d, NULL);", *mimeno);
+ else {
+ /* Fast check to see if remote file name is base name. */
+ filename = part->data;
+ for(cp = filename; *cp; cp++)
+ if(*cp == '/' || *cp == '\\')
+ filename = cp + 1;
+ if(!part->filename || !strcmp(filename, part->filename))
+ filename = NULL;
+ else
+ filename = part->filename;
}
- else if(pp->flags & CURL_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) {
+ break;
+ case MIMEKIND_CALLBACK:
+ /* Can only be reading stdin in the current context. */
+ CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
+ *mimeno);
+ CODE0(" (curl_seek_callback) fseek, NULL, stdin);");
+ break;
+ case MIMEKIND_DATA:
+#ifdef CURL_DOES_CONVERSIONS
+ /* Data is stored in ASCII and we want in in the host character
+ code. Convert it back for output. */
+ data = malloc(part->datasize + 1);
+ if(!data) {
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;
+ memcpy(data, part->data, part->datasize + 1);
+ ret = convert_from_network(data, strlen(data));
+ if(ret) {
+ Curl_safefree(data);
goto nomem;
}
- DATA1(" CURLFORM_CONTENTTYPE, \"%s\",", escaped);
- }
+#else
+ data = part->data;
+#endif
+
+ /* Are there any nul byte in data? */
+ for(cp = data; *cp; cp++)
+ ;
+ size = (cp == data + part->datasize)? (curl_off_t) -1: part->datasize;
+ Curl_safefree(escaped);
+ escaped = c_escape(data, (size_t) part->datasize);
+#ifdef CURL_DOES_CONVERSIONS
+ Curl_safefree(data);
+#endif
+ if(!escaped)
+ return CURLE_OUT_OF_MEMORY;
+ if(size >= 0)
+ CODE3("curl_mime_data(part%d, \"%s\", %" CURL_FORMAT_CURL_OFF_T ");",
+ *mimeno, escaped, size);
+ else
+ CODE2("curl_mime_data(part%d, \"%s\", CURL_ZERO_TERMINATED);",
+ *mimeno, escaped);
+ break;
+ case MIMEKIND_MULTIPART:
+ ret = libcurl_generate_mime(part->arg, &i);
+ if(ret)
+ goto nomem;
+ CODE2("curl_mime_subparts(part%d, mime%d);", *mimeno, i);
+ CODE1("mime%d = NULL;", i); /* Avoid freeing in CLEAN sequence. */
+ break;
+ default:
+ /* Other cases not possible in this context. */
+ break;
+ }
+
+ if(part->encoder) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->encoder->name, CURL_ZERO_TERMINATED);
+ if(!escaped)
+ return CURLE_OUT_OF_MEMORY;
+ CODE2("curl_mime_encoder(part%d, \"%s\");", *mimeno, escaped);
+ }
+
+ if(filename) {
+ Curl_safefree(escaped);
+ escaped = c_escape(filename, CURL_ZERO_TERMINATED);
+ if(!escaped)
+ return CURLE_OUT_OF_MEMORY;
+ CODE2("curl_mime_filename(part%d, \"%s\");", *mimeno, escaped);
+ }
+
+ if(part->name) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
+ if(!escaped)
+ return CURLE_OUT_OF_MEMORY;
+ CODE2("curl_mime_name(part%d, \"%s\");", *mimeno, escaped);
+ }
+
+ if(part->mimetype) {
+ Curl_safefree(escaped);
+ escaped = c_escape(part->mimetype, CURL_ZERO_TERMINATED);
+ if(!escaped)
+ return CURLE_OUT_OF_MEMORY;
+ CODE2("curl_mime_type(part%d, \"%s\");", *mimeno, escaped);
+ }
+
+ if(part->userheaders) {
+ int ownership = part->flags & MIME_USERHEADERS_OWNER? 1: 0;
+
+ ret = libcurl_generate_slist(part->userheaders, &i);
+ if(ret)
+ goto nomem;
+ CODE3("curl_mime_headers(part%d, slist%d, %d);",
+ *mimeno, i, ownership);
+ if(ownership)
+ CODE1("slist%d = NULL;", i); /* Prevent freeing in CLEAN sequence. */
}
- DATA0(" CURLFORM_END);");
}
- CODE2("curl_easy_setopt(hnd, %s, post%d);", name, i);
}
- nomem:
+nomem:
Curl_safefree(escaped);
return ret;
}
+/* setopt wrapper for CURLOPT_MIMEPOST */
+CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
+ const char *name, CURLoption tag,
+ curl_mime *mimepost)
+{
+ CURLcode ret = CURLE_OK;
+
+ ret = curl_easy_setopt(curl, tag, mimepost);
+
+ if(config->libcurl && mimepost && !ret) {
+ int i;
+
+ ret = libcurl_generate_mime(mimepost, &i);
+
+ if(!ret)
+ CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, i);
+ }
+
+nomem:
+ 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;
+ if(config->libcurl && list && !ret) {
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);
+
+ ret = libcurl_generate_slist(list, &i);
+ if(!ret)
+ CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i);
}
nomem:
- Curl_safefree(escaped);
return ret;
}
@@ -507,7 +622,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
long lval = va_arg(arg, long);
long defval = 0L;
const NameValue *nv = NULL;
- for(nv=setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
+ for(nv = setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
if(!strcmp(name, nv->name)) {
defval = nv->value;
break; /* found it */
@@ -569,7 +684,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
REM2("%s set to a %s", name, value);
else {
if(escape) {
- escaped = c_escape(value);
+ escaped = c_escape(value, CURL_ZERO_TERMINATED);
if(!escaped) {
ret = CURLE_OUT_OF_MEMORY;
goto nomem;
diff --git a/src/tool_setopt.h b/src/tool_setopt.h
index da67deeb6..f8a52cd75 100644
--- a/src/tool_setopt.h
+++ b/src/tool_setopt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -85,9 +85,9 @@ CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
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,
+CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
- struct curl_httppost *httppost);
+ curl_mime *mimepost);
CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
struct curl_slist *list);
@@ -109,8 +109,8 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
#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_mimepost(x,y,z) \
+ SETOPT_CHECK(tool_setopt_mimepost(x, global, #y, y, z))
#define my_setopt_slist(x,y,z) \
SETOPT_CHECK(tool_setopt_slist(x, global, #y, y, z))
@@ -138,7 +138,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
#define my_setopt_bitmask(x,y,z) \
SETOPT_CHECK(curl_easy_setopt(x, y, z))
-#define my_setopt_httppost(x,y,z) \
+#define my_setopt_mimepost(x,y,z) \
SETOPT_CHECK(curl_easy_setopt(x, y, z))
#define my_setopt_slist(x,y,z) \
diff --git a/src/tool_strdup.c b/src/tool_strdup.c
index cb4a1c5f6..e6e151bd6 100644
--- a/src/tool_strdup.c
+++ b/src/tool_strdup.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,11 +35,11 @@ char *strdup(const char *str)
if(len >= ((size_t)-1) / sizeof(char))
return (char *)NULL;
- newstr = malloc((len+1)*sizeof(char));
+ newstr = malloc((len + 1)*sizeof(char));
if(!newstr)
return (char *)NULL;
- memcpy(newstr, str, (len+1)*sizeof(char));
+ memcpy(newstr, str, (len + 1)*sizeof(char));
return newstr;
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index d56dcd912..df85d7129 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -49,7 +49,7 @@ static CURLcode glob_fixed(URLGlob *glob, char *fixed, size_t len)
if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
- pat->content.Set.elements[0] = malloc(len+1);
+ pat->content.Set.elements[0] = malloc(len + 1);
if(!pat->content.Set.elements[0])
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
@@ -113,7 +113,7 @@ static CURLcode glob_set(URLGlob *glob, char **patternp,
CURLE_URL_MALFORMAT);
/* add 1 to size since it'll be incremented below */
- if(multiply(amount, pat->content.Set.size+1))
+ if(multiply(amount, pat->content.Set.size + 1))
return GLOBERROR("range overflow", 0, CURLE_URL_MALFORMAT);
/* fall-through */
@@ -207,7 +207,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
if(errno || &pattern[4] == endp || *endp != ']')
step = 0;
else
- pattern = endp+1;
+ pattern = endp + 1;
}
else if(end_c != ']')
/* then this is wrong */
@@ -259,12 +259,12 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
errno = 0;
min_n = strtoul(pattern, &endp, 10);
if(errno || (endp == pattern))
- endp=NULL;
+ endp = NULL;
else {
if(*endp != '-')
endp = NULL;
else {
- pattern = endp+1;
+ pattern = endp + 1;
while(*pattern && ISBLANK(*pattern))
pattern++;
if(!ISDIGIT(*pattern)) {
@@ -277,7 +277,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
/* overflow */
endp = NULL;
else if(*endp == ':') {
- pattern = endp+1;
+ pattern = endp + 1;
errno = 0;
step_n = strtoul(pattern, &endp, 10);
if(errno)
@@ -287,7 +287,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
else
step_n = 1;
if(endp && (*endp == ']')) {
- pattern= endp+1;
+ pattern = endp + 1;
}
else
endp = NULL;
@@ -384,8 +384,8 @@ static CURLcode glob_parse(URLGlob *glob, char *pattern,
/* only allow \ to escape known "special letters" */
if(*pattern == '\\' &&
- (*(pattern+1) == '{' || *(pattern+1) == '[' ||
- *(pattern+1) == '}' || *(pattern+1) == ']') ) {
+ (*(pattern + 1) == '{' || *(pattern + 1) == '[' ||
+ *(pattern + 1) == '}' || *(pattern + 1) == ']') ) {
/* escape character, skip '\' */
++pattern;
@@ -444,7 +444,7 @@ CURLcode glob_url(URLGlob **glob, char *url, unsigned long *urlnum,
glob_buffer = malloc(strlen(url) + 1);
if(!glob_buffer)
return CURLE_OUT_OF_MEMORY;
- glob_buffer[0]=0;
+ glob_buffer[0] = 0;
glob_expand = calloc(1, sizeof(URLGlob));
if(!glob_expand) {
@@ -623,12 +623,12 @@ CURLcode glob_match_url(char **result, char *filename, URLGlob *glob)
unsigned long i;
char *ptr = filename;
unsigned long num = strtoul(&filename[1], &filename, 10);
- URLPattern *pat =NULL;
+ URLPattern *pat = NULL;
if(num < glob->size) {
num--; /* make it zero based */
/* find the correct glob entry */
- for(i=0; i<glob->size; i++) {
+ for(i = 0; i<glob->size; i++) {
if(glob->pattern[i].globindex == (int)num) {
pat = &glob->pattern[i];
break;
diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT
index 75e561ae8..fbeee2a7e 100644
--- a/tests/FILEFORMAT
+++ b/tests/FILEFORMAT
@@ -74,6 +74,8 @@ B) The request was HTTP and included digest details, which adds 1000 to NUM
C) If a HTTP request is NTLM type-1, it adds 1001 to num
D) If a HTTP request is NTLM type-3, it adds 1002 to num
E) If a HTTP request is Basic and num is already >=1000, it adds 1 to num
+F) If a HTTP request is Negotiate, num gets incremented by one for each
+request with Negotiate authorization header on the same test case.
Dynamically changing num in this way allows the test harness to be used to
test authentication negotiation where several different requests must be sent
@@ -243,6 +245,7 @@ threaded-resolver
unittest
unix-sockets
WinSSL
+ld_preload
as well as each protocol that curl supports. A protocol only needs to be
specified if it is different from the server (useful when the server
diff --git a/tests/curl_test_data.py b/tests/curl_test_data.py
index bfe1287d8..21747407d 100755
--- a/tests/curl_test_data.py
+++ b/tests/curl_test_data.py
@@ -24,12 +24,15 @@
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import os
-import xml.etree.ElementTree as ET
+import re
import logging
log = logging.getLogger(__name__)
+REPLY_DATA = re.compile("<reply>\s*<data>(.*?)</data>", re.MULTILINE | re.DOTALL)
+
+
class TestData(object):
def __init__(self, data_folder):
self.data_folder = data_folder
@@ -39,15 +42,17 @@ class TestData(object):
filename = os.path.join(self.data_folder,
"test{0}".format(test_number))
- # The user should handle the exception from failing to find the file.
- tree = ET.parse(filename)
+ log.debug("Parsing file %s", filename)
+
+ with open(filename, "rb") as f:
+ contents = f.read().decode("utf-8")
- # We need the <reply><data> text.
- reply = tree.find("reply")
- data = reply.find("data")
+ m = REPLY_DATA.search(contents)
+ if not m:
+ raise Exception("Couldn't find a <reply><data> section")
- # Return the text contents of the data
- return data.text
+ # Left-strip the data so we don't get a newline before our data.
+ return m.group(1).lstrip()
if __name__ == '__main__':
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 103036040..4243c2183 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -71,13 +71,14 @@ test545 test546 test547 test548 test549 test550 test551 test552 test553 \
test554 test555 test556 test557 test558 test559 test560 test561 test562 \
test563 test564 test565 test566 test567 test568 test569 test570 test571 \
test572 test573 test574 test575 test576 test578 test579 test580 \
-test581 test582 test583 test584 test585 test586 test587 test588 \
+test581 test582 test583 test584 test585 test586 test587 test588 test589 \
test590 test591 test592 test593 test594 test595 test596 test597 test598 \
test599 test600 test601 test602 test603 test604 test605 test606 test607 \
test608 test609 test610 test611 test612 test613 test614 test615 test616 \
test617 test618 test619 test620 test621 test622 test623 test624 test625 \
test626 test627 test628 test629 test630 test631 test632 test633 test634 \
-test635 test636 test637 test638 test639 test640 test641 \
+test635 test636 test637 test638 test639 test640 test641 test642 \
+test643 test644 test645 test646 test647 test648 test649 test650 \
\
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 test711 test712 test713 test714 test715 \
@@ -87,7 +88,7 @@ test809 test810 test811 test812 test813 test814 test815 test816 test817 \
test818 test819 test820 test821 test822 test823 test824 test825 test826 \
test827 test828 test829 test830 test831 test832 test833 test834 test835 \
test836 test837 test838 test839 test840 test841 test842 test843 test844 \
-test845 \
+test845 test846 \
\
test850 test851 test852 test853 test854 test855 test856 test857 test858 \
test859 test860 test861 test862 test863 test864 test865 test866 test867 \
@@ -119,8 +120,11 @@ test1104 test1105 test1106 test1107 test1108 test1109 test1110 test1111 \
test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 \
test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \
test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \
-test1136 test1137 test1138 test1140 test1141 test1142 test1143 \
-test1144 test1145 test1146 test1147 test1148 \
+test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \
+test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
+test1152 test1153 \
+\
+test1160 test1161 \
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 \
@@ -154,8 +158,8 @@ test1416 test1417 test1418 test1419 test1420 test1421 test1422 test1423 \
test1424 test1425 test1426 test1427 \
test1428 test1429 test1430 test1431 test1432 test1433 test1434 test1435 \
test1436 test1437 test1438 test1439 test1440 test1441 test1442 test1443 \
-test1444 test1445 test1446 test1447 test1448 test1450 test1451 \
-test1452 \
+test1444 test1445 test1446 test1447 test1448 test1449 test1450 test1451 \
+test1452 test1453 \
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \
test1516 test1517 \
@@ -172,7 +176,7 @@ test1700 test1701 test1702 \
\
test1800 test1801 \
\
-test1900 test1901 test1902 test1903 \
+test1900 test1901 test1902 test1903 test1904 \
\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
@@ -180,4 +184,5 @@ test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \
-test2048 test2049 test2050 test2051 test2052 test2053 test2054 test2055
+test2048 test2049 test2050 test2051 test2052 test2053 test2054 test2055 \
+test2056 test2057
diff --git a/tests/data/test1053 b/tests/data/test1053
index 8c60e5ce3..239a1100f 100644
--- a/tests/data/test1053
+++ b/tests/data/test1053
@@ -79,7 +79,6 @@ User-Agent: curl/7.18.2 (i686-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.7a ipv6 z
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 410
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------9ef8d6205763
------------------------------9ef8d6205763
@@ -104,7 +103,6 @@ User-Agent: curl/7.18.2 (i686-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.7a ipv6 z
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 410
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------9ef8d6205763
------------------------------9ef8d6205763
diff --git a/tests/data/test1133 b/tests/data/test1133
index 8b016fc14..2238b9c07 100644
--- a/tests/data/test1133
+++ b/tests/data/test1133
@@ -47,8 +47,7 @@ POST /we/want/1133 HTTP/1.1
User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Host: %HOSTIP:%HTTPPORT
Accept: */*
-Content-Length: 967
-Expect: 100-continue
+Content-Length: 969
Content-Type: multipart/form-data; boundary=----------------------------24e78000bd32
------------------------------24e78000bd32
@@ -89,6 +88,7 @@ This is a bar foo
bar
foo
+
------------------------------24e78000bd32--
</protocol>
</verify>
diff --git a/tests/data/test1135 b/tests/data/test1135
index f7c6a7ae2..6a80ddf69 100644
--- a/tests/data/test1135
+++ b/tests/data/test1135
@@ -28,8 +28,20 @@ Verify CURL_EXTERN order
<verify>
<stdout>
-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);
+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);
+CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
+CURL_EXTERN void curl_mime_free(curl_mime *mime);
+CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
+CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name);
+CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
+CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
CURL_EXTERN void curl_formfree(struct curl_httppost *form);
@@ -43,6 +55,7 @@ CURL_EXTERN void curl_free(void *p);
CURL_EXTERN CURLcode curl_global_init(long flags);
CURL_EXTERN CURLcode curl_global_init_mem(long flags,
CURL_EXTERN void curl_global_cleanup(void);
+CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
diff --git a/tests/data/test1139 b/tests/data/test1139
new file mode 100644
index 000000000..72761c670
--- /dev/null
+++ b/tests/data/test1139
@@ -0,0 +1,27 @@
+<testcase>
+<info>
+<keywords>
+source analysis
+symbols-in-versions
+documentation
+--manual
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+
+ <name>
+Verify that all libcurl options have man pages
+ </name>
+
+<command type="perl">
+%SRCDIR/manpage-scan.pl %SRCDIR/.. %PWD/..
+</command>
+</client>
+
+</testcase>
diff --git a/tests/data/test1149 b/tests/data/test1149
new file mode 100644
index 000000000..ae081a8a9
--- /dev/null
+++ b/tests/data/test1149
@@ -0,0 +1,64 @@
+# based on test1010
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+LIST
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+# When doing LIST, we get the default list output hard-coded in the test
+# FTP server
+<datacheck mode="text">
+total 20
+drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
+drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
+drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
+-r--r--r-- 1 0 1 35 Jul 16 1996 README
+lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
+dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
+drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
+dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
+drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
+dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP dir list multicwd then again nocwd
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/list/this/path/1149/ --ftp-method multicwd --next ftp://%HOSTIP:%FTPPORT/list/this/path/1149/ --ftp-method nocwd
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PWD
+CWD list
+CWD this
+CWD path
+CWD 1149
+EPSV
+TYPE A
+LIST
+CWD /
+EPSV
+LIST list/this/path/1149/
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1150 b/tests/data/test1150
new file mode 100644
index 000000000..ecd95d57e
--- /dev/null
+++ b/tests/data/test1150
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP proxy
+</keywords>
+</info>
+# Server-side
+<reply>
+
+# this is returned when we get a GET!
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 7
+Content-Type: text/html
+Funny-head: yesyes
+
+daniel
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP proxy with URLs using different ports
+ </name>
+ <command>
+--proxy http://%HOSTIP:%HTTPPORT http://test.remote.example.com.1150:150/path http://test.remote.example.com.1150:1234/path/
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent: curl/.*
+</strip>
+<protocol>
+GET http://test.remote.example.com.1150:150/path HTTP/1.1
+Host: test.remote.example.com.1150:150
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://test.remote.example.com.1150:1234/path/ HTTP/1.1
+Host: test.remote.example.com.1150:1234
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1151 b/tests/data/test1151
new file mode 100644
index 000000000..08658d8db
--- /dev/null
+++ b/tests/data/test1151
@@ -0,0 +1,66 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+# reject cookies with too long name (instead of capping)
+# 3000 bytes name + 1096 bytes content is fine
+# 3000 bytes name + 1097 bytes content is NOT OK
+# 4096 bytes name + 1 byte content is NOT OK
+# 4094 bytes name + 1 byte content is fine
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Funny-head: yesyes swsclose
+Set-Cookie: foobar=name; domain=127.0.0.1; path=/;
+Set-Cookie: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB; domain=127.0.0.1; path=/;
+Set-Cookie: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB; domain=127.0.0.1; path=/;
+Set-Cookie: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD=E; domain=127.0.0.1; path=/;
+Set-Cookie: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF=E; domain=127.0.0.1; path=/;
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with too long cookies
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/1151 -c log/cookies1151.txt
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1151 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<file name="log/cookies1151.txt">
+# Netscape HTTP Cookie File
+# https://curl.haxx.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+127.0.0.1 FALSE / FALSE 0 foobar name
+127.0.0.1 FALSE / FALSE 0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+127.0.0.1 FALSE / FALSE 0 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF E
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test1152 b/tests/data/test1152
new file mode 100644
index 000000000..aa8c0a7e4
--- /dev/null
+++ b/tests/data/test1152
@@ -0,0 +1,61 @@
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+LIST
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY PWD 257 "just one
+</servercmd>
+
+# When doing LIST, we get the default list output hard-coded in the test
+# FTP server
+<data mode="text">
+total 20
+drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
+drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
+drwxr-xr-x 2 98 98 512 May 2 1996 curl-releases
+-r--r--r-- 1 0 1 35 Jul 16 1996 README
+lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
+dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
+drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
+dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
+drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
+dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP with uneven quote in PWD response
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/test-1152/
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PWD
+CWD test-1152
+EPSV
+TYPE A
+LIST
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1153 b/tests/data/test1153
new file mode 100644
index 000000000..c0e37c133
--- /dev/null
+++ b/tests/data/test1153
@@ -0,0 +1,61 @@
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+LIST
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY PWD 257 "/""hello"""
+</servercmd>
+
+# When doing LIST, we get the default list output hard-coded in the test
+# FTP server
+<data mode="text">
+total 20
+drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
+drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
+drwxr-xr-x 2 98 98 512 May 2 1996 curl-releases
+-r--r--r-- 1 0 1 35 Jul 16 1996 README
+lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
+dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
+drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
+dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
+drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
+dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP with quoted double quotes
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/test-1153/
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PWD
+CWD test-1153
+EPSV
+TYPE A
+LIST
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1160 b/tests/data/test1160
new file mode 100644
index 000000000..26a758c4e
--- /dev/null
+++ b/tests/data/test1160
@@ -0,0 +1,49 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 0
+Set-Cookie: ÿ= ; ÿ zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz†……€zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzúzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzó –zzzzzzzzzzzz~zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz¶zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with long funny format cookie
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/1160 -c log/cookies1160.txt
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1160 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<file name="log/cookies1160.txt">
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test1161 b/tests/data/test1161
new file mode 100644
index 000000000..179531314
--- /dev/null
+++ b/tests/data/test1161
@@ -0,0 +1,54 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 0
+Set-Cookie: ckyPersistent=permanent;path=;path=/
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP cookie with path set twice
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/1161 -c log/cookies1161.txt
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1161 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<file name="log/cookies1161.txt">
+# Netscape HTTP Cookie File
+# https://curl.haxx.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+127.0.0.1 FALSE / FALSE 0 ckyPersistent permanent
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test1315 b/tests/data/test1315
index c2f158a95..888ddc5c1 100644
--- a/tests/data/test1315
+++ b/tests/data/test1315
@@ -47,8 +47,7 @@ POST /we/want/1315 HTTP/1.1
User-Agent: curl/7.18.2 (i686-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.7a ipv6 zlib/1.1.4
Host: %HOSTIP:%HTTPPORT
Accept: */*
-Content-Length: 795
-Expect: 100-continue
+Content-Length: 797
Content-Type: multipart/form-data; boundary=----------------------------9ef8d6205763
------------------------------9ef8d6205763
@@ -77,6 +76,7 @@ Content-Type: text/plain
dummy data
------------------------------aaaaaaaaaaaa--
+
------------------------------9ef8d6205763--
</protocol>
</verify>
diff --git a/tests/data/test1401 b/tests/data/test1401
index deb1b5ed8..940cf8eba 100644
--- a/tests/data/test1401
+++ b/tests/data/test1401
@@ -84,10 +84,10 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1401");
curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
curl_easy_setopt(hnd, CURLOPT_USERPWD, "fake:user");
- curl_easy_setopt(hnd, CURLOPT_USERAGENT, "MyUA");
+ curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1);
+ curl_easy_setopt(hnd, CURLOPT_USERAGENT, "MyUA");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
- curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip");
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
diff --git a/tests/data/test1404 b/tests/data/test1404
index 4265bf882..a26f477bd 100644
--- a/tests/data/test1404
+++ b/tests/data/test1404
@@ -27,13 +27,13 @@ Connection: close
http
</server>
<name>
---libcurl for HTTP RFC1867-type formposting - -F with three files, one with explicit type
+--libcurl for HTTP RFC1867-type formposting - -F with 3 files, one with explicit type & encoder
</name>
<setenv>
SSL_CERT_FILE=
</setenv>
<command>
-http://%HOSTIP:%HTTPPORT/we/want/1404 -F name=value -F 'file=@log/test1404.txt,log/test1404.txt;type=magic/content,log/test1404.txt' --libcurl log/test1404.c
+http://%HOSTIP:%HTTPPORT/we/want/1404 -F name=value -F 'file=@log/test1404.txt,log/test1404.txt;type=magic/content;encoder=8bit,log/test1404.txt;headers=X-testheader-1: header 1;headers=X-testheader-2: header 2' --libcurl log/test1404.c
</command>
# We create this file before the command is invoked!
<file name="log/test1404.txt">
@@ -51,8 +51,7 @@ POST /we/want/1404 HTTP/1.1
User-Agent: curl/7.18.2 (i686-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.7a ipv6 zlib/1.1.4
Host: %HOSTIP:%HTTPPORT
Accept: */*
-Content-Length: 795
-Expect: 100-continue
+Content-Length: 882
Content-Type: multipart/form-data; boundary=----------------------------9ef8d6205763
------------------------------9ef8d6205763
@@ -71,16 +70,20 @@ dummy data
------------------------------9ef8d6205763
Content-Disposition: attachment; filename="test1404.txt"
Content-Type: magic/content
+Content-Transfer-Encoding: 8bit
dummy data
------------------------------9ef8d6205763
Content-Disposition: attachment; filename="test1404.txt"
Content-Type: text/plain
+X-testheader-1: header 1
+X-testheader-2: header 2
dummy data
------------------------------aaaaaaaaaaaa--
+
------------------------------9ef8d6205763--
</protocol>
<stripfile>
@@ -103,30 +106,42 @@ int main(int argc, char *argv[])
{
CURLcode ret;
CURL *hnd;
- struct curl_httppost *post1;
- struct curl_httppost *postend;
+ curl_mime *mime1;
+ curl_mimepart *part1;
+ curl_mime *mime2;
+ curl_mimepart *part2;
+ struct curl_slist *slist1;
- post1 = NULL;
- postend = NULL;
- curl_formadd(&post1, &postend,
- CURLFORM_COPYNAME, "name",
- CURLFORM_COPYCONTENTS, "value",
- CURLFORM_END);
- curl_formadd(&post1, &postend,
- CURLFORM_COPYNAME, "file",
- CURLFORM_FILE, "log/test1404.txt",
- CURLFORM_CONTENTTYPE, "text/plain",
- CURLFORM_FILE, "log/test1404.txt",
- CURLFORM_CONTENTTYPE, "magic/content",
- CURLFORM_FILE, "log/test1404.txt",
- CURLFORM_CONTENTTYPE, "text/plain",
- CURLFORM_END);
+ mime1 = NULL;
+ mime2 = NULL;
+ slist1 = NULL;
+ slist1 = curl_slist_append(slist1, "X-testheader-1: header 1");
+ slist1 = curl_slist_append(slist1, "X-testheader-2: header 2");
hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1404");
curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
- curl_easy_setopt(hnd, CURLOPT_HTTPPOST, post1);
+ mime1 = curl_mime_init(hnd);
+ part1 = curl_mime_addpart(mime1);
+ curl_mime_data(part1, "value", CURL_ZERO_TERMINATED);
+ curl_mime_name(part1, "name");
+ part1 = curl_mime_addpart(mime1);
+ mime2 = curl_mime_init(hnd);
+ part2 = curl_mime_addpart(mime2);
+ curl_mime_filedata(part2, "log/test1404.txt");
+ part2 = curl_mime_addpart(mime2);
+ curl_mime_filedata(part2, "log/test1404.txt");
+ curl_mime_encoder(part2, "8bit");
+ curl_mime_type(part2, "magic/content");
+ part2 = curl_mime_addpart(mime2);
+ curl_mime_filedata(part2, "log/test1404.txt");
+ curl_mime_headers(part2, slist1, 1);
+ slist1 = NULL;
+ curl_mime_subparts(part1, mime2);
+ mime2 = NULL;
+ curl_mime_name(part1, "file");
+ curl_easy_setopt(hnd, CURLOPT_MIMEPOST, mime1);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
@@ -156,8 +171,12 @@ int main(int argc, char *argv[])
curl_easy_cleanup(hnd);
hnd = NULL;
- curl_formfree(post1);
- post1 = NULL;
+ curl_mime_free(mime1);
+ mime1 = NULL;
+ curl_mime_free(mime2);
+ mime2 = NULL;
+ curl_slist_free_all(slist1);
+ slist1 = NULL;
return (int)ret;
}
diff --git a/tests/data/test1449 b/tests/data/test1449
new file mode 100644
index 000000000..d30c13c68
--- /dev/null
+++ b/tests/data/test1449
@@ -0,0 +1,38 @@
+# initially based on test110
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+RETR
+Resume
+</keywords>
+</info>
+# Server-side
+<reply>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP download range with integer overflow
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/1449 -r 36893488147419103232-
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PWD
+EPSV
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1453 b/tests/data/test1453
new file mode 100644
index 000000000..eaf9dd3b9
--- /dev/null
+++ b/tests/data/test1453
@@ -0,0 +1,38 @@
+<testcase>
+<info>
+<keywords>
+Too long tftp filename
+FAILURE
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+tftp
+</features>
+ <name>
+Too long tftp filename
+ </name>
+ <command>
+tftp://%HOSTIP:%TFTPPORT/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# TFTP file name too long
+<errorcode>
+71
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test158 b/tests/data/test158
index 9c4b22f70..dca51b163 100644
--- a/tests/data/test158
+++ b/tests/data/test158
@@ -41,7 +41,6 @@ User-Agent: curl/7.11.2-CVS (i686-pc-linux-gnu) libcurl/7.11.2-CVS OpenSSL/0.9.6
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 145
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------4f12fcdaa3bc
------------------------------4f12fcdaa3bc
diff --git a/tests/data/test163 b/tests/data/test163
index 22341c045..b4e2d260f 100644
--- a/tests/data/test163
+++ b/tests/data/test163
@@ -54,7 +54,6 @@ User-Agent: curl/7.11.2-CVS (i686-pc-linux-gnu) libcurl/7.11.2-CVS OpenSSL/0.9.6
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 304
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------c2d1767eb6ac
------------------------------c2d1767eb6ac
diff --git a/tests/data/test166 b/tests/data/test166
index 2036773f8..f170752e6 100644
--- a/tests/data/test166
+++ b/tests/data/test166
@@ -46,7 +46,6 @@ User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 223
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------b0b3d6d23991
------------------------------b0b3d6d23991
diff --git a/tests/data/test173 b/tests/data/test173
index bf6af0007..754950105 100644
--- a/tests/data/test173
+++ b/tests/data/test173
@@ -53,10 +53,11 @@ POST /we/want/173 HTTP/1.1
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
Host: %HOSTIP:%HTTPPORT
Accept: */*
-Content-Length: 360
+Transfer-Encoding: chunked
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------5dbea401cd8c
+168
------------------------------5dbea401cd8c
Content-Disposition: form-data; name="field1"
@@ -75,6 +76,9 @@ line7
line8
------------------------------5dbea401cd8c--
+
+0
+
</protocol>
</verify>
</testcase>
diff --git a/tests/data/test186 b/tests/data/test186
index b07736cbc..4abc74a2b 100644
--- a/tests/data/test186
+++ b/tests/data/test186
@@ -43,8 +43,7 @@ POST /we/want/186 HTTP/1.1
User-Agent: curl/7.12.2-CVS (i686-pc-linux-gnu) libcurl/7.12.2-CVS OpenSSL/0.9.7d zlib/1.2.1.1 c-ares/1.2.0 libidn/0.5.2
Host: %HOSTIP:%HTTPPORT
Accept: */*
-Content-Length: 321
-Expect: 100-continue
+Content-Length: 320
Content-Type: multipart/form-data; boundary=----------------------------212d9006ceb5
------------------------------212d9006ceb5
@@ -56,7 +55,7 @@ daniel
Content-Disposition: form-data; name="html"
Content-Type: text/html;charset=verymoo
- <body>hello</body>
+<body>hello</body>
------------------------------212d9006ceb5--
</protocol>
</verify>
diff --git a/tests/data/test1904 b/tests/data/test1904
new file mode 100644
index 000000000..08ad534a6
--- /dev/null
+++ b/tests/data/test1904
@@ -0,0 +1,79 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP CONNECT
+HTTP proxy
+proxytunnel
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Content-Length: 9
+
+contents
+</data>
+<connect>
+HTTP/1.1 204 Sure go ahead
+
+</connect>
+<datacheck>
+HTTP/1.1 204 Sure go ahead
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Content-Length: 9
+
+contents
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+http-proxy
+</server>
+ <name>
+HTTP CONNECT with 204 response
+ </name>
+ <command>
+http://test.1904:%HTTPPORT/we/want/that/page/1904 -p --proxy %HOSTIP:%PROXYPORT
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<proxy>
+CONNECT test.1904:%HTTPPORT HTTP/1.1
+Host: test.1904:%HTTPPORT
+User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
+Proxy-Connection: Keep-Alive
+
+</proxy>
+<protocol>
+GET /we/want/that/page/1904 HTTP/1.1
+Host: test.1904:%HTTPPORT
+User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test2056 b/tests/data/test2056
new file mode 100644
index 000000000..f00e21204
--- /dev/null
+++ b/tests/data/test2056
@@ -0,0 +1,87 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP Negotiate auth (stub krb5)
+</keywords>
+</info>
+# Server-side
+<reply>
+<!-- First request, expect 401 Negotiate -->
+<data>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate
+Content-Length: 13
+
+Not yet sir!
+</data>
+<!-- Second request, expect success in one shot -->
+<data1>
+HTTP/1.1 200 Things are fine in server land
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate RA==
+Content-Length: 15
+
+Nice auth sir!
+</data1>
+<datacheck>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate
+Content-Length: 13
+
+HTTP/1.1 200 Things are fine in server land
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate RA==
+Content-Length: 15
+
+Nice auth sir!
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP Negotiate authentication (stub krb5)
+</name>
+<features>
+GSS-API
+ld_preload
+!debug
+</features>
+<setenv>
+LD_PRELOAD=%PWD/libtest/.libs/libstubgss.so
+CURL_STUB_GSS_CREDS="KRB5_Alice"
+</setenv>
+<command>
+-u: --negotiate http://%HOSTIP:%HTTPPORT/2056
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /2056 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /2056 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Negotiate IktSQjVfQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjE6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test2057 b/tests/data/test2057
new file mode 100644
index 000000000..562505168
--- /dev/null
+++ b/tests/data/test2057
@@ -0,0 +1,108 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP Negotiate auth (stub ntlm)
+</keywords>
+</info>
+# Server-side
+<reply>
+<!-- First request, expect 401 Negotiate -->
+<data>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate
+Content-Length: 13
+
+Not yet sir!
+</data>
+<!-- Second request, expect 401 (ntlm challenge) -->
+<data1>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate Qw==
+Content-Length: 19
+
+Still not yet sir!
+</data1>
+<!-- Third request, expect success -->
+<data2>
+HTTP/1.1 200 Things are fine in server land
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate RA==
+Content-Length: 15
+
+Nice auth sir!
+</data2>
+<datacheck>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate
+Content-Length: 13
+
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate Qw==
+Content-Length: 19
+
+HTTP/1.1 200 Things are fine in server land
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate RA==
+Content-Length: 15
+
+Nice auth sir!
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP Negotiate authentication (stub ntlm)
+</name>
+<features>
+GSS-API
+ld_preload
+!debug
+</features>
+<setenv>
+LD_PRELOAD=%PWD/libtest/.libs/libstubgss.so
+CURL_STUB_GSS_CREDS="NTLM_Alice"
+</setenv>
+<command>
+-u: --negotiate http://%HOSTIP:%HTTPPORT/2057
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /2057 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /2057 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Negotiate Ik5UTE1fQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjI6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
+Accept: */*
+
+GET /2057 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Negotiate Ik5UTE1fQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjM6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test259 b/tests/data/test259
index 9532887a9..6e1853601 100644
--- a/tests/data/test259
+++ b/tests/data/test259
@@ -59,7 +59,7 @@ crypto
HTTP POST multipart with Expect: header using proxy anyauth (Digest)
</name>
<command>
--x http://%HOSTIP:%HTTPPORT http://remotehost:54321/we/want/259 -F name=daniel -F tool=curl -F file=@log/test259.txt -U uuuser:pppassword --proxy-anyauth
+-x http://%HOSTIP:%HTTPPORT http://remotehost:54321/we/want/259 -F name=daniel -F tool=curl -F file=@log/test259.txt -U uuuser:pppassword --proxy-anyauth -H "Expect: 100-continue"
</command>
# We create this file before the command is invoked!
<file name="log/test259.txt">
@@ -80,8 +80,8 @@ Host: remotehost:54321
User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Accept: */*
Proxy-Connection: Keep-Alive
-Content-Length: 409
Expect: 100-continue
+Content-Length: 409
Content-Type: multipart/form-data; boundary=----------------------------7c633d5c27ce
------------------------------7c633d5c27ce
@@ -107,8 +107,8 @@ User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 z
Proxy-Authorization: Digest username="uuuser", realm="many secrets", nonce="911", uri="/we/want/259", response="b479994d13e60f3aa192a67c5892ddc5"
Accept: */*
Proxy-Connection: Keep-Alive
-Content-Length: 409
Expect: 100-continue
+Content-Length: 409
Content-Type: multipart/form-data; boundary=----------------------------7c633d5c27ce
------------------------------7c633d5c27ce
diff --git a/tests/data/test277 b/tests/data/test277
index a509b40ec..d3e9d0fa4 100644
--- a/tests/data/test277
+++ b/tests/data/test277
@@ -45,12 +45,11 @@ POST /want/277 HTTP/1.1
User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Host: %HOSTIP:%HTTPPORT
Accept: */*
-Content-Length: 145
-Expect: 100-continue
+Content-Length: 146
Content-Type: text/info; boundary=------------------------
--------------------------
-Content-Disposition: form-data; name="name"
+Content-Disposition: attachment; name="name"
daniel
----------------------------
diff --git a/tests/data/test4 b/tests/data/test4
index df69d3274..542347db5 100644
--- a/tests/data/test4
+++ b/tests/data/test4
@@ -30,7 +30,7 @@ http
Replaced internal and added custom HTTP headers
</name>
<command>
- -H "extra-header: here" -H "Accept: replaced" -H "X-Custom-Header;" -H "X-Test: foo; " -H "X-Test:" -H "X-Test2: foo;" -H "X-Test3: " -H "X-Test4; " -H "X-Test5;ignored" http://%HOSTIP:%HTTPPORT/4
+ -H "extra-header: here" -H "Accept: replaced" -H "X-Custom-Header;" -H "X-Test: foo; " -H "X-Test:" -H "X-Test2: foo;" -H "X-Test3: " -H "X-Test4; " -H "X-Test5;ignored" http://%HOSTIP:%HTTPPORT/4 http://%HOSTIP:%HTTPPORT/4
</command>
</client>
@@ -49,6 +49,14 @@ X-Custom-Header:
X-Test: foo;
X-Test2: foo;
+GET /4 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+extra-header: here
+Accept: replaced
+X-Custom-Header:
+X-Test: foo;
+X-Test2: foo;
+
</protocol>
</verify>
</testcase>
diff --git a/tests/data/test46 b/tests/data/test46
index d1045b331..abcbda8e6 100644
--- a/tests/data/test46
+++ b/tests/data/test46
@@ -19,7 +19,7 @@ Set-Cookie: ckyPersistent=permanent; expires=Fri, 02-Feb-2035 11:56:27 GMT; path
Set-Cookie: ckySession=temporary; path=/
Set-Cookie: ASPSESSIONIDQGGQQSJJ=GKNBDIFAAOFDPDAIEAKDIBKE; path=/
Set-Cookie: justaname=; path=/;
-Set-Cookie: simplyhuge=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
+Set-Cookie: simplyhuge=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
Cache-control: private
Content-Length: 41
@@ -83,7 +83,7 @@ www.loser.com FALSE / FALSE 2139150993 UID 99
%HOSTIP FALSE / FALSE 0 ckySession temporary
%HOSTIP FALSE / FALSE 0 ASPSESSIONIDQGGQQSJJ GKNBDIFAAOFDPDAIEAKDIBKE
%HOSTIP FALSE / FALSE 0 justaname
-%HOSTIP FALSE /want/ FALSE 0 simplyhuge zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
+%HOSTIP FALSE /want/ FALSE 0 simplyhuge zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
</file>
</verify>
</testcase>
diff --git a/tests/data/test506 b/tests/data/test506
index 40eee2532..70d2daada 100644
--- a/tests/data/test506
+++ b/tests/data/test506
@@ -195,6 +195,8 @@ CURLOPT_COOKIEJAR
CURLOPT_COOKIELIST RELOAD
lock: cookie [Pigs in space]: 78
unlock: cookie [Pigs in space]: 79
+lock: cookie [Pigs in space]: 80
+unlock: cookie [Pigs in space]: 81
loaded cookies:
-----------------
.host.foo.com TRUE / FALSE 1896263787 injected yes
@@ -207,17 +209,17 @@ loaded cookies:
www.host.foo.com FALSE / FALSE 1993463787 test6 six_more
-----------------
try SHARE_CLEANUP...
-lock: share [Pigs in space]: 80
-unlock: share [Pigs in space]: 81
+lock: share [Pigs in space]: 82
+unlock: share [Pigs in space]: 83
SHARE_CLEANUP failed, correct
CLEANUP
-lock: cookie [Pigs in space]: 82
-unlock: cookie [Pigs in space]: 83
-lock: share [Pigs in space]: 84
-unlock: share [Pigs in space]: 85
-SHARE_CLEANUP
+lock: cookie [Pigs in space]: 84
+unlock: cookie [Pigs in space]: 85
lock: share [Pigs in space]: 86
unlock: share [Pigs in space]: 87
+SHARE_CLEANUP
+lock: share [Pigs in space]: 88
+unlock: share [Pigs in space]: 89
GLOBAL_CLEANUP
</stdout>
<stderr>
diff --git a/tests/data/test554 b/tests/data/test554
index 3419e5e0f..ce4a14dc4 100644
--- a/tests/data/test554
+++ b/tests/data/test554
@@ -69,7 +69,6 @@ POST /554 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 718
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------
------------------------------
@@ -100,7 +99,6 @@ POST /554 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 732
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------
------------------------------
diff --git a/tests/data/test564 b/tests/data/test564
index 72bf12919..4c9ecd466 100644
--- a/tests/data/test564
+++ b/tests/data/test564
@@ -1,4 +1,6 @@
<testcase>
+# Warning: if this test fails to start the SSH server, check that none of
+# the user's shell profiles sends output to stdout of a non-interactive shell.
<info>
<keywords>
FTP
diff --git a/tests/data/test587 b/tests/data/test587
index 69cbe1ed7..689a877db 100644
--- a/tests/data/test587
+++ b/tests/data/test587
@@ -43,7 +43,6 @@ POST /587 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 718
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------
------------------------------
diff --git a/tests/data/test589 b/tests/data/test589
new file mode 100644
index 000000000..451bb15bd
--- /dev/null
+++ b/tests/data/test589
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP MIME
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK swsclose
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 3
+
+OK
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib589
+</tool>
+
+ <name>
+make a HTTP MIME POST set to NULL
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/589
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+POST /589 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 0
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test642 b/tests/data/test642
new file mode 100644
index 000000000..41fd444fc
--- /dev/null
+++ b/tests/data/test642
@@ -0,0 +1,42 @@
+<testcase>
+<info>
+<keywords>
+SFTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+Test data
+for ssh test
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+sftp
+</server>
+ <name>
+SFTP retrieval
+ </name>
+ <command>
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: --compressed-ssh sftp://%HOSTIP:%SSHPORT%PWD/log/file642.txt --insecure
+</command>
+<file name="log/file642.txt">
+Test data
+for ssh test
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<valgrind>
+disable
+</valgrind>
+</verify>
+</testcase>
diff --git a/tests/data/test643 b/tests/data/test643
new file mode 100644
index 000000000..0eaf22c5f
--- /dev/null
+++ b/tests/data/test643
@@ -0,0 +1,131 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP MIME POST
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</data>
+<datacheck>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib643
+</tool>
+
+ <name>
+HTTP multi-part mimepost using read callback for the file part
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/643
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+# Note that the stripping above removes 12 bytes from every occurrence of the
+# boundary string and since 5 of them are in the body contents, we see
+# (5*12) == 60 bytes less
+<protocol>
+POST /643 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 718
+Content-Type: multipart/form-data; boundary=----------------------------
+
+------------------------------
+Content-Disposition: form-data; name="sendfile"; filename="postit2.c"
+
+this is what we post to the silly web server
+
+------------------------------
+Content-Disposition: form-data; name="callbackdata"
+
+this is what we post to the silly web server
+
+------------------------------
+Content-Disposition: form-data; name="filename"
+
+postit2.c
+------------------------------
+Content-Disposition: form-data; name="submit"
+
+send
+------------------------------
+Content-Disposition: form-data; name="somename"; filename="somefile.txt"
+Content-Type: text/plain
+
+blah blah
+--------------------------------
+POST /643 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 732
+Content-Type: multipart/form-data; boundary=----------------------------
+
+------------------------------
+Content-Disposition: form-data; name="sendfile alternative"; filename="file name 2"
+
+this is what we post to the silly web server
+
+------------------------------
+Content-Disposition: form-data; name="callbackdata"
+
+this is what we post to the silly web server
+
+------------------------------
+Content-Disposition: form-data; name="filename"
+
+postit2.c
+------------------------------
+Content-Disposition: form-data; name="submit"
+
+send
+------------------------------
+Content-Disposition: form-data; name="somename"; filename="somefile.txt"
+Content-Type: text/plain
+
+blah blah
+--------------------------------
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test644 b/tests/data/test644
new file mode 100644
index 000000000..6ac37ce54
--- /dev/null
+++ b/tests/data/test644
@@ -0,0 +1,58 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP MIME POST
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib644
+</tool>
+
+ <name>
+HTTP multi-part formpost with aborted read callback
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/644
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+POST /644 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 718
+Content-Type: multipart/form-data; boundary=----------------------------
+
+------------------------------
+Content-Disposition: form-data; name="sendfile"; filename="postit2.c"
+
+</protocol>
+# CURLE_ABORTED_BY_CALLBACK (42)
+<errorcode>
+42
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test645 b/tests/data/test645
new file mode 100644
index 000000000..6533944b4
--- /dev/null
+++ b/tests/data/test645
@@ -0,0 +1,141 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP MIME POST
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</data>
+<datacheck>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib645
+</tool>
+
+ <name>
+HTTP multi-part chunked mimepost using read callback for the file part
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/645
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+# Note that the stripping above removes 12 bytes from every occurrence of the
+# boundary string and since 5 of them are in the body contents, we see
+# (5*12) == 60 bytes less
+<protocol>
+POST /645 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Transfer-Encoding: chunked
+Content-Type: multipart/form-data; boundary=----------------------------
+Expect: 100-continue
+
+2ce
+------------------------------
+Content-Disposition: form-data; name="sendfile"; filename="postit2.c"
+
+this is what we post to the silly web server
+
+------------------------------
+Content-Disposition: form-data; name="callbackdata"
+
+this is what we post to the silly web server
+
+------------------------------
+Content-Disposition: form-data; name="filename"
+
+postit2.c
+------------------------------
+Content-Disposition: form-data; name="submit"
+
+send
+------------------------------
+Content-Disposition: form-data; name="somename"; filename="somefile.txt"
+Content-Type: text/plain
+
+blah blah
+--------------------------------
+
+0
+
+POST /645 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Transfer-Encoding: chunked
+Content-Type: multipart/form-data; boundary=----------------------------
+Expect: 100-continue
+
+2dc
+------------------------------
+Content-Disposition: form-data; name="sendfile alternative"; filename="file name 2"
+
+this is what we post to the silly web server
+
+------------------------------
+Content-Disposition: form-data; name="callbackdata"
+
+this is what we post to the silly web server
+
+------------------------------
+Content-Disposition: form-data; name="filename"
+
+postit2.c
+------------------------------
+Content-Disposition: form-data; name="submit"
+
+send
+------------------------------
+Content-Disposition: form-data; name="somename"; filename="somefile.txt"
+Content-Type: text/plain
+
+blah blah
+--------------------------------
+
+0
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test646 b/tests/data/test646
new file mode 100644
index 000000000..a53c34090
--- /dev/null
+++ b/tests/data/test646
@@ -0,0 +1,98 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+MULTIPART
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP multipart using mime API
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/646 --mail-rcpt recipient@example.com --mail-from sender@example.com -F "=(;type=multipart/alternative" -F "= <body>This is the html version</body>;headers=X-test1: this is a header;type=text/html;headers=X-test2: this is another header " -F "=This is the plain text version;headers=@log/headers646" -F "=)" -F "=@log/test646.txt;headers=<log/headers646" -H "From: different" -H "To: another" -H "Reply-To: <followup@example.com>"
+</command>
+<file1 name="log/test646.txt">
+This is an attached file.
+
+It may contain any type of data.
+</file1>
+<file2 name="log/headers646">
+# This line is a comment
+X-fileheader1: This is a header from a file
+
+# This line is another comment. It precedes a folded header.
+X-fileheader2: This is #a
+ folded header
+</file2>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+EHLO 646
+MAIL FROM:<sender@example.com>
+RCPT TO:<recipient@example.com>
+DATA
+QUIT
+</protocol>
+<upload>
+Content-Type: multipart/mixed; boundary=----------------------------
+Mime-Version: 1.0
+From: different
+To: another
+Reply-To: <followup@example.com>
+
+------------------------------
+Content-Type: multipart/alternative; boundary=----------------------------
+
+------------------------------
+Content-Type: text/html
+Content-Transfer-Encoding: 8bit
+X-test1: this is a header
+X-test2: this is another header
+
+<body>This is the html version</body>
+------------------------------
+X-fileheader1: This is a header from a file
+X-fileheader2: This is #a folded header
+
+This is the plain text version
+--------------------------------
+
+------------------------------
+Content-Disposition: attachment; filename="test646.txt"
+X-fileheader1: This is a header from a file
+X-fileheader2: This is #a folded header
+
+This is an attached file.
+
+It may contain any type of data.
+
+--------------------------------
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test647 b/tests/data/test647
new file mode 100644
index 000000000..de2b467fc
--- /dev/null
+++ b/tests/data/test647
@@ -0,0 +1,79 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+APPEND
+MULTIPART
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+imap
+</server>
+ <name>
+IMAP APPEND multipart using mime API
+ </name>
+ <command>
+imap://%HOSTIP:%IMAPPORT/647 -F "=(;type=multipart/alternative" -F "= <body>This is the html version</body>;type=text/html" -F "=This is the plain text version" -F "=)" -F "=@log/test647.txt" -H "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)" -H "From: Fred Foobar <foobar@example.com>" -H "To: joe@example.com" -H "Message-Id: <B27397-0100000@example.com>" -H "Subject: afternoon meeting" -u user:secret
+</command>
+<file name="log/test647.txt">
+This is an attached file.
+
+It may contain any type of data.
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+A001 CAPABILITY
+A002 LOGIN user secret
+A003 APPEND 647 (\Seen) {892}
+A004 LOGOUT
+</protocol>
+<upload>
+Content-Type: multipart/mixed; boundary=----------------------------
+Mime-Version: 1.0
+Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
+From: Fred Foobar <foobar@example.com>
+To: joe@example.com
+Message-Id: <B27397-0100000@example.com>
+Subject: afternoon meeting
+
+------------------------------
+Content-Type: multipart/alternative; boundary=----------------------------
+
+------------------------------
+Content-Type: text/html
+Content-Transfer-Encoding: 8bit
+
+<body>This is the html version</body>
+------------------------------
+
+This is the plain text version
+--------------------------------
+
+------------------------------
+Content-Disposition: attachment; filename="test647.txt"
+
+This is an attached file.
+
+It may contain any type of data.
+
+--------------------------------
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test648 b/tests/data/test648
new file mode 100644
index 000000000..cd8f02085
--- /dev/null
+++ b/tests/data/test648
@@ -0,0 +1,75 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+MULTIPART
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP multipart with transfer content encoders
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/648 --mail-rcpt recipient@example.com --mail-from sender@example.com -F '=This is the e-mail inline text with a very long line containing the special character = and that should be split by encoder.;headers=Content-disposition: "inline";encoder=quoted-printable' -F "=@log/test648.txt;encoder=base64" -H "From: different" -H "To: another"
+</command>
+<file name="log/test648.txt">
+This is an attached file.
+
+It may contain any type of data and will be encoded in base64 for transfer.
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+EHLO 648
+MAIL FROM:<sender@example.com>
+RCPT TO:<recipient@example.com>
+DATA
+QUIT
+</protocol>
+<upload>
+Content-Type: multipart/mixed; boundary=----------------------------
+Mime-Version: 1.0
+From: different
+To: another
+
+------------------------------
+Content-Transfer-Encoding: quoted-printable
+Content-disposition: "inline"
+
+This is the e-mail inline text with a very long line containing the special=
+ character =3D and that should be split by encoder.
+------------------------------
+Content-Disposition: attachment; filename="test648.txt"
+Content-Transfer-Encoding: base64
+
+VGhpcyBpcyBhbiBhdHRhY2hlZCBmaWxlLgoKSXQgbWF5IGNvbnRhaW4gYW55IHR5cGUgb2Yg
+ZGF0YSBhbmQgd2lsbCBiZSBlbmNvZGVkIGluIGJhc2U2NCBmb3IgdHJhbnNmZXIuCg==
+--------------------------------
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test649 b/tests/data/test649
new file mode 100644
index 000000000..46c01cd00
--- /dev/null
+++ b/tests/data/test649
@@ -0,0 +1,72 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+MULTIPART
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP multipart with 7bit encoder error
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/649 --mail-rcpt recipient@example.com --mail-from sender@example.com -F '=This is valid;encoder=7bit' -F "=@log/test649.txt;encoder=7bit" -H "From: different" -H "To: another"
+</command>
+<file name="log/test649.txt">
+This is an attached file (in french: pièce jointe).
+
+It contains at least an 8-bit byte value.
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+EHLO 649
+MAIL FROM:<sender@example.com>
+RCPT TO:<recipient@example.com>
+DATA
+</protocol>
+<upload nonewline="yes">
+Content-Type: multipart/mixed; boundary=----------------------------
+Mime-Version: 1.0
+From: different
+To: another
+
+------------------------------
+Content-Transfer-Encoding: 7bit
+
+This is valid
+------------------------------
+Content-Disposition: attachment; filename="test649.txt"
+Content-Transfer-Encoding: 7bit
+
+This is an attached file (in french: pi
+</upload>
+<errorcode>
+26
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test650 b/tests/data/test650
new file mode 100644
index 000000000..e07d4c10b
--- /dev/null
+++ b/tests/data/test650
@@ -0,0 +1,122 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+FORM
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib650
+</tool>
+
+ <name>
+HTTP formpost using form API
+ </name>
+<stdin>
+ Some data from stdin
+</stdin>
+ <command>
+http://%HOSTIP:%HTTPPORT/650 log/test650.filedata
+</command>
+<file name="log/test650.filedata">
+This is data from a file.
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+# Note that the stripping above removes 12 bytes from every occurrence of the
+# boundary string and since 5 of them are in the body contents, we see
+# (5*12) == 60 bytes less
+<protocol>
+POST /650 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Transfer-Encoding: chunked
+Content-Type: multipart/form-data; boundary=----------------------------
+Expect: 100-continue
+
+5f0
+------------------------------
+Content-Disposition: form-data; name="fieldname"
+
+this is what we post to the silly web server
+------------------------------
+Content-Disposition: form-data; name="fieldnam"
+
+uhis is what we post to the silly web serve
+------------------------------
+Content-Disposition: form-data; name="multifile"
+Content-Type: multipart/mixed; boundary=----------------------------
+
+------------------------------
+Content-Disposition: attachment; filename="test650.filedata"
+Content-Type: application/octet-stream
+
+This is data from a file.
+
+------------------------------
+Content-Disposition: attachment; filename="test650.filedata"
+Content-Type: text/whatever
+
+This is data from a file.
+
+------------------------------
+Content-Disposition: attachment; filename="test650.filedata"
+Content-Type: text/whatever
+
+This is data from a file.
+
+--------------------------------
+
+------------------------------
+Content-Disposition: form-data; name="filecontents"
+X-customheader-1: Header 1 data
+X-customheader-2: Header 2 data
+
+This is data from a file.
+
+------------------------------
+Content-Disposition: form-data; name="formlength"
+
+1341
+------------------------------
+Content-Disposition: form-data; name="standardinput"
+Content-Type: application/octet-stream
+
+ Some data from stdin
+
+--------------------------------
+
+0
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test71 b/tests/data/test71
index 341a0033f..0bc76fc03 100644
--- a/tests/data/test71
+++ b/tests/data/test71
@@ -54,7 +54,6 @@ POST /we/want/71 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 408
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------9ef8d6205763
------------------------------9ef8d6205763
diff --git a/tests/data/test800 b/tests/data/test800
index 6b29f7a2b..360206b43 100644
--- a/tests/data/test800
+++ b/tests/data/test800
@@ -31,7 +31,7 @@ imap
IMAP FETCH message
</name>
<command>
-'imap://%HOSTIP:%IMAPPORT/800/;UID=1' -u user:secret
+'imap://%HOSTIP:%IMAPPORT/800/;UID=1' -u '"user:sec"ret{'
</command>
</client>
@@ -40,7 +40,7 @@ IMAP FETCH message
<verify>
<protocol>
A001 CAPABILITY
-A002 LOGIN user secret
+A002 LOGIN "\"user" "sec\"ret{"
A003 SELECT 800
A004 FETCH 1 BODY[]
A005 LOGOUT
diff --git a/tests/data/test846 b/tests/data/test846
new file mode 100644
index 000000000..b363ffd18
--- /dev/null
+++ b/tests/data/test846
@@ -0,0 +1,50 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY welcome * PREAUTH ready to serve already!
+REPLY CAPABILITY * CAPABILITY IMAP4REV1 I18NLEVEL=1 LITERAL+ IDLE UIDPLUS NAMESPACE CHILDREN MAILBOX-REFERRALS BINARY UNSELECT ESEARCH WITHIN SCAN SORT THREAD=REFERENCES THREAD=ORDEREDSUBJECT MULTIAPPEND SASL-IR LOGIN-REFERRALS STARTTLS LOGINDISABLED\r\nA001 OK CAPABILITY completed
+</servercmd>
+<data>
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+imap
+</server>
+ <name>
+IMAP PREAUTH response
+ </name>
+ <command>
+'imap://%HOSTIP:%IMAPPORT/846/;UID=1' -u notused:still-provided
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+A001 CAPABILITY
+A002 SELECT 846
+A003 FETCH 1 BODY[]
+A004 LOGOUT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test856 b/tests/data/test856
index 4d8d7ed61..dcb07c5a9 100644
--- a/tests/data/test856
+++ b/tests/data/test856
@@ -10,6 +10,9 @@ FAILURE
#
# Server-side
<reply>
+<servercmd>
+REPLY PASS -ERR Login failure
+</servercmd>
</reply>
#
diff --git a/tests/data/test9 b/tests/data/test9
index 7905ac838..53fe25eda 100644
--- a/tests/data/test9
+++ b/tests/data/test9
@@ -48,7 +48,6 @@ User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 z
Host: %HOSTIP:%HTTPPORT
Accept: */*
Content-Length: 407
-Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------9ef8d6205763
------------------------------9ef8d6205763
diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl
index 081298f1b..2aba4263a 100755
--- a/tests/ftpserver.pl
+++ b/tests/ftpserver.pl
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2014, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -174,7 +174,6 @@ my $exit_signal; # first signal handled in exit_signal_handler
#**********************************************************************
# Mail related definitions
#
-my $TEXT_USERNAME = "user";
my $TEXT_PASSWORD = "secret";
my $POP3_TIMESTAMP = "<1972.987654321\@curl>";
@@ -1121,9 +1120,6 @@ sub LOGIN_imap {
if ($user eq "") {
sendcontrol "$cmdid BAD Command Argument\r\n";
}
- elsif (($user ne $TEXT_USERNAME) || ($password ne $TEXT_PASSWORD)) {
- sendcontrol "$cmdid NO LOGIN failed\r\n";
- }
else {
sendcontrol "$cmdid OK LOGIN completed\r\n";
}
@@ -1681,7 +1677,7 @@ sub APOP_pop3 {
else {
my $digest = Digest::MD5::md5_hex($POP3_TIMESTAMP, $TEXT_PASSWORD);
- if (($user ne $TEXT_USERNAME) || ($secret ne $digest)) {
+ if ($secret ne $digest) {
sendcontrol "-ERR Login failure\r\n";
}
else {
@@ -1740,12 +1736,7 @@ sub PASS_pop3 {
logmsg "PASS_pop3 got $password\n";
- if (($username ne $TEXT_USERNAME) || ($password ne $TEXT_PASSWORD)) {
- sendcontrol "-ERR Login failure\r\n";
- }
- else {
- sendcontrol "+OK Login successful\r\n";
- }
+ sendcontrol "+OK Login successful\r\n";
return 0;
}
diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am
index 259b86c4f..dcea6d576 100644
--- a/tests/fuzz/Makefile.am
+++ b/tests/fuzz/Makefile.am
@@ -26,30 +26,31 @@ AUTOMAKE_OPTIONS = foreign nostdinc
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#
-
-
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "borrowed" files
-AM_CPPFLAGS = -I$(top_srcdir)/include \
+AM_CXXFLAGS = -I$(top_srcdir)/include \
-I$(top_builddir)/lib \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/tests/fuzz
-EXTRA_DIST = Makefile.inc CMakeLists.txt
+LIBS = -lpthread -lm
-LIBS = -lpthread -lFuzzer -lstdc++ -lm
-LDFLAGS = -L/usr/lib/llvm-5.0/lib
+# Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a"
+# to link the fuzzer(s) against a real fuzzing engine.
+#
+# OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE.
+LIB_FUZZING_ENGINE ?= libstandaloneengine.a
LDADD = $(top_builddir)/lib/libgnurl.la \
- @LDFLAGS@ @LIBCURL_LIBS@
+ $(LIB_FUZZING_ENGINE) @LDFLAGS@ @LIBCURL_LIBS@
# Makefile.inc provides neat definitions
include Makefile.inc
checksrc:
- @PERL@ $(top_srcdir)/lib/checksrc.pl $(srcdir)/*.c
+ @PERL@ $(top_srcdir)/lib/checksrc.pl $(srcdir)/*.cc
noinst_PROGRAMS = $(FUZZPROGS)
-
+noinst_LIBRARIES = $(FUZZLIBS)
diff --git a/tests/fuzz/Makefile.inc b/tests/fuzz/Makefile.inc
index fb6cdb11a..f52adb89c 100644
--- a/tests/fuzz/Makefile.inc
+++ b/tests/fuzz/Makefile.inc
@@ -1,19 +1,15 @@
-FUZZPROGS = http11 ftp imap pop3 httpupload http2
+FUZZPROGS = curl_fuzzer
+FUZZLIBS = libstandaloneengine.a
-http11_SOURCES = curl_fuzzer.c
-http11_CPPFLAGS = $(AM_CPPFLAGS)
+curl_fuzzer_SOURCES = curl_fuzzer.cc
+curl_fuzzer_CXXFLAGS = $(AM_CXXFLAGS)
-ftp_SOURCES = curl_fuzzer.c
-ftp_CPPFLAGS = -DFUZZER_FTP $(AM_CPPFLAGS)
+libstandaloneengine_a_SOURCES = standalone_fuzz_target_runner.cc
+libstandaloneengine_a_CXXFLAGS = $(AM_CXXFLAGS)
-imap_SOURCES = curl_fuzzer.c
-imap_CPPFLAGS = -DFUZZER_IMAP $(AM_CPPFLAGS)
+# Some more targets.
+zip:
+ zip -q -r curl_fuzzer_seed_corpus.zip curl_fuzz_data
-pop3_SOURCES = curl_fuzzer.c
-pop3_CPPFLAGS = -DFUZZER_POP3 $(AM_CPPFLAGS)
-
-httpupload_SOURCES = curl_fuzzer.c
-httpupload_CPPFLAGS = -DFUZZER_HTTP_UPLOAD $(AM_CPPFLAGS)
-
-http2_SOURCES = curl_fuzzer.c
-http2_CPPFLAGS = -DFUZZER_HTTP2 $(AM_CPPFLAGS)
+check: all
+ ./curl_fuzzer curl_fuzz_data/*
diff --git a/tests/fuzz/README b/tests/fuzz/README
index 459bda46b..8b5fcd011 100644
--- a/tests/fuzz/README
+++ b/tests/fuzz/README
@@ -2,13 +2,20 @@ Fuzz tests
==========
The goal is to add tests for *ALL* protocols supported in libcurl.
-We will need some additional patches in the future, to increase coverage.
Building the fuzz target
========================
+From the CURL root directory:
-CC=clang-5.0 CFLAGS="-fsanitize=address -fsanitize-address-use-after-scope -fsanitize-coverage=trace-pc-guard,trace-cmp" ./configure --disable-shared --enable-debug --enable-maintainer-mode
+export CC=clang-5.0
+export CXX=clang++-5.0
+export CFLAGS="-fsanitize=address -fsanitize-address-use-after-scope -fsanitize-coverage=trace-pc-guard,trace-cmp"
+export CXXFLAGS="-fsanitize=address -fsanitize-address-use-after-scope -fsanitize-coverage=trace-pc-guard,trace-cmp -stdlib=libc++"
+./configure --disable-shared --enable-debug --enable-maintainer-mode
make -sj
cd tests/fuzz
-make
+
+(optional) export LIB_FUZZING_ENGINE=<path to libFuzzer.a>
+
+make check
diff --git a/tests/fuzz/corpus.py b/tests/fuzz/corpus.py
new file mode 100644
index 000000000..5474c99af
--- /dev/null
+++ b/tests/fuzz/corpus.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+#
+# Common corpus functions
+import logging
+import struct
+log = logging.getLogger(__name__)
+
+
+class BaseType(object):
+ TYPE_URL = 1
+ TYPE_RSP1 = 2
+ TYPE_USERNAME = 3
+ TYPE_PASSWORD = 4
+ TYPE_POSTFIELDS = 5
+ TYPE_HEADER = 6
+ TYPE_COOKIE = 7
+ TYPE_UPLOAD1 = 8
+ TYPE_RANGE = 9
+ TYPE_CUSTOMREQUEST = 10
+ TYPE_MAIL_RECIPIENT = 11
+ TYPE_MAIL_FROM = 12
+
+
+class TLVEncoder(BaseType):
+ def __init__(self, output):
+ self.output = output
+
+ def write_string(self, tlv_type, wstring):
+ data = wstring.encode("utf-8")
+ self.write_tlv(tlv_type, len(data), data)
+
+ def write_bytes(self, tlv_type, bytedata):
+ self.write_tlv(tlv_type, len(bytedata), bytedata)
+
+ def maybe_write_string(self, tlv_type, wstring):
+ if wstring is not None:
+ self.write_string(tlv_type, wstring)
+
+ def write_tlv(self, tlv_type, tlv_length, tlv_data=None):
+ log.debug("Writing TLV %d, length %d, data %r",
+ tlv_type,
+ tlv_length,
+ tlv_data)
+
+ data = struct.pack("!H", tlv_type)
+ self.output.write(data)
+
+ data = struct.pack("!L", tlv_length)
+ self.output.write(data)
+
+ if tlv_data:
+ self.output.write(tlv_data)
+
+
+class TLVDecoder(BaseType):
+ def __init__(self, inputdata):
+ self.inputdata = inputdata
+ self.pos = 0
+ self.tlv = None
+
+ def __iter__(self):
+ self.pos = 0
+ self.tlv = None
+ return self
+
+ def __next__(self):
+ if self.tlv:
+ self.pos += self.tlv.total_length()
+
+ if (self.pos + TLVHeader.TLV_DECODE_FMT_LEN) > len(self.inputdata):
+ raise StopIteration
+
+ # Get the next TLV
+ self.tlv = TLVHeader(self.inputdata[self.pos:])
+ return self.tlv
+
+ next = __next__
+
+
+class TLVHeader(BaseType):
+ TLV_DECODE_FMT = "!HL"
+ TLV_DECODE_FMT_LEN = struct.calcsize(TLV_DECODE_FMT)
+
+ def __init__(self, data):
+ # Parse the data to populate the TLV fields
+ (self.type, self.length) = struct.unpack(self.TLV_DECODE_FMT, data[0:self.TLV_DECODE_FMT_LEN])
+
+ # Get the remaining data and store it.
+ self.data = data[self.TLV_DECODE_FMT_LEN:self.TLV_DECODE_FMT_LEN + self.length]
+
+ def __repr__(self):
+ return ("{self.__class__.__name__}(type={self.type!r}, length={self.length!r}, data={self.data!r})"
+ .format(self=self))
+
+ def total_length(self):
+ return self.TLV_DECODE_FMT_LEN + self.length \ No newline at end of file
diff --git a/tests/fuzz/curl_fuzz_data/oss-fuzz-3327 b/tests/fuzz/curl_fuzz_data/oss-fuzz-3327
new file mode 100644
index 000000000..064cc623a
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/oss-fuzz-3327
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test1 b/tests/fuzz/curl_fuzz_data/test1
new file mode 100644
index 000000000..f7b734a9c
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test1
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test10 b/tests/fuzz/curl_fuzz_data/test10
new file mode 100644
index 000000000..af1ed53ca
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test10
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test100 b/tests/fuzz/curl_fuzz_data/test100
new file mode 100644
index 000000000..b58d9335a
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test100
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test12 b/tests/fuzz/curl_fuzz_data/test12
new file mode 100644
index 000000000..9ad91dc07
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test12
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test13 b/tests/fuzz/curl_fuzz_data/test13
new file mode 100644
index 000000000..448077dde
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test13
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test1326 b/tests/fuzz/curl_fuzz_data/test1326
new file mode 100644
index 000000000..8801fac96
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test1326
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test1450 b/tests/fuzz/curl_fuzz_data/test1450
new file mode 100644
index 000000000..601236168
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test1450
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test2 b/tests/fuzz/curl_fuzz_data/test2
new file mode 100644
index 000000000..8b44d6719
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test2
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test271 b/tests/fuzz/curl_fuzz_data/test271
new file mode 100644
index 000000000..3a26767f7
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test271
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test3 b/tests/fuzz/curl_fuzz_data/test3
new file mode 100644
index 000000000..81c6670aa
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test3
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test4 b/tests/fuzz/curl_fuzz_data/test4
new file mode 100644
index 000000000..3fa395a29
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test4
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test5 b/tests/fuzz/curl_fuzz_data/test5
new file mode 100644
index 000000000..bdaac4e66
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test5
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test6 b/tests/fuzz/curl_fuzz_data/test6
new file mode 100644
index 000000000..98d9be216
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test6
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test800 b/tests/fuzz/curl_fuzz_data/test800
new file mode 100644
index 000000000..a5899be43
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test800
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test850 b/tests/fuzz/curl_fuzz_data/test850
new file mode 100644
index 000000000..22c08dcfc
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test850
Binary files differ
diff --git a/tests/fuzz/curl_fuzz_data/test900 b/tests/fuzz/curl_fuzz_data/test900
new file mode 100644
index 000000000..eecf0cbaf
--- /dev/null
+++ b/tests/fuzz/curl_fuzz_data/test900
Binary files differ
diff --git a/tests/fuzz/curl_fuzzer.cc b/tests/fuzz/curl_fuzzer.cc
new file mode 100644
index 000000000..dd0298f36
--- /dev/null
+++ b/tests/fuzz/curl_fuzzer.cc
@@ -0,0 +1,447 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, Max Dymond, <cmeister2@gmail.com>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <curl/curl.h>
+#include "curl_fuzzer.h"
+
+/**
+ * Fuzzing entry point. This function is passed a buffer containing a test
+ * case. This test case should drive the CURL API into making a request.
+ */
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ int rc = 0;
+ int tlv_rc;
+ FUZZ_DATA fuzz;
+ TLV tlv;
+
+ /* Have to set all fields to zero before getting to the terminate function */
+ memset(&fuzz, 0, sizeof(FUZZ_DATA));
+
+ if(size < sizeof(TLV_RAW)) {
+ /* Not enough data for a single TLV - don't continue */
+ goto EXIT_LABEL;
+ }
+
+ /* Try to initialize the fuzz data */
+ FTRY(fuzz_initialize_fuzz_data(&fuzz, data, size));
+
+ for(tlv_rc = fuzz_get_first_tlv(&fuzz, &tlv);
+ tlv_rc == 0;
+ tlv_rc = fuzz_get_next_tlv(&fuzz, &tlv)) {
+
+ /* Have the TLV in hand. Parse the TLV. */
+ rc = fuzz_parse_tlv(&fuzz, &tlv);
+
+ if(rc != 0) {
+ /* Failed to parse the TLV. Can't continue. */
+ goto EXIT_LABEL;
+ }
+ }
+
+ if(tlv_rc != TLV_RC_NO_MORE_TLVS) {
+ /* A TLV call failed. Can't continue. */
+ goto EXIT_LABEL;
+ }
+
+ /* Do the CURL stuff! */
+ if(fuzz.header_list != NULL) {
+ curl_easy_setopt(fuzz.easy, CURLOPT_HTTPHEADER, fuzz.header_list);
+ }
+
+ if(fuzz.mail_recipients_list != NULL) {
+ curl_easy_setopt(fuzz.easy, CURLOPT_MAIL_RCPT, fuzz.mail_recipients_list);
+ }
+
+ curl_easy_perform(fuzz.easy);
+
+EXIT_LABEL:
+
+ fuzz_terminate_fuzz_data(&fuzz);
+
+ /* This function must always return 0. Non-zero codes are reserved. */
+ return 0;
+}
+
+/**
+ * Utility function to convert 4 bytes to a u32 predictably.
+ */
+uint32_t to_u32(uint8_t b[4])
+{
+ uint32_t u;
+ u = (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3];
+ return u;
+}
+
+/**
+ * Utility function to convert 2 bytes to a u16 predictably.
+ */
+uint16_t to_u16(uint8_t b[2])
+{
+ uint16_t u;
+ u = (b[0] << 8) + b[1];
+ return u;
+}
+
+/**
+ * Initialize the local fuzz data structure.
+ */
+int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz,
+ const uint8_t *data,
+ size_t data_len)
+{
+ int rc = 0;
+
+ /* Initialize the fuzz data. */
+ memset(fuzz, 0, sizeof(FUZZ_DATA));
+
+ /* Create an easy handle. This will have all of the settings configured on
+ it. */
+ fuzz->easy = curl_easy_init();
+ FCHECK(fuzz->easy != NULL);
+
+ /* Set some standard options on the CURL easy handle. We need to override the
+ socket function so that we create our own sockets to present to CURL. */
+ FTRY(curl_easy_setopt(fuzz->easy,
+ CURLOPT_OPENSOCKETFUNCTION,
+ fuzz_open_socket));
+ FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_OPENSOCKETDATA, fuzz));
+
+ /* In case something tries to set a socket option, intercept this. */
+ FTRY(curl_easy_setopt(fuzz->easy,
+ CURLOPT_SOCKOPTFUNCTION,
+ fuzz_sockopt_callback));
+
+ /* Set the standard read function callback. */
+ FTRY(curl_easy_setopt(fuzz->easy,
+ CURLOPT_READFUNCTION,
+ fuzz_read_callback));
+ FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_READDATA, fuzz));
+
+ /* Set the standard write function callback. */
+ FTRY(curl_easy_setopt(fuzz->easy,
+ CURLOPT_WRITEFUNCTION,
+ fuzz_write_callback));
+ FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_WRITEDATA, fuzz));
+
+ /* Can enable verbose mode by changing 0L to 1L */
+ FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 0L));
+
+ /* Set up the state parser */
+ fuzz->state.data = data;
+ fuzz->state.data_len = data_len;
+
+EXIT_LABEL:
+
+ return rc;
+}
+
+/**
+ * Terminate the fuzz data structure, including freeing any allocated memory.
+ */
+void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz)
+{
+ fuzz_free((void **)&fuzz->url);
+ fuzz_free((void **)&fuzz->username);
+ fuzz_free((void **)&fuzz->password);
+ fuzz_free((void **)&fuzz->postfields);
+ fuzz_free((void **)&fuzz->cookie);
+ fuzz_free((void **)&fuzz->range);
+ fuzz_free((void **)&fuzz->customrequest);
+ fuzz_free((void **)&fuzz->mail_from);
+
+ if(fuzz->header_list != NULL) {
+ curl_slist_free_all(fuzz->header_list);
+ fuzz->header_list = NULL;
+ }
+
+ if(fuzz->mail_recipients_list != NULL) {
+ curl_slist_free_all(fuzz->mail_recipients_list);
+ fuzz->mail_recipients_list = NULL;
+ }
+
+ if(fuzz->easy != NULL) {
+ curl_easy_cleanup(fuzz->easy);
+ fuzz->easy = NULL;
+ }
+}
+
+/**
+ * If a pointer has been allocated, free that pointer.
+ */
+void fuzz_free(void **ptr)
+{
+ if(*ptr != NULL) {
+ free(*ptr);
+ *ptr = NULL;
+ }
+}
+
+/**
+ * Function for providing a socket to CURL already primed with data.
+ */
+static curl_socket_t fuzz_open_socket(void *ptr,
+ curlsocktype purpose,
+ struct curl_sockaddr *address)
+{
+ FUZZ_DATA *fuzz = (FUZZ_DATA *)ptr;
+ int fds[2];
+ curl_socket_t server_fd;
+ curl_socket_t client_fd;
+
+ /* Handle unused parameters */
+ (void)purpose;
+ (void)address;
+
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) {
+ /* Failed to create a pair of sockets. */
+ return CURL_SOCKET_BAD;
+ }
+
+ server_fd = fds[0];
+ client_fd = fds[1];
+
+ /* Try and write the response data to the server file descriptor so the
+ client can read it. */
+ if(write(server_fd,
+ fuzz->rsp1_data,
+ fuzz->rsp1_data_len) != (ssize_t)fuzz->rsp1_data_len) {
+ /* Failed to write the data. */
+ return CURL_SOCKET_BAD;
+ }
+
+ if(shutdown(server_fd, SHUT_WR)) {
+ return CURL_SOCKET_BAD;
+ }
+
+ return client_fd;
+}
+
+/**
+ * Callback function for setting socket options on the sockets created by
+ * fuzz_open_socket. In our testbed the sockets are "already connected".
+ */
+static int fuzz_sockopt_callback(void *ptr,
+ curl_socket_t curlfd,
+ curlsocktype purpose)
+{
+ (void)ptr;
+ (void)curlfd;
+ (void)purpose;
+
+ return CURL_SOCKOPT_ALREADY_CONNECTED;
+}
+
+/**
+ * Callback function for doing data uploads.
+ */
+static size_t fuzz_read_callback(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *ptr)
+{
+ FUZZ_DATA *fuzz = (FUZZ_DATA *)ptr;
+ curl_off_t nread;
+
+ /* If no upload data has been specified, then return an error code. */
+ if(fuzz->upload1_data_len == 0) {
+ /* No data to upload */
+ return CURL_READFUNC_ABORT;
+ }
+
+ /* Send the upload data. */
+ memcpy(buffer,
+ fuzz->upload1_data,
+ fuzz->upload1_data_len);
+
+ return fuzz->upload1_data_len;
+}
+
+/**
+ * Callback function for handling data output quietly.
+ */
+static size_t fuzz_write_callback(void *contents,
+ size_t size,
+ size_t nmemb,
+ void *ptr)
+{
+ size_t total = size * nmemb;
+ FUZZ_DATA *fuzz = (FUZZ_DATA *)ptr;
+ size_t copy_len = total;
+
+ /* Restrict copy_len to at most TEMP_WRITE_ARRAY_SIZE. */
+ if(copy_len > TEMP_WRITE_ARRAY_SIZE) {
+ copy_len = TEMP_WRITE_ARRAY_SIZE;
+ }
+
+ /* Copy bytes to the temp store just to ensure the parameters are
+ exercised. */
+ memcpy(fuzz->write_array, contents, copy_len);
+
+ return total;
+}
+
+/**
+ * TLV access function - gets the first TLV from a data stream.
+ */
+int fuzz_get_first_tlv(FUZZ_DATA *fuzz,
+ TLV *tlv)
+{
+ /* Reset the cursor. */
+ fuzz->state.data_pos = 0;
+ return fuzz_get_tlv_comn(fuzz, tlv);
+}
+
+/**
+ * TLV access function - gets the next TLV from a data stream.
+*/
+int fuzz_get_next_tlv(FUZZ_DATA *fuzz,
+ TLV *tlv)
+{
+ /* Advance the cursor by the full length of the previous TLV. */
+ fuzz->state.data_pos += sizeof(TLV_RAW) + tlv->length;
+
+ /* Work out if there's a TLV's worth of data to read */
+ if(fuzz->state.data_pos + sizeof(TLV_RAW) > fuzz->state.data_len) {
+ /* No more TLVs to parse */
+ return TLV_RC_NO_MORE_TLVS;
+ }
+
+ return fuzz_get_tlv_comn(fuzz, tlv);
+}
+
+/**
+ * Common TLV function for accessing TLVs in a data stream.
+ */
+int fuzz_get_tlv_comn(FUZZ_DATA *fuzz,
+ TLV *tlv)
+{
+ int rc = 0;
+ size_t data_offset;
+ TLV_RAW *raw;
+
+ /* Start by casting the data stream to a TLV. */
+ raw = (TLV_RAW *)&fuzz->state.data[fuzz->state.data_pos];
+ data_offset = fuzz->state.data_pos + sizeof(TLV_RAW);
+
+ /* Set the TLV values. */
+ tlv->type = to_u16(raw->raw_type);
+ tlv->length = to_u32(raw->raw_length);
+ tlv->value = &fuzz->state.data[data_offset];
+
+ /* Sanity check that the TLV length is ok. */
+ if(data_offset + tlv->length > fuzz->state.data_len) {
+ rc = TLV_RC_SIZE_ERROR;
+ }
+
+ return rc;
+}
+
+/**
+ * Do different actions on the CURL handle for different received TLVs.
+ */
+int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv)
+{
+ int rc;
+ char *tmp;
+
+ switch(tlv->type) {
+ case TLV_TYPE_RESPONSE1:
+ /* The pointers in the TLV will always be valid as long as the fuzz data
+ is in scope, which is the entirety of this file. */
+ fuzz->rsp1_data = tlv->value;
+ fuzz->rsp1_data_len = tlv->length;
+ break;
+
+ case TLV_TYPE_UPLOAD1:
+ /* The pointers in the TLV will always be valid as long as the fuzz data
+ is in scope, which is the entirety of this file. */
+ fuzz->upload1_data = tlv->value;
+ fuzz->upload1_data_len = tlv->length;
+
+ curl_easy_setopt(fuzz->easy, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(fuzz->easy,
+ CURLOPT_INFILESIZE_LARGE,
+ (curl_off_t)fuzz->upload1_data_len);
+ break;
+
+ case TLV_TYPE_HEADER:
+ tmp = fuzz_tlv_to_string(tlv);
+ fuzz->header_list = curl_slist_append(fuzz->header_list, tmp);
+ fuzz_free((void **)&tmp);
+ break;
+
+ case TLV_TYPE_MAIL_RECIPIENT:
+ tmp = fuzz_tlv_to_string(tlv);
+ fuzz->mail_recipients_list =
+ curl_slist_append(fuzz->mail_recipients_list, tmp);
+ fuzz_free((void **)&tmp);
+ break;
+
+ /* Define a set of singleton TLVs - they can only have their value set once
+ and all follow the same pattern. */
+ FSINGLETONTLV(TLV_TYPE_URL, url, CURLOPT_URL);
+ FSINGLETONTLV(TLV_TYPE_USERNAME, username, CURLOPT_USERNAME);
+ FSINGLETONTLV(TLV_TYPE_PASSWORD, password, CURLOPT_PASSWORD);
+ FSINGLETONTLV(TLV_TYPE_POSTFIELDS, postfields, CURLOPT_POSTFIELDS);
+ FSINGLETONTLV(TLV_TYPE_COOKIE, cookie, CURLOPT_COOKIE);
+ FSINGLETONTLV(TLV_TYPE_RANGE, range, CURLOPT_RANGE);
+ FSINGLETONTLV(TLV_TYPE_CUSTOMREQUEST, customrequest, CURLOPT_CUSTOMREQUEST);
+ FSINGLETONTLV(TLV_TYPE_MAIL_FROM, mail_from, CURLOPT_MAIL_FROM);
+
+ default:
+ /* The fuzzer generates lots of unknown TLVs - we don't want these in the
+ corpus so we reject any unknown TLVs. */
+ rc = 255;
+ goto EXIT_LABEL;
+ break;
+ }
+
+ rc = 0;
+
+EXIT_LABEL:
+
+ return rc;
+}
+
+/**
+ * Converts a TLV data and length into an allocated string.
+ */
+char *fuzz_tlv_to_string(TLV *tlv)
+{
+ char *tlvstr;
+
+ /* Allocate enough space, plus a null terminator */
+ tlvstr = (char *)malloc(tlv->length + 1);
+
+ if(tlvstr != NULL) {
+ memcpy(tlvstr, tlv->value, tlv->length);
+ tlvstr[tlv->length] = 0;
+ }
+
+ return tlvstr;
+}
diff --git a/tests/fuzz/curl_fuzzer.h b/tests/fuzz/curl_fuzzer.h
new file mode 100644
index 000000000..219ac3ee3
--- /dev/null
+++ b/tests/fuzz/curl_fuzzer.h
@@ -0,0 +1,186 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, Max Dymond, <cmeister2@gmail.com>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under 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>
+#include <testinput.h>
+
+/**
+ * TLV types.
+ */
+#define TLV_TYPE_URL 1
+#define TLV_TYPE_RESPONSE1 2
+#define TLV_TYPE_USERNAME 3
+#define TLV_TYPE_PASSWORD 4
+#define TLV_TYPE_POSTFIELDS 5
+#define TLV_TYPE_HEADER 6
+#define TLV_TYPE_COOKIE 7
+#define TLV_TYPE_UPLOAD1 8
+#define TLV_TYPE_RANGE 9
+#define TLV_TYPE_CUSTOMREQUEST 10
+#define TLV_TYPE_MAIL_RECIPIENT 11
+#define TLV_TYPE_MAIL_FROM 12
+
+/**
+ * TLV function return codes.
+ */
+#define TLV_RC_NO_ERROR 0
+#define TLV_RC_NO_MORE_TLVS 1
+#define TLV_RC_SIZE_ERROR 2
+
+/* Temporary write array size */
+#define TEMP_WRITE_ARRAY_SIZE 10
+
+/**
+ * Byte stream representation of the TLV header. Casting the byte stream
+ * to a TLV_RAW allows us to examine the type and length.
+ */
+typedef struct tlv_raw
+{
+ /* Type of the TLV - 16 bits. */
+ uint8_t raw_type[2];
+
+ /* Length of the TLV data - 32 bits. */
+ uint8_t raw_length[4];
+
+} TLV_RAW;
+
+typedef struct tlv
+{
+ /* Type of the TLV */
+ uint16_t type;
+
+ /* Length of the TLV data */
+ uint32_t length;
+
+ /* Pointer to data if length > 0. */
+ const uint8_t *value;
+
+} TLV;
+
+/**
+ * Internal state when parsing a TLV data stream.
+ */
+typedef struct fuzz_parse_state
+{
+ /* Data stream */
+ const uint8_t *data;
+ size_t data_len;
+
+ /* Current position of our "cursor" in processing the data stream. */
+ size_t data_pos;
+
+} FUZZ_PARSE_STATE;
+
+/**
+ * Data local to a fuzzing run.
+ */
+typedef struct fuzz_data
+{
+ /* CURL easy object */
+ CURL *easy;
+
+ /* Parser state */
+ FUZZ_PARSE_STATE state;
+
+ /* Temporary writefunction state */
+ char write_array[TEMP_WRITE_ARRAY_SIZE];
+
+ /* Response data and length */
+ const uint8_t *rsp1_data;
+ size_t rsp1_data_len;
+
+ /* Upload data and length; */
+ const uint8_t *upload1_data;
+ size_t upload1_data_len;
+
+ /* Singleton string fields. */
+ char *url;
+ char *username;
+ char *password;
+ char *postfields;
+ char *cookie;
+ char *range;
+ char *customrequest;
+ char *mail_from;
+
+ /* List of headers */
+ struct curl_slist *header_list;
+
+ /* List of mail recipients */
+ struct curl_slist *mail_recipients_list;
+
+} FUZZ_DATA;
+
+/* Function prototypes */
+uint32_t to_u32(uint8_t b[4]);
+uint16_t to_u16(uint8_t b[2]);
+int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz,
+ const uint8_t *data,
+ size_t data_len);
+void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz);
+void fuzz_free(void **ptr);
+static curl_socket_t fuzz_open_socket(void *ptr,
+ curlsocktype purpose,
+ struct curl_sockaddr *address);
+static int fuzz_sockopt_callback(void *ptr,
+ curl_socket_t curlfd,
+ curlsocktype purpose);
+static size_t fuzz_read_callback(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *ptr);
+static size_t fuzz_write_callback(void *contents,
+ size_t size,
+ size_t nmemb,
+ void *ptr);
+int fuzz_get_first_tlv(FUZZ_DATA *fuzz, TLV *tlv);
+int fuzz_get_next_tlv(FUZZ_DATA *fuzz, TLV *tlv);
+int fuzz_get_tlv_comn(FUZZ_DATA *fuzz, TLV *tlv);
+int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv);
+char *fuzz_tlv_to_string(TLV *tlv);
+
+/* Macros */
+#define FTRY(FUNC) \
+ { \
+ int _func_rc = (FUNC); \
+ if (_func_rc) \
+ { \
+ rc = _func_rc; \
+ goto EXIT_LABEL; \
+ } \
+ }
+
+#define FCHECK(COND) \
+ { \
+ if (!(COND)) \
+ { \
+ rc = 255; \
+ goto EXIT_LABEL; \
+ } \
+ }
+
+#define FSINGLETONTLV(TLVNAME, FIELDNAME, OPTNAME) \
+ case TLVNAME: \
+ FCHECK(fuzz->FIELDNAME == NULL); \
+ fuzz->FIELDNAME = fuzz_tlv_to_string(tlv); \
+ FTRY(curl_easy_setopt(fuzz->easy, OPTNAME, fuzz->FIELDNAME)); \
+ break \ No newline at end of file
diff --git a/tests/fuzz/generate_corpus.py b/tests/fuzz/generate_corpus.py
new file mode 100755
index 000000000..cffdd37bf
--- /dev/null
+++ b/tests/fuzz/generate_corpus.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# Simple script which generates corpus files.
+
+import argparse
+import logging
+import corpus
+import sys
+sys.path.append("..")
+import curl_test_data
+log = logging.getLogger(__name__)
+
+
+def generate_corpus(options):
+ td = curl_test_data.TestData("../data")
+
+ with open(options.output, "wb") as f:
+ enc = corpus.TLVEncoder(f)
+
+ # Write the URL to the file.
+ enc.write_string(enc.TYPE_URL, options.url)
+
+ # Write the first response to the file.
+ if options.rsp1:
+ enc.write_bytes(enc.TYPE_RSP1, options.rsp1.encode("utf-8"))
+
+ elif options.rsp1file:
+ with open(options.rsp1file, "rb") as g:
+ enc.write_bytes(enc.TYPE_RSP1, g.read())
+
+ elif options.rsp1test:
+ wstring = td.get_test_data(options.rsp1test)
+ enc.write_bytes(enc.TYPE_RSP1, wstring.encode("utf-8"))
+
+ # Write other options to file.
+ enc.maybe_write_string(enc.TYPE_USERNAME, options.username)
+ enc.maybe_write_string(enc.TYPE_PASSWORD, options.password)
+ enc.maybe_write_string(enc.TYPE_POSTFIELDS, options.postfields)
+ enc.maybe_write_string(enc.TYPE_COOKIE, options.cookie)
+ enc.maybe_write_string(enc.TYPE_RANGE, options.range)
+ enc.maybe_write_string(enc.TYPE_CUSTOMREQUEST, options.customrequest)
+ enc.maybe_write_string(enc.TYPE_MAIL_FROM, options.mailfrom)
+
+ # Write the first upload to the file.
+ if options.upload1:
+ enc.write_bytes(enc.TYPE_UPLOAD1, options.upload1.encode("utf-8"))
+ elif options.upload1file:
+ with open(options.upload1file, "rb") as g:
+ enc.write_bytes(enc.TYPE_UPLOAD1, g.read())
+
+ # Write an array of headers to the file.
+ if options.header:
+ for header in options.header:
+ enc.write_string(enc.TYPE_HEADER, header)
+
+ # Write an array of headers to the file.
+ if options.mailrecipient:
+ for mailrecipient in options.mailrecipient:
+ enc.write_string(enc.TYPE_MAIL_RECIPIENT, mailrecipient)
+
+ return ScriptRC.SUCCESS
+
+
+def get_options():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--output", required=True)
+ parser.add_argument("--url", required=True)
+ parser.add_argument("--username")
+ parser.add_argument("--password")
+ parser.add_argument("--postfields")
+ parser.add_argument("--header", action="append")
+ parser.add_argument("--cookie")
+ parser.add_argument("--range")
+ parser.add_argument("--customrequest")
+ parser.add_argument("--mailfrom")
+ parser.add_argument("--mailrecipient", action="append")
+
+ rsp1 = parser.add_mutually_exclusive_group(required=True)
+ rsp1.add_argument("--rsp1")
+ rsp1.add_argument("--rsp1file")
+ rsp1.add_argument("--rsp1test", type=int)
+
+ upload1 = parser.add_mutually_exclusive_group()
+ upload1.add_argument("--upload1")
+ upload1.add_argument("--upload1file")
+
+ return parser.parse_args()
+
+
+def setup_logging():
+ """
+ Set up logging from the command line options
+ """
+ root_logger = logging.getLogger()
+ formatter = logging.Formatter("%(asctime)s %(levelname)-5.5s %(message)s")
+ stdout_handler = logging.StreamHandler(sys.stdout)
+ stdout_handler.setFormatter(formatter)
+ stdout_handler.setLevel(logging.DEBUG)
+ root_logger.addHandler(stdout_handler)
+ root_logger.setLevel(logging.DEBUG)
+
+
+class ScriptRC(object):
+ """Enum for script return codes"""
+ SUCCESS = 0
+ FAILURE = 1
+ EXCEPTION = 2
+
+
+class ScriptException(Exception):
+ pass
+
+
+def main():
+ # Get the options from the user.
+ options = get_options()
+
+ setup_logging()
+
+ # Run main script.
+ try:
+ rc = generate_corpus(options)
+ except Exception as e:
+ log.exception(e)
+ rc = ScriptRC.EXCEPTION
+
+ log.info("Returning %d", rc)
+ return rc
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tests/fuzz/read_corpus.py b/tests/fuzz/read_corpus.py
new file mode 100755
index 000000000..bb8fcedcd
--- /dev/null
+++ b/tests/fuzz/read_corpus.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# Simple script which reads corpus files.
+
+import argparse
+import logging
+import sys
+import corpus
+log = logging.getLogger(__name__)
+
+
+def read_corpus(options):
+ with open(options.input, "rb") as f:
+ dec = corpus.TLVDecoder(f.read())
+ for tlv in dec:
+ print(tlv)
+
+ return ScriptRC.SUCCESS
+
+
+def get_options():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--input", required=True)
+ return parser.parse_args()
+
+
+def setup_logging():
+ """
+ Set up logging from the command line options
+ """
+ root_logger = logging.getLogger()
+ formatter = logging.Formatter("%(asctime)s %(levelname)-5.5s %(message)s")
+ stdout_handler = logging.StreamHandler(sys.stdout)
+ stdout_handler.setFormatter(formatter)
+ stdout_handler.setLevel(logging.DEBUG)
+ root_logger.addHandler(stdout_handler)
+ root_logger.setLevel(logging.DEBUG)
+
+
+class ScriptRC(object):
+ """Enum for script return codes"""
+ SUCCESS = 0
+ FAILURE = 1
+ EXCEPTION = 2
+
+
+class ScriptException(Exception):
+ pass
+
+
+def main():
+ # Get the options from the user.
+ options = get_options()
+
+ setup_logging()
+
+ # Run main script.
+ try:
+ rc = read_corpus(options)
+ except Exception as e:
+ log.exception(e)
+ rc = ScriptRC.EXCEPTION
+
+ log.info("Returning %d", rc)
+ return rc
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tests/fuzz/standalone_fuzz_target_runner.cc b/tests/fuzz/standalone_fuzz_target_runner.cc
new file mode 100644
index 000000000..9b2316ed6
--- /dev/null
+++ b/tests/fuzz/standalone_fuzz_target_runner.cc
@@ -0,0 +1,89 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, Max Dymond, <cmeister2@gmail.com>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "testinput.h"
+
+/**
+ * Main procedure for standalone fuzzing engine.
+ *
+ * Reads filenames from the argument array. For each filename, read the file
+ * into memory and then call the fuzzing interface with the data.
+ */
+int main(int argc, char **argv)
+{
+ int ii;
+ FILE *infile;
+ uint8_t *buffer = NULL;
+ size_t buffer_len;
+
+ for(ii = 1; ii < argc; ii++) {
+ /* Try and open the file. */
+ infile = fopen(argv[ii], "rb");
+ if(infile) {
+ printf("[%s] Open succeeded! \n", argv[ii]);
+
+ /* Get the length of the file. */
+ fseek(infile, 0L, SEEK_END);
+ buffer_len = ftell(infile);
+
+ /* Reset the file indicator to the beginning of the file. */
+ fseek(infile, 0L, SEEK_SET);
+
+ /* Allocate a buffer for the file contents. */
+ buffer = (uint8_t *)calloc(buffer_len, sizeof(uint8_t));
+ if(buffer) {
+ /* Read all the text from the file into the buffer. */
+ fread(buffer, sizeof(uint8_t), buffer_len, infile);
+ printf("[%s] Read %zu bytes, calling fuzzer\n", argv[ii], buffer_len);
+
+ /* Call the fuzzer with the data. */
+ LLVMFuzzerTestOneInput(buffer, buffer_len);
+
+ printf("[%s] Fuzzing complete\n", argv[ii]);
+
+ /* Free the buffer as it's no longer needed. */
+ free(buffer);
+ buffer = NULL;
+ }
+ else
+ {
+ fprintf(stderr,
+ "[%s] Failed to allocate %zu bytes \n",
+ argv[ii],
+ buffer_len);
+ }
+
+ /* Close the file as it's no longer needed. */
+ fclose(infile);
+ infile = NULL;
+ }
+ else
+ {
+ /* Failed to open the file. Maybe wrong name or wrong permissions? */
+ fprintf(stderr, "[%s] Open failed. \n", argv[ii]);
+ }
+ }
+}
diff --git a/src/tool_mfiles.h b/tests/fuzz/testinput.h
index 827f40065..0746cba73 100644
--- a/src/tool_mfiles.h
+++ b/tests/fuzz/testinput.h
@@ -1,5 +1,3 @@
-#ifndef HEADER_CURL_TOOL_MFILES_H
-#define HEADER_CURL_TOOL_MFILES_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2017, Max Dymond, <cmeister2@gmail.com>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,26 +19,5 @@
* 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 */
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); \ No newline at end of file
diff --git a/tests/libtest/.gitignore b/tests/libtest/.gitignore
index ab8b8db67..863e50e28 100644
--- a/tests/libtest/.gitignore
+++ b/tests/libtest/.gitignore
@@ -1,7 +1,10 @@
chkhostname
lib15[0-9][0-9]
+lib1521.c
lib19[0-9][0-9]
lib2033
lib5[0-9][0-9]
+lib64[3-5]
+lib650
libauthretry
libntlmconnect
diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am
index 6ebad89c8..f4c705e41 100644
--- a/tests/libtest/Makefile.am
+++ b/tests/libtest/Makefile.am
@@ -109,6 +109,21 @@ libhostname_la_SOURCES = sethostname.c sethostname.h
libhostname_la_LIBADD =
libhostname_la_DEPENDENCIES =
+# Build a stub gssapi implementation for testing
+if BUILD_STUB_GSS
+noinst_LTLIBRARIES += libstubgss.la
+
+libstubgss_la_CPPFLAGS = $(AM_CPPFLAGS)
+libstubgss_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -rpath /nowhere
+libstubgss_la_CFLAGS = $(AM_CFLAGS) -g -Wno-unused-parameter
+
+libstubgss_la_SOURCES = stub_gssapi.c stub_gssapi.h
+
+libstubgss_la_LIBADD =
+libstubgss_la_DEPENDENCIES =
+endif
+
+
lib1521.c: $(top_srcdir)/tests/libtest/mk-lib1521.pl $(top_srcdir)/include/gnurl/curl.h
@PERL@ $(top_srcdir)/tests/libtest/mk-lib1521.pl < $(top_srcdir)/include/gnurl/curl.h > lib1521.c
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 727582bd0..065899276 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -19,7 +19,8 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
lib547 lib548 lib549 lib552 lib553 lib554 lib555 lib556 lib557 lib558 \
lib559 lib560 lib562 lib564 lib565 lib566 lib567 lib568 lib569 lib570 \
lib571 lib572 lib573 lib574 lib575 lib576 lib578 lib579 lib582 \
- lib583 lib585 lib586 lib587 lib590 lib591 lib597 lib598 lib599 \
+ lib583 lib585 lib586 lib587 lib589 lib590 lib591 lib597 lib598 lib599 \
+ lib643 lib644 lib645 lib650 \
lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515 lib1517 \
lib1520 lib1521 \
@@ -282,6 +283,9 @@ lib586_CPPFLAGS = $(AM_CPPFLAGS)
lib587_SOURCES = lib554.c $(SUPPORTFILES)
lib587_CPPFLAGS = $(AM_CPPFLAGS) -DLIB587
+lib589_SOURCES = lib589.c $(SUPPORTFILES)
+lib589_CPPFLAGS = $(AM_CPPFLAGS)
+
lib590_SOURCES = lib590.c $(SUPPORTFILES)
lib590_CPPFLAGS = $(AM_CPPFLAGS)
@@ -299,6 +303,18 @@ lib598_CPPFLAGS = $(AM_CPPFLAGS)
lib599_SOURCES = lib599.c $(SUPPORTFILES)
lib599_CPPFLAGS = $(AM_CPPFLAGS)
+lib643_SOURCES = lib643.c $(SUPPORTFILES)
+lib643_CPPFLAGS = $(AM_CPPFLAGS)
+
+lib644_SOURCES = lib643.c $(SUPPORTFILES)
+lib644_CPPFLAGS = $(AM_CPPFLAGS) -DLIB644
+
+lib645_SOURCES = lib643.c $(SUPPORTFILES)
+lib645_CPPFLAGS = $(AM_CPPFLAGS) -DLIB645
+
+lib650_SOURCES = lib650.c $(SUPPORTFILES)
+lib650_CPPFLAGS = $(AM_CPPFLAGS)
+
lib1500_SOURCES = lib1500.c $(SUPPORTFILES) $(TESTUTIL)
lib1500_LDADD = $(TESTUTIL_LIBS)
lib1500_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/tests/libtest/first.c b/tests/libtest/first.c
index 72140e314..86d84cacd 100644
--- a/tests/libtest/first.c
+++ b/tests/libtest/first.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -72,8 +72,8 @@ void wait_ms(int ms)
select_wrapper(0, NULL, NULL, NULL, &t);
}
-char *libtest_arg2=NULL;
-char *libtest_arg3=NULL;
+char *libtest_arg2 = NULL;
+char *libtest_arg3 = NULL;
int test_argc;
char **test_argv;
@@ -118,12 +118,12 @@ static void memory_tracking_init(void)
/* returns a hexdump in a static memory area */
char *hexdump(const unsigned char *buffer, size_t len)
{
- static char dump[200*3+1];
+ static char dump[200 * 3 + 1];
char *p = dump;
size_t i;
if(len > 200)
return NULL;
- for(i=0; i<len; i++, p += 3)
+ for(i = 0; i<len; i++, p += 3)
snprintf(p, 4, "%02x ", buffer[i]);
return dump;
}
@@ -162,10 +162,10 @@ int main(int argc, char **argv)
test_argv = argv;
if(argc>2)
- libtest_arg2=argv[2];
+ libtest_arg2 = argv[2];
if(argc>3)
- libtest_arg3=argv[3];
+ libtest_arg3 = argv[3];
URL = argv[1]; /* provide this to the rest */
diff --git a/tests/libtest/lib1501.c b/tests/libtest/lib1501.c
index 8a6ef5172..96094d699 100644
--- a/tests/libtest/lib1501.c
+++ b/tests/libtest/lib1501.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -78,7 +78,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
diff --git a/tests/libtest/lib1502.c b/tests/libtest/lib1502.c
index bd555cbaf..188c120f8 100644
--- a/tests/libtest/lib1502.c
+++ b/tests/libtest/lib1502.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -99,7 +99,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
diff --git a/tests/libtest/lib1506.c b/tests/libtest/lib1506.c
index 47fc335ce..d456bc95c 100644
--- a/tests/libtest/lib1506.c
+++ b/tests/libtest/lib1506.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013, Linus Nielsen Feltzing <linus@haxx.se>
+ * Copyright (C) 2013, 2017, 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
@@ -45,7 +45,7 @@ int test(char *URL)
(void)URL;
/* Create fake DNS entries for serverX.example.com for all handles */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
snprintf(dnsentry, sizeof(dnsentry), "server%d.example.com:%s:%s",
i + 1, port, address);
printf("%s\n", dnsentry);
@@ -66,7 +66,7 @@ int test(char *URL)
multi_setopt(m, CURLMOPT_MAXCONNECTS, 3L);
/* get NUM_HANDLES easy handles */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
/* get an easy handle */
easy_init(curl[i]);
/* specify target */
@@ -85,7 +85,7 @@ int test(char *URL)
fprintf(stderr, "Start at URL 0\n");
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
/* add handle to multi */
multi_add_handle(m, curl[i]);
@@ -112,7 +112,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
@@ -123,7 +123,7 @@ test_cleanup:
/* proper cleanup sequence - type PB */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
curl_multi_remove_handle(m, curl[i]);
curl_easy_cleanup(curl[i]);
}
diff --git a/tests/libtest/lib1507.c b/tests/libtest/lib1507.c
index cd8500195..5e3a5926a 100644
--- a/tests/libtest/lib1507.c
+++ b/tests/libtest/lib1507.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -118,7 +118,7 @@ int test(char *URL)
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
if(tutil_tvdiff(tutil_tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
fprintf(stderr, "ABORTING TEST, since it seems "
diff --git a/tests/libtest/lib1510.c b/tests/libtest/lib1510.c
index 25e9fed31..d72749b24 100644
--- a/tests/libtest/lib1510.c
+++ b/tests/libtest/lib1510.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013, Linus Nielsen Feltzing <linus@haxx.se>
+ * Copyright (C) 2013, 2017, 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
@@ -43,7 +43,7 @@ int test(char *URL)
(void)URL;
/* Create fake DNS entries for serverX.example.com for all handles */
- for(i=0; i < NUM_URLS; i++) {
+ for(i = 0; i < NUM_URLS; i++) {
snprintf(dnsentry, sizeof(dnsentry), "server%d.example.com:%s:%s", i + 1,
port, address);
printf("%s\n", dnsentry);
@@ -72,7 +72,7 @@ int test(char *URL)
easy_setopt(curl, CURLOPT_MAXCONNECTS, 3L);
/* get NUM_HANDLES easy handles */
- for(i=0; i < NUM_URLS; i++) {
+ for(i = 0; i < NUM_URLS; i++) {
/* specify target */
snprintf(target_url, sizeof(target_url),
"http://server%d.example.com:%s/path/1510%04i",
diff --git a/tests/libtest/lib1512.c b/tests/libtest/lib1512.c
index f4091b45a..5e794b293 100644
--- a/tests/libtest/lib1512.c
+++ b/tests/libtest/lib1512.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2016, Linus Nielsen Feltzing <linus@haxx.se>
+ * Copyright (C) 2013 - 2017, 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
@@ -55,7 +55,7 @@ int test(char *URL)
slist = curl_slist_append(slist, dnsentry);
/* get NUM_HANDLES easy handles */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
/* get an easy handle */
easy_init(curl[i]);
/* specify target */
@@ -76,7 +76,7 @@ int test(char *URL)
easy_setopt(curl[0], CURLOPT_RESOLVE, slist);
/* run NUM_HANDLES transfers */
- for(i=0; (i < NUM_HANDLES) && !res; i++)
+ for(i = 0; (i < NUM_HANDLES) && !res; i++)
res = curl_easy_perform(curl[i]);
test_cleanup:
diff --git a/tests/libtest/lib1513.c b/tests/libtest/lib1513.c
index d0123f1f6..932ca7208 100644
--- a/tests/libtest/lib1513.c
+++ b/tests/libtest/lib1513.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,7 +48,7 @@ static int progressKiller(void *arg,
int test(char *URL)
{
CURL *curl;
- int res=0;
+ int res = 0;
global_init(CURL_GLOBAL_ALL);
diff --git a/tests/libtest/lib1515.c b/tests/libtest/lib1515.c
index c1499381a..39bccc59b 100644
--- a/tests/libtest/lib1515.c
+++ b/tests/libtest/lib1515.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -87,7 +87,7 @@ static int do_one_request(CURLM *m, char *URL, char *resolve)
timeout.tv_usec = 0;
multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
multi_perform(m, &still_running);
@@ -148,6 +148,7 @@ int test(char *URL)
test_cleanup:
curl_multi_cleanup(multi);
+ curl_global_cleanup();
return (int) res;
}
diff --git a/tests/libtest/lib1517.c b/tests/libtest/lib1517.c
index e270ed74d..ea622b046 100644
--- a/tests/libtest/lib1517.c
+++ b/tests/libtest/lib1517.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -54,7 +54,7 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
struct WriteThis pooh;
diff --git a/tests/libtest/lib1531.c b/tests/libtest/lib1531.c
index 287acd6c6..5ee617e52 100644
--- a/tests/libtest/lib1531.c
+++ b/tests/libtest/lib1531.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,6 +37,9 @@ int test(char *URL)
int still_running; /* keep number of running handles */
CURLMsg *msg; /* for picking up messages with the transfer status */
int msgs_left; /* how many messages are left */
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
/* Allocate one CURL handle per transfer */
easy = curl_easy_init();
@@ -112,7 +115,7 @@ int test(char *URL)
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
- rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
@@ -139,6 +142,7 @@ int test(char *URL)
/* Free the CURL handles */
curl_easy_cleanup(easy);
+ curl_global_cleanup();
return 0;
}
diff --git a/tests/libtest/lib1538.c b/tests/libtest/lib1538.c
index e4e16f203..91481e88d 100644
--- a/tests/libtest/lib1538.c
+++ b/tests/libtest/lib1538.c
@@ -37,13 +37,14 @@ int test(char *URL)
curl_easy_strerror(-INT_MAX);
curl_multi_strerror(-INT_MAX);
curl_share_strerror(-INT_MAX);
- for(easyret=CURLE_OK; easyret <= CURL_LAST; easyret++) {
+ for(easyret = CURLE_OK; easyret <= CURL_LAST; easyret++) {
printf("e%d: %s\n", (int)easyret, curl_easy_strerror(easyret));
}
- for(multiret=CURLM_CALL_MULTI_PERFORM; multiret <= CURLM_LAST; multiret++) {
+ for(multiret = CURLM_CALL_MULTI_PERFORM; multiret <= CURLM_LAST;
+ multiret++) {
printf("m%d: %s\n", (int)multiret, curl_multi_strerror(multiret));
}
- for(shareret=CURLSHE_OK; shareret <= CURLSHE_LAST; shareret++) {
+ for(shareret = CURLSHE_OK; shareret <= CURLSHE_LAST; shareret++) {
printf("s%d: %s\n", (int)shareret, curl_share_strerror(shareret));
}
diff --git a/tests/libtest/lib1550.c b/tests/libtest/lib1550.c
index 5c2fb6f6a..1df5503fd 100644
--- a/tests/libtest/lib1550.c
+++ b/tests/libtest/lib1550.c
@@ -27,13 +27,20 @@
int test(char *URL)
{
- CURLM *handle = curl_multi_init();
- const char *bl_servers[] = {"Microsoft-IIS/6.0", "nginx/0.8.54", NULL};
- const char *bl_sites[] = {"curl.haxx.se:443", "example.com:80", NULL};
+ CURLM *handle;
+ int res = CURLE_OK;
+ static const char * const bl_servers[] =
+ {"Microsoft-IIS/6.0", "nginx/0.8.54", NULL};
+ static const char * const bl_sites[] =
+ {"curl.haxx.se:443", "example.com:80", NULL};
+
+ global_init(CURL_GLOBAL_ALL);
+ handle = curl_multi_init();
(void)URL; /* unused */
curl_multi_setopt(handle, CURLMOPT_PIPELINING_SERVER_BL, bl_servers);
curl_multi_setopt(handle, CURLMOPT_PIPELINING_SITE_BL, bl_sites);
curl_multi_cleanup(handle);
+ curl_global_cleanup();
return 0;
}
diff --git a/tests/libtest/lib1551.c b/tests/libtest/lib1551.c
index e3ff3b313..edd6e9c8f 100644
--- a/tests/libtest/lib1551.c
+++ b/tests/libtest/lib1551.c
@@ -30,6 +30,7 @@ int test(char *URL)
CURL *curl;
CURLcode res = CURLE_OK;
+ global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, URL);
@@ -41,5 +42,6 @@ int test(char *URL)
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
+ curl_global_cleanup();
return (int)res;
}
diff --git a/tests/libtest/lib1900.c b/tests/libtest/lib1900.c
index cac1dd1d9..109c57062 100644
--- a/tests/libtest/lib1900.c
+++ b/tests/libtest/lib1900.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2013 - 2017, 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
@@ -88,13 +88,13 @@ static int parse_url_file(const char *filename)
static void free_urls(void)
{
int i;
- for(i = 0;i < num_handles;i++) {
+ for(i = 0; i < num_handles; i++) {
Curl_safefree(urlstring[i]);
}
- for(i = 0;i < blacklist_num_servers;i++) {
+ for(i = 0; i < blacklist_num_servers; i++) {
Curl_safefree(server_blacklist[i]);
}
- for(i = 0;i < blacklist_num_sites;i++) {
+ for(i = 0; i < blacklist_num_sites; i++) {
Curl_safefree(site_blacklist[i]);
}
}
@@ -103,7 +103,7 @@ static int create_handles(void)
{
int i;
- for(i = 0;i < num_handles;i++) {
+ for(i = 0; i < num_handles; i++) {
handles[i] = curl_easy_init();
}
return 0;
@@ -126,7 +126,7 @@ static void remove_handles(void)
{
int i;
- for(i = 0;i < num_handles;i++) {
+ for(i = 0; i < num_handles; i++) {
if(handles[i])
curl_easy_cleanup(handles[i]);
}
@@ -229,7 +229,7 @@ int test(char *URL)
interval.tv_sec = 0;
interval.tv_usec = 1000;
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib500.c b/tests/libtest/lib500.c
index d17b24b20..677ab73a7 100644
--- a/tests/libtest/lib500.c
+++ b/tests/libtest/lib500.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,7 +61,7 @@ int test(char *URL)
{
CURLcode res;
CURL *curl;
- char *ipstr=NULL;
+ char *ipstr = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib502.c b/tests/libtest/lib502.c
index 7cf6415a6..ce4bc47d1 100644
--- a/tests/libtest/lib502.c
+++ b/tests/libtest/lib502.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,7 +73,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib503.c b/tests/libtest/lib503.c
index 2eb287483..15b45f95b 100644
--- a/tests/libtest/lib503.c
+++ b/tests/libtest/lib503.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2012, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -83,7 +83,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib504.c b/tests/libtest/lib504.c
index 3466dc948..771b2038a 100644
--- a/tests/libtest/lib504.c
+++ b/tests/libtest/lib504.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -95,7 +95,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib505.c b/tests/libtest/lib505.c
index ad5d214c6..cc7463bde 100644
--- a/tests/libtest/lib505.c
+++ b/tests/libtest/lib505.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,7 +43,7 @@ int test(char *URL)
struct_stat file_info;
struct curl_slist *hl;
- struct curl_slist *headerlist=NULL;
+ struct curl_slist *headerlist = NULL;
const char *buf_1 = "RNFR 505";
const char *buf_2 = "RNTO 505-forreal";
diff --git a/tests/libtest/lib506.c b/tests/libtest/lib506.c
index d26252b6f..1b522be64 100644
--- a/tests/libtest/lib506.c
+++ b/tests/libtest/lib506.c
@@ -131,7 +131,7 @@ static void *fire(void *ptr)
struct curl_slist *headers;
struct Tdata *tdata = (struct Tdata*)ptr;
CURL *curl;
- int i=0;
+ int i = 0;
curl = curl_easy_init();
if(!curl) {
@@ -261,7 +261,7 @@ int test(char *URL)
res = 0;
/* start treads */
- for(i=1; i<=THREADS; i++) {
+ for(i = 1; i <= THREADS; i++) {
/* set thread data */
tdata.url = suburl(URL, i); /* must be curl_free()d */
@@ -349,7 +349,7 @@ int test(char *URL)
/* try to free share, expect to fail because share is in use*/
printf("try SHARE_CLEANUP...\n");
scode = curl_share_cleanup(share);
- if(scode==CURLSHE_OK) {
+ if(scode == CURLSHE_OK) {
fprintf(stderr, "curl_share_cleanup succeed but error expected\n");
share = NULL;
}
@@ -368,7 +368,7 @@ test_cleanup:
/* free share */
printf("SHARE_CLEANUP\n");
scode = curl_share_cleanup(share);
- if(scode!=CURLSHE_OK)
+ if(scode != CURLSHE_OK)
fprintf(stderr, "curl_share_cleanup failed, code errno %d\n",
(int)scode);
diff --git a/tests/libtest/lib507.c b/tests/libtest/lib507.c
index ebe897ac8..9cd47ccd5 100644
--- a/tests/libtest/lib507.c
+++ b/tests/libtest/lib507.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -70,7 +70,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
diff --git a/tests/libtest/lib508.c b/tests/libtest/lib508.c
index 1f6c6838a..30705e46a 100644
--- a/tests/libtest/lib508.c
+++ b/tests/libtest/lib508.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,7 +50,7 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
struct WriteThis pooh;
diff --git a/tests/libtest/lib510.c b/tests/libtest/lib510.c
index 4c290f1ef..4d568df44 100644
--- a/tests/libtest/lib510.c
+++ b/tests/libtest/lib510.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -62,7 +62,7 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
struct curl_slist *slist = NULL;
struct WriteThis pooh;
pooh.counter = 0;
diff --git a/tests/libtest/lib513.c b/tests/libtest/lib513.c
index 7c34bc4db..c6a98cca2 100644
--- a/tests/libtest/lib513.c
+++ b/tests/libtest/lib513.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,7 +35,7 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib514.c b/tests/libtest/lib514.c
index 7b33d52f9..702058b19 100644
--- a/tests/libtest/lib514.c
+++ b/tests/libtest/lib514.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib515.c b/tests/libtest/lib515.c
index 6fb178720..9f29d43c9 100644
--- a/tests/libtest/lib515.c
+++ b/tests/libtest/lib515.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib516.c b/tests/libtest/lib516.c
index 00c54c450..6d83e218c 100644
--- a/tests/libtest/lib516.c
+++ b/tests/libtest/lib516.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib517.c b/tests/libtest/lib517.c
index 22162ff1e..af7b2aa7a 100644
--- a/tests/libtest/lib517.c
+++ b/tests/libtest/lib517.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -131,7 +131,7 @@ int test(char *URL)
(void)URL; /* not used */
- for(i=0; dates[i]; i++) {
+ for(i = 0; dates[i]; i++) {
printf("%d: %s => %ld\n", i, dates[i], (long)curl_getdate(dates[i], NULL));
}
diff --git a/tests/libtest/lib525.c b/tests/libtest/lib525.c
index 715b7fbe2..c179960c1 100644
--- a/tests/libtest/lib525.c
+++ b/tests/libtest/lib525.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -132,7 +132,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib526.c b/tests/libtest/lib526.c
index 522cd7422..42eb7cb18 100644
--- a/tests/libtest/lib526.c
+++ b/tests/libtest/lib526.c
@@ -59,7 +59,7 @@ int test(char *URL)
int current = 0;
int i;
- for(i=0; i < NUM_HANDLES; i++)
+ for(i = 0; i < NUM_HANDLES; i++)
curl[i] = NULL;
start_test_timing();
@@ -67,7 +67,7 @@ int test(char *URL)
global_init(CURL_GLOBAL_ALL);
/* get NUM_HANDLES easy handles */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
easy_init(curl[i]);
/* specify target */
easy_setopt(curl[i], CURLOPT_URL, URL);
@@ -133,7 +133,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
@@ -145,7 +145,7 @@ test_cleanup:
/* test 526 and 528 */
/* proper cleanup sequence - type PB */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
curl_multi_remove_handle(m, curl[i]);
curl_easy_cleanup(curl[i]);
}
@@ -162,7 +162,7 @@ test_cleanup:
will be leaked, let's use undocumented cleanup sequence - type UB */
if(res)
- for(i=0; i < NUM_HANDLES; i++)
+ for(i = 0; i < NUM_HANDLES; i++)
curl_easy_cleanup(curl[i]);
curl_multi_cleanup(m);
@@ -173,7 +173,7 @@ test_cleanup:
/* test 532 */
/* undocumented cleanup sequence - type UB */
- for(i=0; i < NUM_HANDLES; i++)
+ for(i = 0; i < NUM_HANDLES; i++)
curl_easy_cleanup(curl[i]);
curl_multi_cleanup(m);
curl_global_cleanup();
diff --git a/tests/libtest/lib530.c b/tests/libtest/lib530.c
index 82bfab36c..7b71fa5e8 100644
--- a/tests/libtest/lib530.c
+++ b/tests/libtest/lib530.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@ int test(char *URL)
char target_url[256];
int handles_added = 0;
- for(i=0; i < NUM_HANDLES; i++)
+ for(i = 0; i < NUM_HANDLES; i++)
curl[i] = NULL;
start_test_timing();
@@ -49,7 +49,7 @@ int test(char *URL)
multi_init(m);
/* get NUM_HANDLES easy handles */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
/* get an easy handle */
easy_init(curl[i]);
/* specify target */
@@ -101,7 +101,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
@@ -110,7 +110,7 @@ test_cleanup:
/* proper cleanup sequence - type PB */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
curl_multi_remove_handle(m, curl[i]);
curl_easy_cleanup(curl[i]);
}
diff --git a/tests/libtest/lib533.c b/tests/libtest/lib533.c
index 706b269fe..7dd0fb59c 100644
--- a/tests/libtest/lib533.c
+++ b/tests/libtest/lib533.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@ int test(char *URL)
CURL *curl = NULL;
int running;
CURLM *m = NULL;
- int current=0;
+ int current = 0;
start_test_timing();
@@ -95,7 +95,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib536.c b/tests/libtest/lib536.c
index f3ba5734c..e6943626d 100644
--- a/tests/libtest/lib536.c
+++ b/tests/libtest/lib536.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -63,7 +63,7 @@ static int perform(CURLM *multi)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- res_select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
+ res_select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
if(res)
return res;
diff --git a/tests/libtest/lib540.c b/tests/libtest/lib540.c
index ac862092f..a13653ce6 100644
--- a/tests/libtest/lib540.c
+++ b/tests/libtest/lib540.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -152,7 +152,7 @@ static int loop(int num, CURLM *cm, const char *url, const char *userpwd,
T.tv_usec = 0;
}
- res_select_test(M+1, &R, &W, &E, &T);
+ res_select_test(M + 1, &R, &W, &E, &T);
if(res)
return res;
}
@@ -165,7 +165,7 @@ static int loop(int num, CURLM *cm, const char *url, const char *userpwd,
curl_easy_strerror(msg->data.result));
curl_multi_remove_handle(cm, e);
curl_easy_cleanup(e);
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
if(eh[i] == e) {
eh[i] = NULL;
break;
@@ -192,7 +192,7 @@ int test(char *URL)
int res = 0;
int i;
- for(i=0; i < NUM_HANDLES; i++)
+ for(i = 0; i < NUM_HANDLES; i++)
eh[i] = NULL;
start_test_timing();
@@ -234,7 +234,7 @@ test_cleanup:
/* proper cleanup sequence - type PB */
- for(i=0; i < NUM_HANDLES; i++) {
+ for(i = 0; i < NUM_HANDLES; i++) {
curl_multi_remove_handle(cm, eh[i]);
curl_easy_cleanup(eh[i]);
}
diff --git a/tests/libtest/lib543.c b/tests/libtest/lib543.c
index 6d2532d12..957839f7a 100644
--- a/tests/libtest/lib543.c
+++ b/tests/libtest/lib543.c
@@ -27,15 +27,18 @@
int test(char *URL)
{
- unsigned char a[] = {0x9c, 0x26, 0x4b, 0x3d, 0x49, 0x4, 0xa1, 0x1,
- 0xe0, 0xd8, 0x7c, 0x20, 0xb7, 0xef, 0x53, 0x29, 0xfa,
- 0x1d, 0x57, 0xe1};
+ static const unsigned char a[] = {
+ 0x9c, 0x26, 0x4b, 0x3d, 0x49, 0x4, 0xa1, 0x1,
+ 0xe0, 0xd8, 0x7c, 0x20, 0xb7, 0xef, 0x53, 0x29, 0xfa,
+ 0x1d, 0x57, 0xe1};
CURL *easy;
int asize;
char *s;
+ CURLcode res = CURLE_OK;
(void)URL;
+ global_init(CURL_GLOBAL_ALL);
easy = curl_easy_init();
if(!easy) {
fprintf(stderr, "curl_easy_init() failed\n");
@@ -44,7 +47,7 @@ int test(char *URL)
asize = (int)sizeof(a);
- s = curl_easy_escape(easy, (char *)a, asize);
+ s = curl_easy_escape(easy, (const char *)a, asize);
if(s)
printf("%s\n", s);
@@ -53,6 +56,7 @@ int test(char *URL)
curl_free(s);
curl_easy_cleanup(easy);
+ curl_global_cleanup();
return 0;
}
diff --git a/tests/libtest/lib544.c b/tests/libtest/lib544.c
index 28eacdaf6..1f832d2a6 100644
--- a/tests/libtest/lib544.c
+++ b/tests/libtest/lib544.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,7 @@ static char teststring[] =
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib547.c b/tests/libtest/lib547.c
index ce967c085..3db4890de 100644
--- a/tests/libtest/lib547.c
+++ b/tests/libtest/lib547.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -82,7 +82,7 @@ int test(char *URL)
CURLcode res;
CURL *curl;
#ifndef LIB548
- int counter=0;
+ int counter = 0;
#endif
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib552.c b/tests/libtest/lib552.c
index 3a93dafaf..5082eb044 100644
--- a/tests/libtest/lib552.c
+++ b/tests/libtest/lib552.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,7 @@ void dump(const char *text,
size_t i;
size_t c;
- unsigned int width=0x10;
+ unsigned int width = 0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
@@ -48,30 +48,32 @@ void dump(const char *text,
fprintf(stream, "%s, %d bytes (0x%x)\n", text, (int)size, (int)size);
- for(i=0; i<size; i+= width) {
+ for(i = 0; i<size; i += width) {
fprintf(stream, "%04x: ", (int)i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
- if(i+c < size)
- fprintf(stream, "%02x ", ptr[i+c]);
+ if(i + c < size)
+ fprintf(stream, "%02x ", ptr[i + c]);
else
fputs(" ", stream);
}
- for(c = 0; (c < width) && (i+c < size); c++) {
+ for(c = 0; (c < width) && (i + c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
- if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
- i+=(c+2-width);
+ if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+ ptr[i + c + 1] == 0x0A) {
+ i += (c + 2 - width);
break;
}
fprintf(stream, "%c",
- (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+ (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)? ptr[i + c] : '.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
- if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
- i+=(c+3-width);
+ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+ ptr[i + c + 2] == 0x0A) {
+ i += (c + 3 - width);
break;
}
}
@@ -166,19 +168,15 @@ static curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp)
int test(char *URL)
{
CURL *curl;
- CURLcode res = CURLE_OUT_OF_MEMORY;
+ CURLcode res = CURLE_OK;
struct data config;
size_t i;
static const char fill[] = "test data";
config.trace_ascii = 1; /* enable ascii tracing */
- curl = curl_easy_init();
- if(!curl) {
- fprintf(stderr, "curl_easy_init() failed\n");
- curl_global_cleanup();
- return TEST_ERR_MAJOR_BAD;
- }
+ global_init(CURL_GLOBAL_ALL);
+ easy_init(curl);
test_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
test_setopt(curl, CURLOPT_DEBUGDATA, &config);
@@ -186,7 +184,7 @@ int test(char *URL)
test_setopt(curl, CURLOPT_VERBOSE, 1L);
/* setup repeated data string */
- for(i=0; i < sizeof(databuf); ++i)
+ for(i = 0; i < sizeof(databuf); ++i)
databuf[i] = fill[i % sizeof fill];
/* Post */
diff --git a/tests/libtest/lib553.c b/tests/libtest/lib553.c
index 288f4c1d1..c06561e1d 100644
--- a/tests/libtest/lib553.c
+++ b/tests/libtest/lib553.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,7 +32,7 @@
static size_t myreadfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
- static size_t total=POSTLEN;
+ static size_t total = POSTLEN;
static char buf[1024];
(void)stream;
@@ -60,7 +60,7 @@ int test(char *URL)
CURL *curl;
CURLcode res = CURLE_FAILED_INIT;
int i;
- struct curl_slist *headerlist=NULL, *hl;
+ struct curl_slist *headerlist = NULL, *hl;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
@@ -77,7 +77,7 @@ int test(char *URL)
for(i = 0; i < NUM_HEADERS; i++) {
int len = snprintf(buf, sizeof(buf), "Header%d: ", i);
memset(&buf[len], 'A', SIZE_HEADERS);
- buf[len + SIZE_HEADERS]=0; /* zero terminate */
+ buf[len + SIZE_HEADERS] = 0; /* zero terminate */
hl = curl_slist_append(headerlist, buf);
if(!hl)
goto test_cleanup;
diff --git a/tests/libtest/lib554.c b/tests/libtest/lib554.c
index 083746243..936d0a10a 100644
--- a/tests/libtest/lib554.c
+++ b/tests/libtest/lib554.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -67,11 +67,11 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
static int once(char *URL, bool oldstyle)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
CURLFORMcode formrc;
- struct curl_httppost *formpost=NULL;
- struct curl_httppost *lastptr=NULL;
+ struct curl_httppost *formpost = NULL;
+ struct curl_httppost *lastptr = NULL;
struct WriteThis pooh;
struct WriteThis pooh2;
diff --git a/tests/libtest/lib555.c b/tests/libtest/lib555.c
index 8156a95e7..fc71bb643 100644
--- a/tests/libtest/lib555.c
+++ b/tests/libtest/lib555.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -77,9 +77,9 @@ int test(char *URL)
{
int res = 0;
CURL *curl = NULL;
- int counter=0;
+ int counter = 0;
CURLM *m = NULL;
- int running=1;
+ int running = 1;
start_test_timing();
@@ -141,7 +141,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 4a598f22d..9a87fbda9 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
#include "memdebug.h"
-#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
# define MPRNT_SUFFIX_CURL_OFF_T LL
#else
# define MPRNT_SUFFIX_CURL_OFF_T L
@@ -129,7 +129,7 @@ static int test_unsigned_short_formatting(void)
#if (SIZEOF_SHORT == 1)
- i=1; us_test[i].num = 0xFFU; us_test[i].expected = "256";
+ i = 1; us_test[i].num = 0xFFU; us_test[i].expected = "256";
i++; us_test[i].num = 0xF0U; us_test[i].expected = "240";
i++; us_test[i].num = 0x0FU; us_test[i].expected = "15";
@@ -146,7 +146,7 @@ static int test_unsigned_short_formatting(void)
#elif (SIZEOF_SHORT == 2)
- i=1; us_test[i].num = 0xFFFFU; us_test[i].expected = "65535";
+ i = 1; us_test[i].num = 0xFFFFU; us_test[i].expected = "65535";
i++; us_test[i].num = 0xFF00U; us_test[i].expected = "65280";
i++; us_test[i].num = 0x00FFU; us_test[i].expected = "255";
@@ -167,7 +167,7 @@ static int test_unsigned_short_formatting(void)
#elif (SIZEOF_SHORT == 4)
- i=1; us_test[i].num = 0xFFFFFFFFU; us_test[i].expected = "4294967295";
+ i = 1; us_test[i].num = 0xFFFFFFFFU; us_test[i].expected = "4294967295";
i++; us_test[i].num = 0xFFFF0000U; us_test[i].expected = "4294901760";
i++; us_test[i].num = 0x0000FFFFU; us_test[i].expected = "65535";
@@ -201,9 +201,9 @@ static int test_unsigned_short_formatting(void)
#endif
- for(i=1; i<=num_ushort_tests; i++) {
+ for(i = 1; i <= num_ushort_tests; i++) {
- for(j=0; j<BUFSZ; j++)
+ for(j = 0; j<BUFSZ; j++)
us_test[i].result[j] = 'X';
us_test[i].result[BUFSZ-1] = '\0';
@@ -236,7 +236,7 @@ static int test_signed_short_formatting(void)
#if (SIZEOF_SHORT == 1)
- i=1; ss_test[i].num = 0x7F; ss_test[i].expected = "127";
+ i = 1; ss_test[i].num = 0x7F; ss_test[i].expected = "127";
i++; ss_test[i].num = 0x70; ss_test[i].expected = "112";
i++; ss_test[i].num = 0x07; ss_test[i].expected = "7";
@@ -261,7 +261,7 @@ static int test_signed_short_formatting(void)
#elif (SIZEOF_SHORT == 2)
- i=1; ss_test[i].num = 0x7FFF; ss_test[i].expected = "32767";
+ i = 1; ss_test[i].num = 0x7FFF; ss_test[i].expected = "32767";
i++; ss_test[i].num = 0x7FFE; ss_test[i].expected = "32766";
i++; ss_test[i].num = 0x7FFD; ss_test[i].expected = "32765";
i++; ss_test[i].num = 0x7F00; ss_test[i].expected = "32512";
@@ -304,7 +304,7 @@ static int test_signed_short_formatting(void)
#elif (SIZEOF_SHORT == 4)
- i=1; ss_test[i].num = 0x7FFFFFFF; ss_test[i].expected = "2147483647";
+ i = 1; ss_test[i].num = 0x7FFFFFFF; ss_test[i].expected = "2147483647";
i++; ss_test[i].num = 0x7FFFFFFE; ss_test[i].expected = "2147483646";
i++; ss_test[i].num = 0x7FFFFFFD; ss_test[i].expected = "2147483645";
i++; ss_test[i].num = 0x7FFF0000; ss_test[i].expected = "2147418112";
@@ -371,9 +371,9 @@ static int test_signed_short_formatting(void)
#endif
- for(i=1; i<=num_sshort_tests; i++) {
+ for(i = 1; i <= num_sshort_tests; i++) {
- for(j=0; j<BUFSZ; j++)
+ for(j = 0; j<BUFSZ; j++)
ss_test[i].result[j] = 'X';
ss_test[i].result[BUFSZ-1] = '\0';
@@ -406,7 +406,7 @@ static int test_unsigned_int_formatting(void)
#if (SIZEOF_INT == 2)
- i=1; ui_test[i].num = 0xFFFFU; ui_test[i].expected = "65535";
+ i = 1; ui_test[i].num = 0xFFFFU; ui_test[i].expected = "65535";
i++; ui_test[i].num = 0xFF00U; ui_test[i].expected = "65280";
i++; ui_test[i].num = 0x00FFU; ui_test[i].expected = "255";
@@ -427,7 +427,7 @@ static int test_unsigned_int_formatting(void)
#elif (SIZEOF_INT == 4)
- i=1; ui_test[i].num = 0xFFFFFFFFU; ui_test[i].expected = "4294967295";
+ i = 1; ui_test[i].num = 0xFFFFFFFFU; ui_test[i].expected = "4294967295";
i++; ui_test[i].num = 0xFFFF0000U; ui_test[i].expected = "4294901760";
i++; ui_test[i].num = 0x0000FFFFU; ui_test[i].expected = "65535";
@@ -462,7 +462,7 @@ static int test_unsigned_int_formatting(void)
#elif (SIZEOF_INT == 8)
/* !checksrc! disable LONGLINE all */
- i=1; ui_test[i].num = 0xFFFFFFFFFFFFFFFFU; ui_test[i].expected = "18446744073709551615";
+ i = 1; ui_test[i].num = 0xFFFFFFFFFFFFFFFFU; ui_test[i].expected = "18446744073709551615";
i++; ui_test[i].num = 0xFFFFFFFF00000000U; ui_test[i].expected = "18446744069414584320";
i++; ui_test[i].num = 0x00000000FFFFFFFFU; ui_test[i].expected = "4294967295";
@@ -521,9 +521,9 @@ static int test_unsigned_int_formatting(void)
#endif
- for(i=1; i<=num_uint_tests; i++) {
+ for(i = 1; i <= num_uint_tests; i++) {
- for(j=0; j<BUFSZ; j++)
+ for(j = 0; j<BUFSZ; j++)
ui_test[i].result[j] = 'X';
ui_test[i].result[BUFSZ-1] = '\0';
@@ -556,7 +556,7 @@ static int test_signed_int_formatting(void)
#if (SIZEOF_INT == 2)
- i=1; si_test[i].num = 0x7FFF; si_test[i].expected = "32767";
+ i = 1; si_test[i].num = 0x7FFF; si_test[i].expected = "32767";
i++; si_test[i].num = 0x7FFE; si_test[i].expected = "32766";
i++; si_test[i].num = 0x7FFD; si_test[i].expected = "32765";
i++; si_test[i].num = 0x7F00; si_test[i].expected = "32512";
@@ -599,7 +599,7 @@ static int test_signed_int_formatting(void)
#elif (SIZEOF_INT == 4)
- i=1; si_test[i].num = 0x7FFFFFFF; si_test[i].expected = "2147483647";
+ i = 1; si_test[i].num = 0x7FFFFFFF; si_test[i].expected = "2147483647";
i++; si_test[i].num = 0x7FFFFFFE; si_test[i].expected = "2147483646";
i++; si_test[i].num = 0x7FFFFFFD; si_test[i].expected = "2147483645";
i++; si_test[i].num = 0x7FFF0000; si_test[i].expected = "2147418112";
@@ -666,7 +666,7 @@ static int test_signed_int_formatting(void)
#elif (SIZEOF_INT == 8)
- i=1; si_test[i].num = 0x7FFFFFFFFFFFFFFF; si_test[i].expected = "9223372036854775807";
+ i = 1; si_test[i].num = 0x7FFFFFFFFFFFFFFF; si_test[i].expected = "9223372036854775807";
i++; si_test[i].num = 0x7FFFFFFFFFFFFFFE; si_test[i].expected = "9223372036854775806";
i++; si_test[i].num = 0x7FFFFFFFFFFFFFFD; si_test[i].expected = "9223372036854775805";
i++; si_test[i].num = 0x7FFFFFFF00000000; si_test[i].expected = "9223372032559808512";
@@ -749,9 +749,9 @@ static int test_signed_int_formatting(void)
#endif
- for(i=1; i<=num_sint_tests; i++) {
+ for(i = 1; i <= num_sint_tests; i++) {
- for(j=0; j<BUFSZ; j++)
+ for(j = 0; j<BUFSZ; j++)
si_test[i].result[j] = 'X';
si_test[i].result[BUFSZ-1] = '\0';
@@ -782,9 +782,9 @@ static int test_unsigned_long_formatting(void)
int num_ulong_tests;
int failed = 0;
-#if (CURL_SIZEOF_LONG == 2)
+#if (SIZEOF_LONG == 2)
- i=1; ul_test[i].num = 0xFFFFUL; ul_test[i].expected = "65535";
+ i = 1; ul_test[i].num = 0xFFFFUL; ul_test[i].expected = "65535";
i++; ul_test[i].num = 0xFF00UL; ul_test[i].expected = "65280";
i++; ul_test[i].num = 0x00FFUL; ul_test[i].expected = "255";
@@ -803,9 +803,9 @@ static int test_unsigned_long_formatting(void)
num_ulong_tests = i;
-#elif (CURL_SIZEOF_LONG == 4)
+#elif (SIZEOF_LONG == 4)
- i=1; ul_test[i].num = 0xFFFFFFFFUL; ul_test[i].expected = "4294967295";
+ i = 1; ul_test[i].num = 0xFFFFFFFFUL; ul_test[i].expected = "4294967295";
i++; ul_test[i].num = 0xFFFF0000UL; ul_test[i].expected = "4294901760";
i++; ul_test[i].num = 0x0000FFFFUL; ul_test[i].expected = "65535";
@@ -837,9 +837,9 @@ static int test_unsigned_long_formatting(void)
num_ulong_tests = i;
-#elif (CURL_SIZEOF_LONG == 8)
+#elif (SIZEOF_LONG == 8)
- i=1; ul_test[i].num = 0xFFFFFFFFFFFFFFFFUL; ul_test[i].expected = "18446744073709551615";
+ i = 1; ul_test[i].num = 0xFFFFFFFFFFFFFFFFUL; ul_test[i].expected = "18446744073709551615";
i++; ul_test[i].num = 0xFFFFFFFF00000000UL; ul_test[i].expected = "18446744069414584320";
i++; ul_test[i].num = 0x00000000FFFFFFFFUL; ul_test[i].expected = "4294967295";
@@ -898,9 +898,9 @@ static int test_unsigned_long_formatting(void)
#endif
- for(i=1; i<=num_ulong_tests; i++) {
+ for(i = 1; i <= num_ulong_tests; i++) {
- for(j=0; j<BUFSZ; j++)
+ for(j = 0; j<BUFSZ; j++)
ul_test[i].result[j] = 'X';
ul_test[i].result[BUFSZ-1] = '\0';
@@ -931,9 +931,9 @@ static int test_signed_long_formatting(void)
int num_slong_tests;
int failed = 0;
-#if (CURL_SIZEOF_LONG == 2)
+#if (SIZEOF_LONG == 2)
- i=1; sl_test[i].num = 0x7FFFL; sl_test[i].expected = "32767";
+ i = 1; sl_test[i].num = 0x7FFFL; sl_test[i].expected = "32767";
i++; sl_test[i].num = 0x7FFEL; sl_test[i].expected = "32766";
i++; sl_test[i].num = 0x7FFDL; sl_test[i].expected = "32765";
i++; sl_test[i].num = 0x7F00L; sl_test[i].expected = "32512";
@@ -974,9 +974,9 @@ static int test_signed_long_formatting(void)
num_slong_tests = i;
-#elif (CURL_SIZEOF_LONG == 4)
+#elif (SIZEOF_LONG == 4)
- i=1; sl_test[i].num = 0x7FFFFFFFL; sl_test[i].expected = "2147483647";
+ i = 1; sl_test[i].num = 0x7FFFFFFFL; sl_test[i].expected = "2147483647";
i++; sl_test[i].num = 0x7FFFFFFEL; sl_test[i].expected = "2147483646";
i++; sl_test[i].num = 0x7FFFFFFDL; sl_test[i].expected = "2147483645";
i++; sl_test[i].num = 0x7FFF0000L; sl_test[i].expected = "2147418112";
@@ -1041,9 +1041,9 @@ static int test_signed_long_formatting(void)
num_slong_tests = i;
-#elif (CURL_SIZEOF_LONG == 8)
+#elif (SIZEOF_LONG == 8)
- i=1; sl_test[i].num = 0x7FFFFFFFFFFFFFFFL; sl_test[i].expected = "9223372036854775807";
+ i = 1; sl_test[i].num = 0x7FFFFFFFFFFFFFFFL; sl_test[i].expected = "9223372036854775807";
i++; sl_test[i].num = 0x7FFFFFFFFFFFFFFEL; sl_test[i].expected = "9223372036854775806";
i++; sl_test[i].num = 0x7FFFFFFFFFFFFFFDL; sl_test[i].expected = "9223372036854775805";
i++; sl_test[i].num = 0x7FFFFFFF00000000L; sl_test[i].expected = "9223372032559808512";
@@ -1126,9 +1126,9 @@ static int test_signed_long_formatting(void)
#endif
- for(i=1; i<=num_slong_tests; i++) {
+ for(i = 1; i <= num_slong_tests; i++) {
- for(j=0; j<BUFSZ; j++)
+ for(j = 0; j<BUFSZ; j++)
sl_test[i].result[j] = 'X';
sl_test[i].result[BUFSZ-1] = '\0';
@@ -1159,9 +1159,9 @@ static int test_curl_off_t_formatting(void)
int num_cofft_tests;
int failed = 0;
-#if (CURL_SIZEOF_CURL_OFF_T == 2)
+#if (SIZEOF_CURL_OFF_T == 2)
- i=1; co_test[i].num = MPRNT_OFF_T_C(0x7FFF); co_test[i].expected = "32767";
+ i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFF); co_test[i].expected = "32767";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFE); co_test[i].expected = "32766";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFD); co_test[i].expected = "32765";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7F00); co_test[i].expected = "32512";
@@ -1202,9 +1202,9 @@ static int test_curl_off_t_formatting(void)
num_cofft_tests = i;
-#elif (CURL_SIZEOF_CURL_OFF_T == 4)
+#elif (SIZEOF_CURL_OFF_T == 4)
- i=1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFF); co_test[i].expected = "2147483647";
+ i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFF); co_test[i].expected = "2147483647";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFE); co_test[i].expected = "2147483646";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFD); co_test[i].expected = "2147483645";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFF0000); co_test[i].expected = "2147418112";
@@ -1269,9 +1269,9 @@ static int test_curl_off_t_formatting(void)
num_cofft_tests = i;
-#elif (CURL_SIZEOF_CURL_OFF_T == 8)
+#elif (SIZEOF_CURL_OFF_T == 8)
- i=1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFF); co_test[i].expected = "9223372036854775807";
+ i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFF); co_test[i].expected = "9223372036854775807";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFE); co_test[i].expected = "9223372036854775806";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFD); co_test[i].expected = "9223372036854775805";
i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFF00000000); co_test[i].expected = "9223372032559808512";
@@ -1354,9 +1354,9 @@ static int test_curl_off_t_formatting(void)
#endif
- for(i=1; i<=num_cofft_tests; i++) {
+ for(i = 1; i <= num_cofft_tests; i++) {
- for(j=0; j<BUFSZ; j++)
+ for(j = 0; j<BUFSZ; j++)
co_test[i].result[j] = 'X';
co_test[i].result[BUFSZ-1] = '\0';
@@ -1546,6 +1546,7 @@ static int test_weird_arguments(void)
}
/* DBL_MAX value from Linux */
+/* !checksrc! disable PLUSNOSPACE 1 */
#define MAXIMIZE -1.7976931348623157081452E+308
static int test_float_formatting(void)
diff --git a/tests/libtest/lib560.c b/tests/libtest/lib560.c
index 8fa0c2de2..0093ea113 100644
--- a/tests/libtest/lib560.c
+++ b/tests/libtest/lib560.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -91,7 +91,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
diff --git a/tests/libtest/lib564.c b/tests/libtest/lib564.c
index 1822931bc..f959f2043 100644
--- a/tests/libtest/lib564.c
+++ b/tests/libtest/lib564.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -76,7 +76,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &rd, &wr, &exc, &interval);
+ select_test(maxfd + 1, &rd, &wr, &exc, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib567.c b/tests/libtest/lib567.c
index f9f55e3c0..64fb29afb 100644
--- a/tests/libtest/lib567.c
+++ b/tests/libtest/lib567.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@ int test(char *URL)
{
CURLcode res;
CURL *curl;
- struct curl_slist *custom_headers=NULL;
+ struct curl_slist *custom_headers = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib568.c b/tests/libtest/lib568.c
index 0cdef812b..3bb53f61e 100644
--- a/tests/libtest/lib568.c
+++ b/tests/libtest/lib568.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,8 +47,8 @@ int test(char *URL)
FILE *sdpf = NULL;
struct_stat file_info;
char *stream_uri = NULL;
- int request=1;
- struct curl_slist *custom_headers=NULL;
+ int request = 1;
+ struct curl_slist *custom_headers = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib569.c b/tests/libtest/lib569.c
index d7381d9a2..c18c882b9 100644
--- a/tests/libtest/lib569.c
+++ b/tests/libtest/lib569.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@ int test(char *URL)
CURL *curl;
char *stream_uri = NULL;
char *rtsp_session_id;
- int request=1;
+ int request = 1;
int i;
FILE *idfile = NULL;
diff --git a/tests/libtest/lib570.c b/tests/libtest/lib570.c
index 9d9b5a134..1756a8615 100644
--- a/tests/libtest/lib570.c
+++ b/tests/libtest/lib570.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -32,7 +32,7 @@ int test(char *URL)
{
int res;
CURL *curl;
- int request=1;
+ int request = 1;
char *stream_uri = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib571.c b/tests/libtest/lib571.c
index f19b643ff..70524f2f2 100644
--- a/tests/libtest/lib571.c
+++ b/tests/libtest/lib571.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -70,7 +70,7 @@ static size_t rtp_write(void *ptr, size_t size, size_t nmemb, void *stream)
}
data += 4;
- for(i = 0; i < message_size; i+= RTP_DATA_SIZE) {
+ for(i = 0; i < message_size; i += RTP_DATA_SIZE) {
if(message_size - i > RTP_DATA_SIZE) {
if(memcmp(RTP_DATA, data + i, RTP_DATA_SIZE) != 0) {
printf("RTP PAYLOAD CORRUPTED [%s]\n", data + i);
@@ -103,7 +103,7 @@ int test(char *URL)
int res;
CURL *curl;
char *stream_uri = NULL;
- int request=1;
+ int request = 1;
FILE *protofile = NULL;
protofile = fopen(libtest_arg2, "wb");
diff --git a/tests/libtest/lib572.c b/tests/libtest/lib572.c
index 47a9da535..a78c9358d 100644
--- a/tests/libtest/lib572.c
+++ b/tests/libtest/lib572.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,8 +47,8 @@ int test(char *URL)
FILE *paramsf = NULL;
struct_stat file_info;
char *stream_uri = NULL;
- int request=1;
- struct curl_slist *custom_headers=NULL;
+ int request = 1;
+ struct curl_slist *custom_headers = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib573.c b/tests/libtest/lib573.c
index dce198b50..eb817b1ed 100644
--- a/tests/libtest/lib573.c
+++ b/tests/libtest/lib573.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -88,7 +88,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib575.c b/tests/libtest/lib575.c
index 186170cfc..6baa12229 100644
--- a/tests/libtest/lib575.c
+++ b/tests/libtest/lib575.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -93,7 +93,7 @@ int test(char *URL)
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
abort_on_test_timeout();
diff --git a/tests/libtest/lib578.c b/tests/libtest/lib578.c
index 41b23db34..1b4ee526c 100644
--- a/tests/libtest/lib578.c
+++ b/tests/libtest/lib578.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,7 +51,7 @@ static int progress_callback(void *clientp, double dltotal, double dlnow,
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib579.c b/tests/libtest/lib579.c
index 61aa4f5df..cba4b1cb4 100644
--- a/tests/libtest/lib579.c
+++ b/tests/libtest/lib579.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -87,7 +87,7 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
struct curl_slist *slist = NULL;
struct WriteThis pooh;
pooh.counter = 0;
diff --git a/tests/libtest/lib586.c b/tests/libtest/lib586.c
index 859ef3430..669f71c15 100644
--- a/tests/libtest/lib586.c
+++ b/tests/libtest/lib586.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -99,7 +99,7 @@ static void *fire(void *ptr)
CURLcode code;
struct Tdata *tdata = (struct Tdata*)ptr;
CURL *curl;
- int i=0;
+ int i = 0;
curl = curl_easy_init();
if(!curl) {
@@ -185,7 +185,7 @@ int test(char *URL)
res = 0;
/* start treads */
- for(i=1; i<=THREADS; i++) {
+ for(i = 1; i <= THREADS; i++) {
/* set thread data */
tdata.url = URL;
@@ -218,7 +218,7 @@ int test(char *URL)
/* try to free share, expect to fail because share is in use*/
printf("try SHARE_CLEANUP...\n");
scode = curl_share_cleanup(share);
- if(scode==CURLSHE_OK) {
+ if(scode == CURLSHE_OK) {
fprintf(stderr, "curl_share_cleanup succeed but error expected\n");
share = NULL;
}
@@ -235,7 +235,7 @@ test_cleanup:
/* free share */
printf("SHARE_CLEANUP\n");
scode = curl_share_cleanup(share);
- if(scode!=CURLSHE_OK)
+ if(scode != CURLSHE_OK)
fprintf(stderr, "curl_share_cleanup failed, code errno %d\n",
(int)scode);
diff --git a/tests/libtest/lib589.c b/tests/libtest/lib589.c
new file mode 100644
index 000000000..667459d0d
--- /dev/null
+++ b/tests/libtest/lib589.c
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under 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 "test.h"
+
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ /* First set the URL that is about to receive our POST. */
+ test_setopt(curl, CURLOPT_URL, URL);
+ test_setopt(curl, CURLOPT_MIMEPOST, NULL);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L); /* show verbose for debug */
+ test_setopt(curl, CURLOPT_HEADER, 1L); /* include header */
+
+ /* Now, we should be making a zero byte POST request */
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ return (int)res;
+}
diff --git a/tests/libtest/lib591.c b/tests/libtest/lib591.c
index 53ede3fcd..f25cc4d73 100644
--- a/tests/libtest/lib591.c
+++ b/tests/libtest/lib591.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2012, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -123,7 +123,7 @@ int test(char *URL)
interval.tv_usec = 100000L; /* 100 ms */
}
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib597.c b/tests/libtest/lib597.c
index 813af7541..c8529743e 100644
--- a/tests/libtest/lib597.c
+++ b/tests/libtest/lib597.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -60,10 +60,7 @@ int test(char *URL)
start_test_timing();
- res_global_init(CURL_GLOBAL_ALL);
- if(res) {
- return res;
- }
+ global_init(CURL_GLOBAL_ALL);
easy_init(easy);
@@ -123,11 +120,11 @@ int test(char *URL)
interval.tv_usec = (itimeout%1000)*1000;
}
else {
- interval.tv_sec = TEST_HANG_TIMEOUT/1000+1;
+ interval.tv_sec = TEST_HANG_TIMEOUT/1000 + 1;
interval.tv_usec = 0;
}
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/lib599.c b/tests/libtest/lib599.c
index 843fb2121..0e05977b5 100644
--- a/tests/libtest/lib599.c
+++ b/tests/libtest/lib599.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,7 +42,7 @@ static int progress_callback(void *clientp, double dltotal,
int test(char *URL)
{
CURL *curl;
- CURLcode res=CURLE_OK;
+ CURLcode res = CURLE_OK;
double content_length = 0.0;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib643.c b/tests/libtest/lib643.c
new file mode 100644
index 000000000..e26a2515f
--- /dev/null
+++ b/tests/libtest/lib643.c
@@ -0,0 +1,270 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under 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 "test.h"
+
+#include "memdebug.h"
+
+static char data[]=
+#ifdef CURL_DOES_CONVERSIONS
+ /* ASCII representation with escape sequences for non-ASCII platforms */
+ "\x74\x68\x69\x73\x20\x69\x73\x20\x77\x68\x61\x74\x20\x77\x65\x20\x70"
+ "\x6f\x73\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x73\x69\x6c\x6c\x79\x20"
+ "\x77\x65\x62\x20\x73\x65\x72\x76\x65\x72\x0a";
+#else
+ "this is what we post to the silly web server\n";
+#endif
+
+struct WriteThis {
+ char *readptr;
+ curl_off_t sizeleft;
+};
+
+static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
+{
+#ifdef LIB644
+ (void)ptr;
+ (void)size;
+ (void)nmemb;
+ (void)userp;
+ return CURL_READFUNC_ABORT;
+#else
+
+ struct WriteThis *pooh = (struct WriteThis *)userp;
+ int eof = !*pooh->readptr;
+
+ if(size*nmemb < 1)
+ return 0;
+
+#ifndef LIB645
+ eof = pooh->sizeleft <= 0;
+ if(!eof)
+ pooh->sizeleft--;
+#endif
+
+ if(!eof) {
+ *ptr = *pooh->readptr; /* copy one single byte */
+ pooh->readptr++; /* advance pointer */
+ return 1; /* we return 1 byte at a time! */
+ }
+
+ return 0; /* no more data left to deliver */
+#endif
+}
+
+static int once(char *URL, bool oldstyle)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ curl_mime *mime = NULL;
+ curl_mimepart *part = NULL;
+ struct WriteThis pooh;
+ struct WriteThis pooh2;
+ curl_off_t datasize = -1;
+
+ pooh.readptr = data;
+#ifndef LIB645
+ datasize = (curl_off_t)strlen(data);
+#endif
+ pooh.sizeleft = datasize;
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ mime = curl_mime_init(curl);
+ if(!mime) {
+ fprintf(stderr, "curl_mime_init() failed\n");
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ part = curl_mime_addpart(mime);
+ if(!part) {
+ fprintf(stderr, "curl_mime_addpart(1) failed\n");
+ curl_mime_free(mime);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ /* Fill in the file upload part */
+ if(oldstyle) {
+ res = curl_mime_name(part, "sendfile");
+ if(!res)
+ res = curl_mime_data_cb(part, datasize, read_callback,
+ NULL, NULL, &pooh);
+ if(!res)
+ res = curl_mime_filename(part, "postit2.c");
+ }
+ else {
+ /* new style */
+ res = curl_mime_name(part, "sendfile alternative");
+ if(!res)
+ res = curl_mime_data_cb(part, datasize, read_callback,
+ NULL, NULL, &pooh);
+ if(!res)
+ res = curl_mime_filename(part, "file name 2");
+ }
+
+ if(res)
+ printf("curl_mime_xxx(1) = %s\n", curl_easy_strerror(res));
+
+ /* Now add the same data with another name and make it not look like
+ a file upload but still using the callback */
+
+ pooh2.readptr = data;
+#ifndef LIB645
+ datasize = (curl_off_t)strlen(data);
+#endif
+ pooh2.sizeleft = datasize;
+
+ part = curl_mime_addpart(mime);
+ if(!part) {
+ fprintf(stderr, "curl_mime_addpart(2) failed\n");
+ curl_mime_free(mime);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+ /* Fill in the file upload part */
+ res = curl_mime_name(part, "callbackdata");
+ if(!res)
+ res = curl_mime_data_cb(part, datasize, read_callback,
+ NULL, NULL, &pooh2);
+
+ if(res)
+ printf("curl_mime_xxx(2) = %s\n", curl_easy_strerror(res));
+
+ part = curl_mime_addpart(mime);
+ if(!part) {
+ fprintf(stderr, "curl_mime_addpart(3) failed\n");
+ curl_mime_free(mime);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ /* Fill in the filename field */
+ res = curl_mime_name(part, "filename");
+ if(!res)
+ res = curl_mime_data(part,
+#ifdef CURL_DOES_CONVERSIONS
+ /* ASCII representation with escape
+ sequences for non-ASCII platforms */
+ "\x70\x6f\x73\x74\x69\x74\x32\x2e\x63",
+#else
+ "postit2.c",
+#endif
+ CURL_ZERO_TERMINATED);
+
+ if(res)
+ printf("curl_mime_xxx(3) = %s\n", curl_easy_strerror(res));
+
+ /* Fill in a submit field too */
+ part = curl_mime_addpart(mime);
+ if(!part) {
+ fprintf(stderr, "curl_mime_addpart(4) failed\n");
+ curl_mime_free(mime);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+ res = curl_mime_name(part, "submit");
+ if(!res)
+ res = curl_mime_data(part,
+#ifdef CURL_DOES_CONVERSIONS
+ /* ASCII representation with escape
+ sequences for non-ASCII platforms */
+ "\x73\x65\x6e\x64",
+#else
+ "send",
+#endif
+ CURL_ZERO_TERMINATED);
+
+ if(res)
+ printf("curl_mime_xxx(4) = %s\n", curl_easy_strerror(res));
+
+ part = curl_mime_addpart(mime);
+ if(!part) {
+ fprintf(stderr, "curl_mime_addpart(5) failed\n");
+ curl_mime_free(mime);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+ res = curl_mime_name(part, "somename");
+ if(!res)
+ res = curl_mime_filename(part, "somefile.txt");
+ if(!res)
+ res = curl_mime_data(part, "blah blah", 9);
+
+ if(res)
+ printf("curl_mime_xxx(5) = %s\n", curl_easy_strerror(res));
+
+ /* First set the URL that is about to receive our POST. */
+ test_setopt(curl, CURLOPT_URL, URL);
+
+ /* send a multi-part mimepost */
+ test_setopt(curl, CURLOPT_MIMEPOST, mime);
+
+ /* get verbose debug output please */
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ /* include headers in the output */
+ test_setopt(curl, CURLOPT_HEADER, 1L);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+
+ /* now cleanup the mimepost structure */
+ curl_mime_free(mime);
+
+ return res;
+}
+
+int test(char *URL)
+{
+ int res;
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ res = once(URL, TRUE); /* old */
+ if(!res)
+ res = once(URL, FALSE); /* new */
+
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib650.c b/tests/libtest/lib650.c
new file mode 100644
index 000000000..130ef1e77
--- /dev/null
+++ b/tests/libtest/lib650.c
@@ -0,0 +1,189 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under 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 "test.h"
+
+#include "memdebug.h"
+
+static char data[] =
+#ifdef CURL_DOES_CONVERSIONS
+ /* ASCII representation with escape sequences for non-ASCII platforms */
+ "\x74\x68\x69\x73\x20\x69\x73\x20\x77\x68\x61\x74\x20\x77\x65\x20\x70"
+ "\x6f\x73\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x73\x69\x6c\x6c\x79\x20"
+ "\x77\x65\x62\x20\x73\x65\x72\x76\x65\x72";
+#else
+ "this is what we post to the silly web server";
+#endif
+
+static char name[] = "fieldname";
+
+
+/* This test attempts to use all form API features that are not
+ * used elsewhere.
+ */
+
+/* curl_formget callback to count characters. */
+static size_t count_chars(void *userp, const char *buf, size_t len)
+{
+ size_t *pcounter = (size_t *) userp;
+
+ (void) buf;
+ *pcounter += len;
+ return len;
+}
+
+
+int test(char *URL)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+ CURLFORMcode formrc;
+ struct curl_slist *headers = NULL;
+ struct curl_httppost *formpost = NULL;
+ struct curl_httppost *lastptr = NULL;
+ struct curl_forms formarray[3];
+ size_t formlength = 0;
+ char flbuf[32];
+
+ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ /* Check proper name and data copying. */
+ formrc = curl_formadd(&formpost, &lastptr,
+ CURLFORM_COPYNAME, &name,
+ CURLFORM_COPYCONTENTS, &data,
+ CURLFORM_END);
+
+ if(formrc)
+ printf("curl_formadd(1) = %d\n", (int) formrc);
+
+ /* Use a form array for the non-copy test. */
+ formarray[0].option = CURLFORM_PTRCONTENTS;
+ formarray[0].value = data;
+ formarray[1].option = CURLFORM_CONTENTSLENGTH;
+ formarray[1].value = (char *) strlen(data) - 1;
+ formarray[2].option = CURLFORM_END;
+ formarray[2].value = NULL;
+ formrc = curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_PTRNAME, name,
+ CURLFORM_NAMELENGTH, strlen(name) - 1,
+ CURLFORM_ARRAY, formarray,
+ CURLFORM_FILENAME, "remotefile.txt",
+ CURLFORM_END);
+
+ if(formrc)
+ printf("curl_formadd(2) = %d\n", (int) formrc);
+
+ /* Now change in-memory data to affect CURLOPT_PTRCONTENTS value.
+ Copied values (first field) must not be affected.
+ CURLOPT_PTRNAME actually copies the name thus we do not test this here. */
+ data[0]++;
+
+ /* Check multi-files and content type propagation. */
+ formrc = curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "multifile",
+ CURLFORM_FILE, libtest_arg2, /* Set in first.c. */
+ CURLFORM_FILE, libtest_arg2,
+ CURLFORM_CONTENTTYPE, "text/whatever",
+ CURLFORM_FILE, libtest_arg2,
+ CURLFORM_END);
+
+ if(formrc)
+ printf("curl_formadd(3) = %d\n", (int) formrc);
+
+ /* Check data from file content and headers. */
+ headers = curl_slist_append(headers, "X-customheader-1: Header 1 data");
+ headers = curl_slist_append(headers, "X-customheader-2: Header 2 data");
+ formrc = curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "filecontents",
+ CURLFORM_FILECONTENT, libtest_arg2,
+ CURLFORM_CONTENTHEADER, headers,
+ CURLFORM_END);
+
+ if(formrc)
+ printf("curl_formadd(3) = %d\n", (int) formrc);
+
+ /* Measure the current form length.
+ * This is done before including stdin data because we want to reuse it
+ * and stdin cannot be rewound.
+ */
+ curl_formget(formpost, (void *) &formlength, count_chars);
+
+ /* Include length in data for external check. */
+ curl_msnprintf(flbuf, sizeof flbuf, "%lu", (unsigned long) formlength);
+ formrc = curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "formlength",
+ CURLFORM_COPYCONTENTS, &flbuf,
+ CURLFORM_END);
+
+ /* Check stdin (may be problematic on some platforms). */
+ formrc = curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "standardinput",
+ CURLFORM_FILE, "-",
+ CURLFORM_END);
+
+ if(formrc)
+ printf("curl_formadd(4) = %d\n", (int) formrc);
+
+ curl = curl_easy_init();
+ if(!curl) {
+ fprintf(stderr, "curl_easy_init() failed\n");
+ curl_slist_free_all(headers);
+ curl_formfree(formpost);
+ curl_global_cleanup();
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ /* First set the URL that is about to receive our POST. */
+ test_setopt(curl, CURLOPT_URL, URL);
+
+ /* send a multi-part formpost */
+ test_setopt(curl, CURLOPT_HTTPPOST, formpost);
+
+ /* get verbose debug output please */
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ /* include headers in the output */
+ test_setopt(curl, CURLOPT_HEADER, 1L);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+
+test_cleanup:
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+
+ /* now cleanup the formpost chain */
+ curl_formfree(formpost);
+ curl_slist_free_all(headers);
+
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/libntlmconnect.c b/tests/libtest/libntlmconnect.c
index ad20e8b8f..0d527a779 100644
--- a/tests/libtest/libntlmconnect.c
+++ b/tests/libtest/libntlmconnect.c
@@ -196,7 +196,7 @@ int test(char *url)
interval.tv_usec = (itimeout%1000)*1000;
}
else {
- interval.tv_sec = TEST_HANG_TIMEOUT/1000+1;
+ interval.tv_sec = TEST_HANG_TIMEOUT/1000 + 1;
interval.tv_usec = 0;
/* if there's no timeout and we get here on the last handle, we may
@@ -207,7 +207,7 @@ int test(char *url)
}
}
- select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
+ select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
abort_on_test_timeout();
}
diff --git a/tests/libtest/mk-lib1521.pl b/tests/libtest/mk-lib1521.pl
index a75fad928..0b1d10d46 100644
--- a/tests/libtest/mk-lib1521.pl
+++ b/tests/libtest/mk-lib1521.pl
@@ -143,9 +143,10 @@ int test(char *URL)
void *conv_to_network_cb = NULL;
void *conv_from_utf8_cb = NULL;
void *interleavecb = NULL;
- char *stringpointerextra=(char *)"moooo";
- struct curl_slist *slist=NULL;
- struct curl_httppost *httppost=NULL;
+ char *stringpointerextra = (char *)"moooo";
+ struct curl_slist *slist = NULL;
+ struct curl_httppost *httppost = NULL;
+ curl_mime *mimepost = NULL;
FILE *stream = stderr;
struct data object;
char *charp;
@@ -157,6 +158,7 @@ int test(char *URL)
struct curl_tlssessioninfo *tlssession;
CURLcode res = CURLE_OK;
(void)URL; /* not used */
+ global_init(CURL_GLOBAL_ALL);
easy_init(dep);
easy_init(curl);
share = curl_share_init();
@@ -215,6 +217,9 @@ while(<STDIN>) {
elsif($name eq "HTTPPOST") {
print "${pref} httppost);\n$check";
}
+ elsif($name eq "MIMEPOST") {
+ print "${pref} mimepost);\n$check";
+ }
elsif($name eq "STDERR") {
print "${pref} stream);\n$check";
}
@@ -296,6 +301,7 @@ test_cleanup:
curl_easy_cleanup(curl);
curl_easy_cleanup(dep);
curl_share_cleanup(share);
+ curl_global_cleanup();
return (int)res;
}
diff --git a/tests/libtest/stub_gssapi.c b/tests/libtest/stub_gssapi.c
new file mode 100644
index 000000000..168becf88
--- /dev/null
+++ b/tests/libtest/stub_gssapi.c
@@ -0,0 +1,397 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Only provides the bare minimum to link with libcurl */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "stub_gssapi.h"
+
+#define MAX_CREDS_LENGTH 250
+#define APPROX_TOKEN_LEN 250
+
+enum min_err_code {
+ GSS_OK = 0,
+ GSS_NO_MEMORY,
+ GSS_INVALID_ARGS,
+ GSS_INVALID_CREDS,
+ GSS_INVALID_CTX,
+ GSS_SERVER_ERR,
+ GSS_NO_MECH,
+ GSS_LAST
+};
+
+const char *min_err_table[] = {
+ "stub-gss: no error",
+ "stub-gss: no memory",
+ "stub-gss: invalid arguments",
+ "stub-gss: invalid credentials",
+ "stub-gss: invalid context",
+ "stub-gss: server returned error",
+ "stub-gss: cannot find a mechanism",
+ NULL
+};
+
+struct gss_ctx_id_t_desc_struct {
+ enum { NONE, KRB5, NTLM1, NTLM3 } sent;
+ int have_krb5;
+ int have_ntlm;
+ OM_uint32 flags;
+ char creds[MAX_CREDS_LENGTH];
+};
+
+OM_uint32 gss_init_sec_context(OM_uint32 *min,
+ gss_const_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ gss_const_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ /* The token will be encoded in base64 */
+ int length = APPROX_TOKEN_LEN * 3 / 4;
+ int used = 0;
+ char *token = NULL;
+ const char *creds = NULL;
+ gss_ctx_id_t ctx = NULL;
+
+ if(!min)
+ return GSS_S_FAILURE;
+
+ *min = 0;
+
+ if(!context_handle || !target_name || !output_token) {
+ *min = GSS_INVALID_ARGS;
+ return GSS_S_FAILURE;
+ }
+
+ creds = getenv("CURL_STUB_GSS_CREDS");
+ if(!creds || strlen(creds) >= MAX_CREDS_LENGTH) {
+ *min = GSS_INVALID_CREDS;
+ return GSS_S_FAILURE;
+ }
+
+ ctx = *context_handle;
+ if(ctx && strcmp(ctx->creds, creds)) {
+ *min = GSS_INVALID_CREDS;
+ return GSS_S_FAILURE;
+ }
+
+ output_token->length = 0;
+ output_token->value = NULL;
+
+ if(input_token && input_token->length) {
+ if(!ctx) {
+ *min = GSS_INVALID_CTX;
+ return GSS_S_FAILURE;
+ }
+
+ /* Server response, either D (RA==) or C (Qw==) */
+ if(((char *) input_token->value)[0] == 'D') {
+ /* Done */
+ switch(ctx->sent) {
+ case KRB5:
+ case NTLM3:
+ if(ret_flags)
+ *ret_flags = ctx->flags;
+ if(time_rec)
+ *time_rec = GSS_C_INDEFINITE;
+ return GSS_S_COMPLETE;
+ default:
+ *min = GSS_SERVER_ERR;
+ return GSS_S_FAILURE;
+ }
+ }
+
+ if(((char *) input_token->value)[0] != 'C') {
+ /* We only support Done or Continue */
+ *min = GSS_SERVER_ERR;
+ return GSS_S_FAILURE;
+ }
+
+ /* Continue */
+ switch(ctx->sent) {
+ case KRB5:
+ /* We sent KRB5 and it failed, let's try NTLM */
+ if(ctx->have_ntlm) {
+ ctx->sent = NTLM1;
+ break;
+ }
+ else {
+ *min = GSS_SERVER_ERR;
+ return GSS_S_FAILURE;
+ }
+ case NTLM1:
+ ctx->sent = NTLM3;
+ break;
+ default:
+ *min = GSS_SERVER_ERR;
+ return GSS_S_FAILURE;
+ }
+ }
+ else {
+ if(ctx) {
+ *min = GSS_INVALID_CTX;
+ return GSS_S_FAILURE;
+ }
+
+ ctx = (gss_ctx_id_t) calloc(sizeof(*ctx), 1);
+ if(!ctx) {
+ *min = GSS_NO_MEMORY;
+ return GSS_S_FAILURE;
+ }
+
+ if(strstr(creds, "KRB5"))
+ ctx->have_krb5 = 1;
+
+ if(strstr(creds, "NTLM"))
+ ctx->have_ntlm = 1;
+
+ if(ctx->have_krb5)
+ ctx->sent = KRB5;
+ else if(ctx->have_ntlm)
+ ctx->sent = NTLM1;
+ else {
+ free(ctx);
+ *min = GSS_NO_MECH;
+ return GSS_S_FAILURE;
+ }
+
+ strcpy(ctx->creds, creds);
+ ctx->flags = req_flags;
+ }
+
+ token = malloc(length);
+ if(!token) {
+ free(ctx);
+ *min = GSS_NO_MEMORY;
+ return GSS_S_FAILURE;
+ }
+
+ /* Token format: creds:target:type:padding */
+ used = snprintf(token, length, "%s:%s:%d:", creds,
+ (char *) target_name, ctx->sent);
+
+ if(used >= length) {
+ free(token);
+ free(ctx);
+ *min = GSS_NO_MEMORY;
+ return GSS_S_FAILURE;
+ }
+
+ /* Overwrite null terminator */
+ memset(token + used, 'A', length - used);
+
+ *context_handle = ctx;
+
+ output_token->value = token;
+ output_token->length = length;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
+OM_uint32 gss_delete_sec_context(OM_uint32 *min,
+ gss_ctx_id_t *context_handle,
+ gss_buffer_t output_token)
+{
+ if(!min)
+ return GSS_S_FAILURE;
+
+ if(!context_handle) {
+ *min = GSS_INVALID_CTX;
+ return GSS_S_FAILURE;
+ }
+
+ free(*context_handle);
+ *context_handle = NULL;
+ *min = 0;
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_release_buffer(OM_uint32 *min,
+ gss_buffer_t buffer)
+{
+ if(min)
+ *min = 0;
+
+ if(buffer && buffer->length) {
+ free(buffer->value);
+ buffer->length = 0;
+ }
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_import_name(OM_uint32 *min,
+ const gss_buffer_t input_name_buffer,
+ const gss_OID input_name_type,
+ gss_name_t *output_name)
+{
+ char *name = NULL;
+
+ if(!min)
+ return GSS_S_FAILURE;
+
+ if(!input_name_buffer || !output_name) {
+ *min = GSS_INVALID_ARGS;
+ return GSS_S_FAILURE;
+ }
+
+ name = strndup(input_name_buffer->value, input_name_buffer->length);
+ if(!name) {
+ *min = GSS_NO_MEMORY;
+ return GSS_S_FAILURE;
+ }
+
+ *output_name = (gss_name_t) name;
+ *min = 0;
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_release_name(OM_uint32 *min,
+ gss_name_t *input_name)
+{
+ if(min)
+ *min = 0;
+
+ if(input_name)
+ free(*input_name);
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_display_status(OM_uint32 *min,
+ OM_uint32 status_value,
+ int status_type,
+ const gss_OID mech_type,
+ OM_uint32 *message_context,
+ gss_buffer_t status_string)
+{
+ const char maj_str[] = "Stub GSS error";
+ if(min)
+ *min = 0;
+
+ if(message_context)
+ *message_context = 0;
+
+ if(status_string) {
+ status_string->value = NULL;
+ status_string->length = 0;
+
+ if(status_value >= GSS_LAST)
+ return GSS_S_FAILURE;
+
+ switch(status_type) {
+ case GSS_C_GSS_CODE:
+ status_string->value = strdup(maj_str);
+ break;
+ case GSS_C_MECH_CODE:
+ status_string->value = strdup(min_err_table[status_value]);
+ break;
+ default:
+ return GSS_S_FAILURE;
+ }
+
+ if(status_string->value)
+ status_string->length = strlen(status_string->value);
+ else
+ return GSS_S_FAILURE;
+ }
+
+ return GSS_S_COMPLETE;
+}
+
+/* Stubs returning error */
+
+OM_uint32 gss_display_name(OM_uint32 *min,
+ gss_const_name_t input_name,
+ gss_buffer_t output_name_buffer,
+ gss_OID *output_name_type)
+{
+ return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_inquire_context(OM_uint32 *min,
+ gss_const_ctx_id_t context_handle,
+ gss_name_t *src_name,
+ gss_name_t *targ_name,
+ OM_uint32 *lifetime_rec,
+ gss_OID *mech_type,
+ OM_uint32 *ctx_flags,
+ int *locally_initiated,
+ int *open_context)
+{
+ return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_wrap(OM_uint32 *min,
+ gss_const_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ const gss_buffer_t input_message_buffer,
+ int *conf_state,
+ gss_buffer_t output_message_buffer)
+{
+ return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_unwrap(OM_uint32 *min,
+ gss_const_ctx_id_t context_handle,
+ const gss_buffer_t input_message_buffer,
+ gss_buffer_t output_message_buffer,
+ int *conf_state,
+ gss_qop_t *qop_state)
+{
+ return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_seal(OM_uint32 *min,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ int qop_req,
+ gss_buffer_t input_message_buffer,
+ int *conf_state,
+ gss_buffer_t output_message_buffer)
+{
+ return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_unseal(OM_uint32 *min,
+ gss_ctx_id_t context_handle,
+ gss_buffer_t input_message_buffer,
+ gss_buffer_t output_message_buffer,
+ int *conf_state,
+ int *qop_state)
+{
+ return GSS_S_FAILURE;
+}
+
diff --git a/tests/libtest/stub_gssapi.h b/tests/libtest/stub_gssapi.h
new file mode 100644
index 000000000..9a302f0f5
--- /dev/null
+++ b/tests/libtest/stub_gssapi.h
@@ -0,0 +1,183 @@
+#ifndef HEADER_CURL_GSSAPI_STUBS_H
+#define HEADER_CURL_GSSAPI_STUBS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* Roughly based on Heimdal's gssapi.h */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define GSS_ERROR(status) (status & 0x80000000)
+
+#define GSS_S_COMPLETE 0
+#define GSS_S_FAILURE (0x80000000)
+#define GSS_S_CONTINUE_NEEDED (1ul)
+
+#define GSS_C_QOP_DEFAULT 0
+#define GSS_C_NO_OID ((gss_OID) 0)
+#define GSS_C_NO_NAME ((gss_name_t) 0)
+#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
+#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
+#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
+#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
+
+#define GSS_C_NULL_OID GSS_C_NO_OID
+
+#define GSS_C_EMPTY_BUFFER {0, NULL}
+
+#define GSS_C_AF_INET 2
+
+#define GSS_C_GSS_CODE 1
+#define GSS_C_MECH_CODE 2
+
+#define GSS_C_DELEG_FLAG 1
+#define GSS_C_MUTUAL_FLAG 2
+#define GSS_C_REPLAY_FLAG 4
+#define GSS_C_CONF_FLAG 16
+#define GSS_C_INTEG_FLAG 32
+
+/*
+ * Expiration time of 2^32-1 seconds means infinite lifetime for a
+ * credential or security context
+ */
+#define GSS_C_INDEFINITE 0xfffffffful
+
+#define GSS_C_NT_HOSTBASED_SERVICE NULL
+
+typedef uint32_t OM_uint32;
+
+typedef OM_uint32 gss_qop_t;
+
+typedef struct gss_buffer_desc_struct {
+ size_t length;
+ void *value;
+} gss_buffer_desc, *gss_buffer_t;
+
+struct gss_cred_id_t_desc_struct;
+typedef struct gss_cred_id_t_desc_struct *gss_cred_id_t;
+typedef const struct gss_cred_id_t_desc_struct *gss_const_cred_id_t;
+
+struct gss_ctx_id_t_desc_struct;
+typedef struct gss_ctx_id_t_desc_struct *gss_ctx_id_t;
+typedef const struct gss_ctx_id_t_desc_struct *gss_const_ctx_id_t;
+
+struct gss_name_t_desc_struct;
+typedef struct gss_name_t_desc_struct *gss_name_t;
+typedef const struct gss_name_t_desc_struct *gss_const_name_t;
+
+typedef struct gss_OID_desc_struct {
+ OM_uint32 length;
+ void *elements;
+} gss_OID_desc, *gss_OID;
+
+typedef struct gss_channel_bindings_struct {
+ OM_uint32 initiator_addrtype;
+ gss_buffer_desc initiator_address;
+ OM_uint32 acceptor_addrtype;
+ gss_buffer_desc acceptor_address;
+ gss_buffer_desc application_data;
+} *gss_channel_bindings_t;
+
+OM_uint32 gss_release_buffer(OM_uint32 * /*minor_status*/,
+ gss_buffer_t /*buffer*/);
+
+OM_uint32 gss_init_sec_context(OM_uint32 * /*minor_status*/,
+ gss_const_cred_id_t /*initiator_cred_handle*/,
+ gss_ctx_id_t * /*context_handle*/,
+ gss_const_name_t /*target_name*/,
+ const gss_OID /*mech_type*/,
+ OM_uint32 /*req_flags*/,
+ OM_uint32 /*time_req*/,
+ const gss_channel_bindings_t /*input_chan_bindings*/,
+ const gss_buffer_t /*input_token*/,
+ gss_OID * /*actual_mech_type*/,
+ gss_buffer_t /*output_token*/,
+ OM_uint32 * /*ret_flags*/,
+ OM_uint32 * /*time_rec*/);
+
+OM_uint32 gss_delete_sec_context(OM_uint32 * /*minor_status*/,
+ gss_ctx_id_t * /*context_handle*/,
+ gss_buffer_t /*output_token*/);
+
+OM_uint32 gss_inquire_context(OM_uint32 * /*minor_status*/,
+ gss_const_ctx_id_t /*context_handle*/,
+ gss_name_t * /*src_name*/,
+ gss_name_t * /*targ_name*/,
+ OM_uint32 * /*lifetime_rec*/,
+ gss_OID * /*mech_type*/,
+ OM_uint32 * /*ctx_flags*/,
+ int * /*locally_initiated*/,
+ int * /*open_context*/);
+
+OM_uint32 gss_wrap(OM_uint32 * /*minor_status*/,
+ gss_const_ctx_id_t /*context_handle*/,
+ int /*conf_req_flag*/,
+ gss_qop_t /*qop_req*/,
+ const gss_buffer_t /*input_message_buffer*/,
+ int * /*conf_state*/,
+ gss_buffer_t /*output_message_buffer*/);
+
+OM_uint32 gss_unwrap(OM_uint32 * /*minor_status*/,
+ gss_const_ctx_id_t /*context_handle*/,
+ const gss_buffer_t /*input_message_buffer*/,
+ gss_buffer_t /*output_message_buffer*/,
+ int * /*conf_state*/,
+ gss_qop_t * /*qop_state*/);
+
+OM_uint32 gss_seal(OM_uint32 * /*minor_status*/,
+ gss_ctx_id_t /*context_handle*/,
+ int /*conf_req_flag*/,
+ int /*qop_req*/,
+ gss_buffer_t /*input_message_buffer*/,
+ int * /*conf_state*/,
+ gss_buffer_t /*output_message_buffer*/);
+
+OM_uint32 gss_unseal(OM_uint32 * /*minor_status*/,
+ gss_ctx_id_t /*context_handle*/,
+ gss_buffer_t /*input_message_buffer*/,
+ gss_buffer_t /*output_message_buffer*/,
+ int * /*conf_state*/,
+ int * /*qop_state*/);
+
+OM_uint32 gss_import_name(OM_uint32 * /*minor_status*/,
+ const gss_buffer_t /*input_name_buffer*/,
+ const gss_OID /*input_name_type*/,
+ gss_name_t * /*output_name*/);
+
+OM_uint32 gss_release_name(OM_uint32 * /*minor_status*/,
+ gss_name_t * /*input_name*/);
+
+OM_uint32 gss_display_name(OM_uint32 * /*minor_status*/,
+ gss_const_name_t /*input_name*/,
+ gss_buffer_t /*output_name_buffer*/,
+ gss_OID * /*output_name_type*/);
+
+OM_uint32 gss_display_status(OM_uint32 * /*minor_status*/,
+ OM_uint32 /*status_value*/,
+ int /*status_type*/,
+ const gss_OID /*mech_type*/,
+ OM_uint32 * /*message_context*/,
+ gss_buffer_t /*status_string*/);
+
+#endif /* HEADER_CURL_GSSAPI_STUBS_H */
+
diff --git a/tests/libtest/testtrace.c b/tests/libtest/testtrace.c
index 62641e15c..5c68b3b1b 100644
--- a/tests/libtest/testtrace.c
+++ b/tests/libtest/testtrace.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -53,25 +53,27 @@ void libtest_debug_dump(const char *timebuf, const char *text, FILE *stream,
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
- if(i+c < size)
- fprintf(stream, "%02x ", ptr[i+c]);
+ if(i + c < size)
+ fprintf(stream, "%02x ", ptr[i + c]);
else
fputs(" ", stream);
}
- for(c = 0; (c < width) && (i+c < size); c++) {
+ for(c = 0; (c < width) && (i + c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
if(nohex &&
- (i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) {
- i += (c+2-width);
+ (i + c + 1 < size) && (ptr[i + c] == 0x0D) &&
+ (ptr[i + c + 1] == 0x0A)) {
+ i += (c + 2 - width);
break;
}
- fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ?
- ptr[i+c] : '.');
+ fprintf(stream, "%c", ((ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80)) ?
+ ptr[i + c] : '.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
if(nohex &&
- (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) {
- i += (c+3-width);
+ (i + c + 2 < size) && (ptr[i + c + 1] == 0x0D) &&
+ (ptr[i + c + 2] == 0x0A)) {
+ i += (c + 3 - width);
break;
}
}
diff --git a/tests/runtests.pl b/tests/runtests.pl
index c67673fbd..66919bcd7 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -232,6 +232,7 @@ my $has_crypto; # set if libcurl is built with cryptographic support
my $has_cares; # set if built with c-ares
my $has_threadedres;# set if built with threaded resolver
my $has_psl; # set if libcurl is built with PSL support
+my $has_ldpreload; # set if curl is built for systems supporting LD_PRELOAD
# this version is decided by the particular nghttp2 library that is being used
my $h2cver = "h2c";
@@ -2731,6 +2732,9 @@ sub checksystem {
$curl =~ s/^(.*)(libcurl.*)/$1/g;
$libcurl = $2;
+ if($curl =~ /linux|bsd|solaris|darwin/) {
+ $has_ldpreload = 1;
+ }
if($curl =~ /win32|mingw(32|64)/) {
# This is a Windows MinGW build or native build, we need to use
# Win32-style path.
@@ -3315,6 +3319,11 @@ sub singletest {
next;
}
}
+ elsif($1 eq "ld_preload") {
+ if($has_ldpreload && !$debug_build) {
+ next;
+ }
+ }
elsif($1 eq "unittest") {
if($debug_build) {
next;
@@ -3585,9 +3594,9 @@ sub singletest {
for $k (@keywords) {
chomp $k;
- if ($disabled_keywords{$k}) {
+ if ($disabled_keywords{lc($k)}) {
$why = "disabled by keyword";
- } elsif ($enabled_keywords{$k}) {
+ } elsif ($enabled_keywords{lc($k)}) {
$match = 1;
}
}
@@ -3755,6 +3764,13 @@ sub singletest {
# if this section exists, we verify upload
my @upload = getpart("verify", "upload");
+ if(@upload) {
+ my %hash = getpartattr("verify", "upload");
+ if($hash{'nonewline'}) {
+ # cut off the final newline from the final line of the upload data
+ chomp($upload[$#upload]);
+ }
+ }
# if this section exists, it might be FTP server instructions:
my @ftpservercmd = getpart("reply", "servercmd");
@@ -3808,23 +3824,25 @@ sub singletest {
unlink($memdump);
}
- # create a (possibly-empty) file before starting the test
- my @inputfile=getpart("client", "file");
- my %fileattr = getpartattr("client", "file");
- my $filename=$fileattr{'name'};
- if(@inputfile || $filename) {
- if(!$filename) {
- logmsg "ERROR: section client=>file has no name attribute\n";
- timestampskippedevents($testnum);
- return -1;
+ # create (possibly-empty) files before starting the test
+ for my $partsuffix (('', '1', '2', '3', '4')) {
+ my @inputfile=getpart("client", "file".$partsuffix);
+ my %fileattr = getpartattr("client", "file".$partsuffix);
+ my $filename=$fileattr{'name'};
+ if(@inputfile || $filename) {
+ if(!$filename) {
+ logmsg "ERROR: section client=>file has no name attribute\n";
+ timestampskippedevents($testnum);
+ return -1;
+ }
+ my $fileContent = join('', @inputfile);
+ subVariables \$fileContent;
+# logmsg "DEBUG: writing file " . $filename . "\n";
+ open(OUTFILE, ">$filename");
+ binmode OUTFILE; # for crapage systems, use binary
+ print OUTFILE $fileContent;
+ close(OUTFILE);
}
- my $fileContent = join('', @inputfile);
- subVariables \$fileContent;
-# logmsg "DEBUG: writing file " . $filename . "\n";
- open(OUTFILE, ">$filename");
- binmode OUTFILE; # for crapage systems, use binary
- print OUTFILE $fileContent;
- close(OUTFILE);
}
my %cmdhash = getpartattr("client", "command");
@@ -4289,6 +4307,17 @@ sub singletest {
if(@upload) {
# verify uploaded data
my @out = loadarray("$LOGDIR/upload.$testnum");
+
+ # what parts to cut off from the upload
+ my @strippart = getpart("verify", "strippart");
+ my $strip;
+ for $strip (@strippart) {
+ chomp $strip;
+ for(@out) {
+ eval $strip;
+ }
+ }
+
$res = compare($testnum, $testname, "upload", \@out, \@upload);
if ($res) {
return 1;
@@ -5379,10 +5408,10 @@ EOHELP
$disabled{$1}=$1;
}
elsif($ARGV[0] =~ /^!(.+)/) {
- $disabled_keywords{$1}=$1;
+ $disabled_keywords{lc($1)}=$1;
}
elsif($ARGV[0] =~ /^([-[{a-zA-Z].*)/) {
- $enabled_keywords{$1}=$1;
+ $enabled_keywords{lc($1)}=$1;
}
else {
print "Unknown option: $ARGV[0]\n";
diff --git a/tests/server/fake_ntlm.c b/tests/server/fake_ntlm.c
index 0d1b3e1b6..ca2b438b6 100644
--- a/tests/server/fake_ntlm.c
+++ b/tests/server/fake_ntlm.c
@@ -63,7 +63,8 @@ static char *printable(char *inbuf, size_t inlength)
inlength = strlen(inbuf);
if(inlength) {
- outincr = ((inlength/2) < (HEX_STR_LEN+1)) ? HEX_STR_LEN+1 : inlength/2;
+ outincr = ((inlength/2) < (HEX_STR_LEN + 1)) ?
+ HEX_STR_LEN + 1 : inlength/2;
outsize = inlength + outincr;
}
else
@@ -78,7 +79,7 @@ static char *printable(char *inbuf, size_t inlength)
return outbuf;
}
- for(i=0; i<inlength; i++) {
+ for(i = 0; i<inlength; i++) {
if(o > outsize - (HEX_STR_LEN + 1)) {
newsize = outsize + outincr;
@@ -186,7 +187,7 @@ int main(int argc, char *argv[])
}
filename = test2file(testnum);
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -204,7 +205,7 @@ int main(int argc, char *argv[])
}
}
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -224,7 +225,7 @@ int main(int argc, char *argv[])
while(fgets(buf, sizeof(buf), stdin)) {
if(strcmp(buf, type1_input) == 0) {
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -246,7 +247,7 @@ int main(int argc, char *argv[])
fflush(stdout);
}
else if(strncmp(buf, type3_input, strlen(type3_input)) == 0) {
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
diff --git a/tests/server/getpart.c b/tests/server/getpart.c
index bb8351bc3..d434ba289 100644
--- a/tests/server/getpart.c
+++ b/tests/server/getpart.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -66,6 +66,35 @@ curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
# pragma warning(default:4232) /* MSVC extension, dllimport identity */
#endif
+
+/*
+ * Curl_convert_clone() returns a malloced copy of the source string (if
+ * returning CURLE_OK), with the data converted to network format. This
+ * function is used by base64 code in libcurl built to support data
+ * conversion. This is a DUMMY VERSION that returns data unmodified - for
+ * use by the test server only.
+ */
+CURLcode Curl_convert_clone(struct Curl_easy *data,
+ const char *indata,
+ size_t insize,
+ char **outbuf);
+CURLcode Curl_convert_clone(struct Curl_easy *data,
+ const char *indata,
+ size_t insize,
+ char **outbuf)
+{
+ char *convbuf;
+ (void)data;
+
+ convbuf = malloc(insize);
+ if(!convbuf)
+ return CURLE_OUT_OF_MEMORY;
+
+ memcpy(convbuf, indata, insize);
+ *outbuf = convbuf;
+ return CURLE_OK;
+}
+
/*
* readline()
*
@@ -250,11 +279,11 @@ int getpart(char **outbuf, size_t *outlen,
const char *main, const char *sub, FILE *stream)
{
# define MAX_TAG_LEN 79
- char couter[MAX_TAG_LEN+1]; /* current outermost section */
- char cmain[MAX_TAG_LEN+1]; /* current main section */
- char csub[MAX_TAG_LEN+1]; /* current sub section */
- char ptag[MAX_TAG_LEN+1]; /* potential tag */
- char patt[MAX_TAG_LEN+1]; /* potential attributes */
+ char couter[MAX_TAG_LEN + 1]; /* current outermost section */
+ char cmain[MAX_TAG_LEN + 1]; /* current main section */
+ char csub[MAX_TAG_LEN + 1]; /* current sub section */
+ char ptag[MAX_TAG_LEN + 1]; /* potential tag */
+ char patt[MAX_TAG_LEN + 1]; /* potential attributes */
char *buffer = NULL;
char *ptr;
char *end;
@@ -451,4 +480,3 @@ int getpart(char **outbuf, size_t *outlen,
return error;
}
-
diff --git a/tests/server/resolve.c b/tests/server/resolve.c
index 34f14e066..4cbdba6ec 100644
--- a/tests/server/resolve.c
+++ b/tests/server/resolve.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -57,11 +57,11 @@
static bool use_ipv6 = FALSE;
static const char *ipv_inuse = "IPv4";
-const char *serverlogfile=""; /* for a util.c function we don't use */
+const char *serverlogfile = ""; /* for a util.c function we don't use */
int main(int argc, char *argv[])
{
- int arg=1;
+ int arg = 1;
const char *host = NULL;
int rc = 0;
diff --git a/tests/server/rtspd.c b/tests/server/rtspd.c
index 120d65d52..53ffeb6e1 100644
--- a/tests/server/rtspd.c
+++ b/tests/server/rtspd.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -70,11 +70,11 @@ static int serverlogslocked = 0;
#define REQBUFSIZ 150000
#define REQBUFSIZ_TXT "149999"
-static long prevtestno=-1; /* previous test number we served */
-static long prevpartno=-1; /* previous part number we served */
-static bool prevbounce=FALSE; /* instructs the server to increase the part
- number for a test in case the identical
- testno+partno request shows up again */
+static long prevtestno = -1; /* previous test number we served */
+static long prevpartno = -1; /* previous part number we served */
+static bool prevbounce = FALSE; /* instructs the server to increase the part
+ number for a test in case the identical
+ testno+partno request shows up again */
#define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
#define RCMD_IDLE 1 /* told to sit idle */
@@ -156,7 +156,7 @@ enum {
DOCNUMBER_NOTHING = -7,
DOCNUMBER_QUIT = -6,
DOCNUMBER_BADCONNECT = -5,
- DOCNUMBER_INTERNAL= -4,
+ DOCNUMBER_INTERNAL = -4,
DOCNUMBER_CONNECT = -3,
DOCNUMBER_WERULEZ = -2,
DOCNUMBER_404 = -1
@@ -332,7 +332,7 @@ static void restore_signal_handlers(void)
static int ProcessRequest(struct httprequest *req)
{
- char *line=&req->reqbuf[req->checkindex];
+ char *line = &req->reqbuf[req->checkindex];
bool chunked = FALSE;
static char request[REQUEST_KEYWORD_SIZE];
static char doc[MAXDOCNAMELEN];
@@ -421,7 +421,7 @@ static int ProcessRequest(struct httprequest *req)
filename = test2file(req->testno);
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -433,7 +433,7 @@ static int ProcessRequest(struct httprequest *req)
else {
char *cmd = NULL;
size_t cmdsize = 0;
- int num=0;
+ int num = 0;
int rtp_channel = 0;
int rtp_size = 0;
@@ -500,7 +500,7 @@ static int ProcessRequest(struct httprequest *req)
SET_RTP_PKT_LEN(rtp_scratch, rtp_size);
/* Fill it with junk data */
- for(i = 0; i < rtp_size; i+= RTP_DATA_SIZE) {
+ for(i = 0; i < rtp_size; i += RTP_DATA_SIZE) {
memcpy(rtp_scratch + 4 + i, RTP_DATA, RTP_DATA_SIZE);
}
@@ -554,8 +554,8 @@ static int ProcessRequest(struct httprequest *req)
/* if the host name starts with test, the port number used in the
CONNECT line will be used as test number! */
char *portp = strchr(doc, ':');
- if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1)))
- req->testno = strtol(portp+1, NULL, 10);
+ if(portp && (*(portp + 1) != '\0') && ISDIGIT(*(portp + 1)))
+ req->testno = strtol(portp + 1, NULL, 10);
else
req->testno = DOCNUMBER_CONNECT;
}
@@ -596,7 +596,7 @@ static int ProcessRequest(struct httprequest *req)
if(got_exit_signal)
return 1; /* done */
- if((req->cl==0) && strncasecompare("Content-Length:", line, 15)) {
+ if((req->cl == 0) && strncasecompare("Content-Length:", line, 15)) {
/* If we don't ignore content-length, we read it and we read the whole
request including the body before we return. If we've been told to
ignore the content-length, we will return as soon as all headers
@@ -896,10 +896,10 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
ssize_t written;
size_t count;
const char *buffer;
- char *ptr=NULL;
+ char *ptr = NULL;
FILE *stream;
- char *cmd=NULL;
- size_t cmdsize=0;
+ char *cmd = NULL;
+ size_t cmdsize = 0;
FILE *dump;
bool persistant = TRUE;
bool sendfailure = FALSE;
@@ -988,7 +988,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
if(0 != req->partno)
snprintf(partbuf, sizeof(partbuf), "data%ld", req->partno);
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1012,7 +1012,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
}
/* re-open the same file again */
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1140,7 +1140,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
char command[32];
int quarters;
int num;
- ptr=cmd;
+ ptr = cmd;
do {
if(2 == sscanf(ptr, "%31s %d", command, &num)) {
if(!strcmp("wait", command)) {
@@ -1194,7 +1194,7 @@ int main(int argc, char *argv[])
struct httprequest req;
int rc;
int error;
- int arg=1;
+ int arg = 1;
long pid;
memset(&req, 0, sizeof(req));
diff --git a/tests/server/sockfilt.c b/tests/server/sockfilt.c
index 6695d8486..f13ef208d 100644
--- a/tests/server/sockfilt.c
+++ b/tests/server/sockfilt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -478,26 +478,26 @@ static void lograw(unsigned char *buffer, ssize_t len)
ssize_t i;
unsigned char *ptr = buffer;
char *optr = data;
- ssize_t width=0;
+ ssize_t width = 0;
int left = sizeof(data);
- for(i=0; i<len; i++) {
+ for(i = 0; i<len; i++) {
switch(ptr[i]) {
case '\n':
snprintf(optr, left, "\\n");
width += 2;
optr += 2;
- left-=2;
+ left -= 2;
break;
case '\r':
snprintf(optr, left, "\\r");
width += 2;
optr += 2;
- left-=2;
+ left -= 2;
break;
default:
snprintf(optr, left, "%c", (ISGRAPH(ptr[i]) ||
- ptr[i]==0x20) ?ptr[i]:'.');
+ ptr[i] == 0x20) ?ptr[i]:'.');
width++;
optr++;
left--;
@@ -1200,7 +1200,7 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
int rc;
int totdelay = 0;
int maxretr = 10;
- int delay= 20;
+ int delay = 20;
int attempt = 0;
int error = 0;
@@ -1343,7 +1343,7 @@ int main(int argc, char *argv[])
bool juggle_again;
int rc;
int error;
- int arg=1;
+ int arg = 1;
enum sockmode mode = PASSIVE_LISTEN; /* default */
const char *addr = NULL;
diff --git a/tests/server/sws.c b/tests/server/sws.c
index bff30f212..821497068 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -81,11 +81,11 @@ static bool is_proxy = FALSE;
#define REQBUFSIZ 150000
#define REQBUFSIZ_TXT "149999"
-static long prevtestno=-1; /* previous test number we served */
-static long prevpartno=-1; /* previous part number we served */
-static bool prevbounce=FALSE; /* instructs the server to increase the part
- number for a test in case the identical
- testno+partno request shows up again */
+static long prevtestno = -1; /* previous test number we served */
+static long prevpartno = -1; /* previous part number we served */
+static bool prevbounce = FALSE; /* instructs the server to increase the part
+ number for a test in case the identical
+ testno+partno request shows up again */
#define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
#define RCMD_IDLE 1 /* told to sit idle */
@@ -359,7 +359,7 @@ static int parse_servercmd(struct httprequest *req)
filename = test2file(req->testno);
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -372,7 +372,7 @@ static int parse_servercmd(struct httprequest *req)
char *orgcmd = NULL;
char *cmd = NULL;
size_t cmdsize = 0;
- int num=0;
+ int num = 0;
/* get the custom server control "commands" */
error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream);
@@ -456,7 +456,7 @@ static int parse_servercmd(struct httprequest *req)
static int ProcessRequest(struct httprequest *req)
{
- char *line=&req->reqbuf[req->checkindex];
+ char *line = &req->reqbuf[req->checkindex];
bool chunked = FALSE;
static char request[REQUEST_KEYWORD_SIZE];
static char doc[MAXDOCNAMELEN];
@@ -552,7 +552,7 @@ static int ProcessRequest(struct httprequest *req)
if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
doc, &prot_major, &prot_minor) == 3) {
char *portp = NULL;
- unsigned long part=0;
+ unsigned long part = 0;
snprintf(logbuf, sizeof(logbuf),
"Received a CONNECT %s HTTP/%d.%d request",
@@ -578,18 +578,18 @@ static int ProcessRequest(struct httprequest *req)
}
if(*p != ']')
logmsg("Invalid CONNECT IPv6 address format");
- else if(*(p+1) != ':')
+ else if(*(p + 1) != ':')
logmsg("Invalid CONNECT IPv6 port format");
else
- portp = p+1;
+ portp = p + 1;
req->testno = part;
}
else
portp = strchr(doc, ':');
- if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1))) {
- unsigned long ulnum = strtoul(portp+1, NULL, 10);
+ if(portp && (*(portp + 1) != '\0') && ISDIGIT(*(portp + 1))) {
+ unsigned long ulnum = strtoul(portp + 1, NULL, 10);
if(!ulnum || (ulnum > 65535UL))
logmsg("Invalid CONNECT port received");
else
@@ -711,7 +711,7 @@ static int ProcessRequest(struct httprequest *req)
if(got_exit_signal)
return 1; /* done */
- if((req->cl==0) && strncasecompare("Content-Length:", line, 15)) {
+ if((req->cl == 0) && strncasecompare("Content-Length:", line, 15)) {
/* If we don't ignore content-length, we read it and we read the whole
request including the body before we return. If we've been told to
ignore the content-length, we will return as soon as all headers
@@ -763,7 +763,20 @@ static int ProcessRequest(struct httprequest *req)
logmsg("Authorization header found, as required");
}
- if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
+ if(strstr(req->reqbuf, "Authorization: Negotiate")) {
+ /* Negotiate iterations */
+ static long prev_testno = -1;
+ static long prev_partno = -1;
+ logmsg("Negotiate: prev_testno: %d, prev_partno: %d",
+ prev_testno, prev_partno);
+ if(req->testno != prev_testno) {
+ prev_testno = req->testno;
+ prev_partno = req->partno;
+ }
+ prev_partno += 1;
+ req->partno = prev_partno;
+ }
+ else if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
/* If the client is passing this Digest-header, we set the part number
to 1000. Not only to spice up the complexity of this, but to make
Digest stuff to work in the test suite. */
@@ -858,7 +871,7 @@ static void storerequest(const char *reqbuf, size_t totalsize)
size_t written;
size_t writeleft;
FILE *dump;
- const char *dumpfile=is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
+ const char *dumpfile = is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
if(reqbuf == NULL)
return;
@@ -1044,10 +1057,10 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
ssize_t written;
size_t count;
const char *buffer;
- char *ptr=NULL;
+ char *ptr = NULL;
FILE *stream;
- char *cmd=NULL;
- size_t cmdsize=0;
+ char *cmd = NULL;
+ size_t cmdsize = 0;
FILE *dump;
bool persistant = TRUE;
bool sendfailure = FALSE;
@@ -1118,7 +1131,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
/* select the <data> tag for "normal" requests and the <connect> one
for CONNECT requests (within the <reply> section) */
- const char *section= req->connect_request?"connect":"data";
+ const char *section = req->connect_request?"connect":"data";
if(req->partno)
snprintf(partbuf, sizeof(partbuf), "%s%ld", section, req->partno);
@@ -1127,7 +1140,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
logmsg("Send response test%ld section <%s>", req->testno, partbuf);
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1150,7 +1163,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
}
/* re-open the same file again */
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1266,7 +1279,7 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
char command[32];
int quarters;
int num;
- ptr=cmd;
+ ptr = cmd;
do {
if(2 == sscanf(ptr, "%31s %d", command, &num)) {
if(!strcmp("wait", command)) {
@@ -1436,7 +1449,7 @@ static void http_connect(curl_socket_t *infdp,
int max_tunnel_idx; /* CTRL or DATA */
int loop;
int i;
- int timeout_count=0;
+ int timeout_count = 0;
/* primary tunnel client endpoint already connected */
clientfd[CTRL] = *infdp;
@@ -1526,7 +1539,7 @@ static void http_connect(curl_socket_t *infdp,
if(rc > 0) {
/* socket action */
bool tcp_fin_wr;
- timeout_count=0;
+ timeout_count = 0;
if(got_exit_signal)
break;
@@ -1974,7 +1987,7 @@ int main(int argc, char *argv[])
struct httprequest req;
int rc = 0;
int error;
- int arg=1;
+ int arg = 1;
long pid;
const char *connecthost = "127.0.0.1";
const char *socket_type = "IPv4";
@@ -2319,7 +2332,7 @@ int main(int argc, char *argv[])
logmsg("====> Client disconnect %d", req.connmon);
if(req.connmon) {
- const char *keepopen="[DISCONNECT]\n";
+ const char *keepopen = "[DISCONNECT]\n";
storerequest(keepopen, strlen(keepopen));
}
diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c
index df01eb782..a8b565197 100644
--- a/tests/server/tftpd.c
+++ b/tests/server/tftpd.c
@@ -515,7 +515,7 @@ static void read_ahead(struct testcase *test,
}
else {
if(test->rcount) {
- c=test->rptr[0];
+ c = test->rptr[0];
test->rptr++;
test->rcount--;
}
@@ -571,9 +571,9 @@ static ssize_t write_behind(struct testcase *test, int convert)
char outfile[256];
snprintf(outfile, sizeof(outfile), "log/upload.%ld", test->testno);
#ifdef WIN32
- test->ofile=open(outfile, O_CREAT|O_RDWR|O_BINARY, 0777);
+ test->ofile = open(outfile, O_CREAT|O_RDWR|O_BINARY, 0777);
#else
- test->ofile=open(outfile, O_CREAT|O_RDWR, 0777);
+ test->ofile = open(outfile, O_CREAT|O_RDWR, 0777);
#endif
if(test->ofile == -1) {
logmsg("Couldn't create and/or open file %s for upload!", outfile);
@@ -992,7 +992,7 @@ static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
/* before increasing pointer, make sure it is still within the legal
space */
- if((cp+1) < &buf.storage[size]) {
+ if((cp + 1) < &buf.storage[size]) {
++cp;
if(first) {
/* store the mode since we need it later */
@@ -1074,7 +1074,7 @@ static int parse_servercmd(struct testcase *req)
filename = test2file(req->testno);
- stream=fopen(filename, "rb");
+ stream = fopen(filename, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1086,7 +1086,7 @@ static int parse_servercmd(struct testcase *req)
char *orgcmd = NULL;
char *cmd = NULL;
size_t cmdsize = 0;
- int num=0;
+ int num = 0;
/* get the custom server control "commands" */
error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream);
@@ -1192,7 +1192,7 @@ static int validate_access(struct testcase *test,
snprintf(partbuf, sizeof(partbuf), "data%ld", partno);
if(file) {
- FILE *stream=fopen(file, "rb");
+ FILE *stream = fopen(file, "rb");
if(!stream) {
error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
diff --git a/tests/server/util.c b/tests/server/util.c
index 42e585349..1bbd89a3c 100644
--- a/tests/server/util.c
+++ b/tests/server/util.c
@@ -81,15 +81,15 @@ char *data_to_hex(char *data, size_t len)
if(len > 255)
len = 255;
- for(i=0; i < len; i++) {
+ for(i = 0; i < len; i++) {
if((data[i] >= 0x20) && (data[i] < 0x7f))
*optr++ = *iptr++;
else {
snprintf(optr, 4, "%%%02x", *iptr++);
- optr+=3;
+ optr += 3;
}
}
- *optr=0; /* in case no sprintf was used */
+ *optr = 0; /* in case no sprintf was used */
return buf;
}
@@ -189,7 +189,7 @@ void win32_cleanup(void)
#endif /* USE_WINSOCK */
/* set by the main code to point to where the test dir is */
-const char *path=".";
+const char *path = ".";
char *test2file(long testno)
{
diff --git a/tests/unit/unit1300.c b/tests/unit/unit1300.c
index 8ec32a8c9..c64fadef9 100644
--- a/tests/unit/unit1300.c
+++ b/tests/unit/unit1300.c
@@ -145,7 +145,7 @@ UNITTEST_START
* 3: "new" head's previous will be NULL
*/
- head=llist.head;
+ head = llist.head;
abort_unless(head, "llist.head is NULL");
element_next = head->next;
llist_size = Curl_llist_count(&llist);
diff --git a/tests/unit/unit1301.c b/tests/unit/unit1301.c
index aa8610113..2af60bef4 100644
--- a/tests/unit/unit1301.c
+++ b/tests/unit/unit1301.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@ UNITTEST_START
int rc;
rc = curl_strequal("iii", "III");
-fail_unless(rc != 0, "return code should be zero");
+fail_unless(rc != 0, "return code should be non-zero");
rc = curl_strequal("iiia", "III");
fail_unless(rc == 0, "return code should be zero");
diff --git a/tests/unit/unit1302.c b/tests/unit/unit1302.c
index 8dae5aad1..e6f94b24e 100644
--- a/tests/unit/unit1302.c
+++ b/tests/unit/unit1302.c
@@ -30,15 +30,19 @@ static struct Curl_easy *data;
static CURLcode unit_setup(void)
{
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
data = curl_easy_init();
if(!data)
return CURLE_OUT_OF_MEMORY;
- return CURLE_OK;
+ return res;
}
static void unit_stop(void)
{
curl_easy_cleanup(data);
+ curl_global_cleanup();
}
UNITTEST_START
diff --git a/tests/unit/unit1303.c b/tests/unit/unit1303.c
index 143ccd034..75a8e59c2 100644
--- a/tests/unit/unit1303.c
+++ b/tests/unit/unit1303.c
@@ -29,15 +29,19 @@ static struct Curl_easy *data;
static CURLcode unit_setup(void)
{
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
data = curl_easy_init();
if(!data)
return CURLE_OUT_OF_MEMORY;
- return CURLE_OK;
+ return res;
}
static void unit_stop(void)
{
curl_easy_cleanup(data);
+ curl_global_cleanup();
}
/* BASE is just a define to make us fool around with decently large number so
@@ -134,7 +138,7 @@ UNITTEST_START
data->progress.t_startop.tv_sec = BASE;
data->progress.t_startop.tv_usec = 0;
- for(i=0; i < sizeof(run)/sizeof(run[0]); i++) {
+ for(i = 0; i < sizeof(run)/sizeof(run[0]); i++) {
NOW(run[i].now_s, run[i].now_us);
TIMEOUTS(run[i].timeout_ms, run[i].connecttimeout_ms);
timeout = Curl_timeleft(data, &now, run[i].connecting);
diff --git a/tests/unit/unit1305.c b/tests/unit/unit1305.c
index b958d0434..6e4bbb861 100644
--- a/tests/unit/unit1305.c
+++ b/tests/unit/unit1305.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -130,7 +130,7 @@ UNITTEST_START
key_len = strlen(data_key);
data_node->inuse = 1; /* hash will hold the reference */
- nodep = Curl_hash_add(&hp, data_key, key_len+1, data_node);
+ nodep = Curl_hash_add(&hp, data_key, key_len + 1, data_node);
abort_unless(nodep, "insertion into hash failed");
/* Freeing will now be done by Curl_hash_destroy */
data_node = NULL;
diff --git a/tests/unit/unit1308.c b/tests/unit/unit1308.c
index 4cd384877..27624a648 100644
--- a/tests/unit/unit1308.c
+++ b/tests/unit/unit1308.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -71,7 +71,7 @@ UNITTEST_START
fail_unless(rc == 0, "curl_formget returned error");
- fail_unless(total_size == 486, "curl_formget got wrong size back");
+ fail_unless(total_size == 488, "curl_formget got wrong size back");
curl_formfree(post);
@@ -88,7 +88,7 @@ UNITTEST_START
rc = curl_formget(post, &total_size, print_httppost_callback);
fail_unless(rc == 0, "curl_formget returned error");
- fail_unless(total_size == 847, "curl_formget got wrong size back");
+ fail_unless(total_size == 851, "curl_formget got wrong size back");
curl_formfree(post);
diff --git a/tests/unit/unit1309.c b/tests/unit/unit1309.c
index 9d1e70d27..c53cbcbce 100644
--- a/tests/unit/unit1309.c
+++ b/tests/unit/unit1309.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,8 +42,8 @@ static void splayprint(struct Curl_tree * t, int d, char output)
if(t == NULL)
return;
- splayprint(t->larger, d+1, output);
- for(i=0; i<d; i++)
+ splayprint(t->larger, d + 1, output);
+ for(i = 0; i<d; i++)
if(output)
printf(" ");
@@ -52,7 +52,7 @@ static void splayprint(struct Curl_tree * t, int d, char output)
(long)t->key.tv_usec, i);
}
- for(count=0, node = t->samen; node != t; node = node->samen, count++)
+ for(count = 0, node = t->samen; node != t; node = node->samen, count++)
;
if(output) {
@@ -62,7 +62,7 @@ static void splayprint(struct Curl_tree * t, int d, char output)
printf("\n");
}
- splayprint(t->smaller, d+1, output);
+ splayprint(t->smaller, d + 1, output);
}
UNITTEST_START
@@ -94,7 +94,7 @@ UNITTEST_START
splayprint(root, 0, 1);
for(i = 0; i < NUM_NODES; i++) {
- int rem = (i+7)%NUM_NODES;
+ int rem = (i + 7)%NUM_NODES;
printf("Tree look:\n");
splayprint(root, 0, 1);
printf("remove pointer %d, payload %ld\n", rem,
@@ -119,13 +119,13 @@ UNITTEST_START
/* add some nodes with the same key */
for(j = 0; j <= i % 3; j++) {
size_t payload = key.tv_usec*10 + j;
- nodes[i*3+j].payload = (void *)payload; /* for simplicity */
- root = Curl_splayinsert(key, root, &nodes[i*3+j]);
+ nodes[i * 3 + j].payload = (void *)payload; /* for simplicity */
+ root = Curl_splayinsert(key, root, &nodes[i * 3 + j]);
}
}
removed = NULL;
- for(i = 0; i <= 1100; i+= 100) {
+ for(i = 0; i <= 1100; i += 100) {
printf("Removing nodes not larger than %d\n", i);
tv_now.tv_usec = i;
root = Curl_splaygetbest(tv_now, root, &removed);
diff --git a/tests/unit/unit1323.c b/tests/unit/unit1323.c
index 65dd3d287..7bb4cca40 100644
--- a/tests/unit/unit1323.c
+++ b/tests/unit/unit1323.c
@@ -49,7 +49,7 @@ UNITTEST_START
};
size_t i;
- for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+ for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
time_t result = curlx_tvdiff(tests[i].first, tests[i].second);
if(result != tests[i].result) {
printf("%d.%06u to %d.%06u got %d, but expected %d\n",
diff --git a/tests/unit/unit1395.c b/tests/unit/unit1395.c
index 13ea97bc4..527f28142 100644
--- a/tests/unit/unit1395.c
+++ b/tests/unit/unit1395.c
@@ -43,7 +43,7 @@ struct dotdot {
UNITTEST_START
unsigned int i;
- int fails=0;
+ int fails = 0;
const struct dotdot pairs[] = {
{ "/a/b/c/./../../g", "/a/g" },
{ "mid/content=5/../6", "mid/6" },
@@ -74,7 +74,7 @@ UNITTEST_START
{ ".", "" },
};
- for(i=0; i < sizeof(pairs)/sizeof(pairs[0]); i++) {
+ for(i = 0; i < sizeof(pairs)/sizeof(pairs[0]); i++) {
char *out = Curl_dedotdotify(pairs[i].input);
abort_unless(out != NULL, "returned NULL!");
diff --git a/tests/unit/unit1396.c b/tests/unit/unit1396.c
index f3275fdb6..4dd25b40d 100644
--- a/tests/unit/unit1396.c
+++ b/tests/unit/unit1396.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,13 +25,17 @@ static CURL *hnd;
static CURLcode unit_setup(void)
{
- return CURLE_OK;
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+ return res;
}
static void unit_stop(void)
{
if(hnd)
curl_easy_cleanup(hnd);
+ curl_global_cleanup();
}
struct test {
@@ -77,7 +81,7 @@ UNITTEST_START
hnd = curl_easy_init();
abort_unless(hnd != NULL, "returned NULL!");
- for(i=0; list1[i].in; i++) {
+ for(i = 0; list1[i].in; i++) {
int outlen;
char *out = curl_easy_unescape(hnd,
list1[i].in, list1[i].inlen,
@@ -93,7 +97,7 @@ UNITTEST_START
curl_free(out);
}
- for(i=0; list2[i].in; i++) {
+ for(i = 0; list2[i].in; i++) {
int outlen;
char *out = curl_easy_escape(hnd, list2[i].in, list2[i].inlen);
abort_unless(out != NULL, "returned NULL!");
diff --git a/tests/unit/unit1398.c b/tests/unit/unit1398.c
index 095242b07..7e6761c65 100644
--- a/tests/unit/unit1398.c
+++ b/tests/unit/unit1398.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -30,7 +30,7 @@ UNITTEST_START
int rc;
char buf[3] = {'b', 'u', 'g'};
-const char *str="bug";
+const char *str = "bug";
int width = 3;
char output[24];
diff --git a/tests/unit/unit1399.c b/tests/unit/unit1399.c
index 82e0dc27e..91fd3dae1 100644
--- a/tests/unit/unit1399.c
+++ b/tests/unit/unit1399.c
@@ -36,6 +36,20 @@ static void unit_stop(void)
}
+/*
+ * Invoke Curl_pgrsTime for TIMER_STARTSINGLE to trigger the behavior that
+ * manages is_t_startransfer_set, but fake the t_startsingle time for purposes
+ * of the test.
+ */
+static void fake_t_startsingle_time(struct Curl_easy *data,
+ struct curltime fake_now,
+ int seconds_offset)
+{
+ Curl_pgrsTime(data, TIMER_STARTSINGLE);
+ data->progress.t_startsingle.tv_sec = fake_now.tv_sec + seconds_offset;
+ data->progress.t_startsingle.tv_usec = fake_now.tv_usec;
+}
+
static bool usec_matches_seconds(time_t time_usec, int expected_seconds)
{
int time_sec = (int)(time_usec / usec_magnitude);
@@ -46,55 +60,58 @@ static bool usec_matches_seconds(time_t time_usec, int expected_seconds)
return same;
}
+static void expect_timer_seconds(struct Curl_easy *data, int seconds)
+{
+ char msg[64];
+ snprintf(msg, sizeof(msg), "about %d seconds should have passed", seconds);
+ fail_unless(usec_matches_seconds(data->progress.t_nslookup, seconds), msg);
+ fail_unless(usec_matches_seconds(data->progress.t_connect, seconds), msg);
+ fail_unless(usec_matches_seconds(data->progress.t_appconnect, seconds), msg);
+ fail_unless(usec_matches_seconds(data->progress.t_pretransfer, seconds),
+ msg);
+ fail_unless(usec_matches_seconds(data->progress.t_starttransfer, seconds),
+ msg);
+}
+
+/* Scenario: simulate a redirect. When a redirect occurs, t_nslookup,
+ * t_connect, t_appconnect, t_pretransfer, and t_starttransfer are addative.
+ * E.g., if t_starttransfer took 2 seconds initially and took another 1
+ * second for the redirect request, then the resulting t_starttransfer should
+ * be 3 seconds. */
UNITTEST_START
struct Curl_easy data;
struct curltime now = Curl_tvnow();
+ data.progress.t_nslookup = 0;
+ data.progress.t_connect = 0;
+ data.progress.t_appconnect = 0;
+ data.progress.t_pretransfer = 0;
data.progress.t_starttransfer = 0;
data.progress.t_redirect = 0;
-
- /*
- * Set the startsingle time to a second ago. This time is used by
- * Curl_pgrsTime to calculate how much time the events takes.
- * t_starttransfer should be updated to reflect the difference from this time
- * when `Curl_pgrsTime is invoked.
- */
- data.progress.t_startsingle.tv_sec = now.tv_sec - 1;
- data.progress.t_startsingle.tv_usec = now.tv_usec;
-
+ data.progress.start.tv_sec = now.tv_sec - 2;
+ data.progress.start.tv_usec = now.tv_usec;
+ fake_t_startsingle_time(&data, now, -2);
+
+ Curl_pgrsTime(&data, TIMER_NAMELOOKUP);
+ Curl_pgrsTime(&data, TIMER_CONNECT);
+ Curl_pgrsTime(&data, TIMER_APPCONNECT);
+ Curl_pgrsTime(&data, TIMER_PRETRANSFER);
Curl_pgrsTime(&data, TIMER_STARTTRANSFER);
- fail_unless(usec_matches_seconds(data.progress.t_starttransfer, 1),
- "about 1 second should have passed");
-
- /*
- * Update the startsingle time to a second ago to simulate another second has
- * passed.
- * Now t_starttransfer should not be changed, as t_starttransfer has already
- * occurred and another invocation of `Curl_pgrsTime` for TIMER_STARTTRANSFER
- * is superfluous.
- */
- data.progress.t_startsingle.tv_sec = now.tv_sec - 2;
- data.progress.t_startsingle.tv_usec = now.tv_usec;
-
- Curl_pgrsTime(&data, TIMER_STARTTRANSFER);
+ expect_timer_seconds(&data, 2);
- fail_unless(usec_matches_seconds(data.progress.t_starttransfer, 1),
- "about 1 second should have passed");
-
- /*
- * Simulate what happens after a redirect has occurred.
- *
- * Since the value of t_starttransfer is set to the value from the first
- * request, it should be updated when a transfer occurs such that
- * t_starttransfer is the starttransfer time of the redirect request.
- */
- data.progress.t_startsingle.tv_sec = now.tv_sec - 3;
- data.progress.t_startsingle.tv_usec = now.tv_usec;
+ /* now simulate the redirect */
data.progress.t_redirect = data.progress.t_starttransfer + 1;
-
+ fake_t_startsingle_time(&data, now, -1);
+
+ Curl_pgrsTime(&data, TIMER_NAMELOOKUP);
+ Curl_pgrsTime(&data, TIMER_CONNECT);
+ Curl_pgrsTime(&data, TIMER_APPCONNECT);
+ Curl_pgrsTime(&data, TIMER_PRETRANSFER);
+ /* ensure t_starttransfer is only set on the first invocation by attempting
+ * to set it twice */
+ Curl_pgrsTime(&data, TIMER_STARTTRANSFER);
Curl_pgrsTime(&data, TIMER_STARTTRANSFER);
- fail_unless(usec_matches_seconds(data.progress.t_starttransfer, 3),
- "about 3 second should have passed");
+ expect_timer_seconds(&data, 3);
UNITTEST_STOP
diff --git a/tests/unit/unit1600.c b/tests/unit/unit1600.c
index 11d718d35..190cf0f0a 100644
--- a/tests/unit/unit1600.c
+++ b/tests/unit/unit1600.c
@@ -28,13 +28,19 @@ static CURL *easy;
static CURLcode unit_setup(void)
{
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
easy = curl_easy_init();
- return easy ? CURLE_OK : CURLE_OUT_OF_MEMORY;
+ if(!easy)
+ return CURLE_OUT_OF_MEMORY;
+ return res;
}
static void unit_stop(void)
{
curl_easy_cleanup(easy);
+ curl_global_cleanup();
}
UNITTEST_START
diff --git a/tests/unit/unit1605.c b/tests/unit/unit1605.c
index 2fe3a5aca..dd5372225 100644
--- a/tests/unit/unit1605.c
+++ b/tests/unit/unit1605.c
@@ -23,14 +23,23 @@
#include "llist.h"
+static CURL *easy;
+
static CURLcode unit_setup(void)
{
- return CURLE_OK;
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+ easy = curl_easy_init();
+ if(!easy)
+ return CURLE_OUT_OF_MEMORY;
+ return res;
}
static void unit_stop(void)
{
-
+ curl_easy_cleanup(easy);
+ curl_global_cleanup();
}
UNITTEST_START
@@ -45,6 +54,4 @@ UNITTEST_START
esc = curl_easy_unescape(easy, "%41%41%41%41", -1, &len);
fail_unless(esc == NULL, "negative string length can't work");
- curl_easy_cleanup(easy);
-
UNITTEST_STOP
diff --git a/tests/unit/unit1606.c b/tests/unit/unit1606.c
index eca8f3c38..9640ce2c7 100644
--- a/tests/unit/unit1606.c
+++ b/tests/unit/unit1606.c
@@ -24,18 +24,27 @@
#include "speedcheck.h"
#include "urldata.h"
+static CURL *easy;
+
static CURLcode unit_setup(void)
{
- return CURLE_OK;
+ int res = CURLE_OK;
+
+ global_init(CURL_GLOBAL_ALL);
+ easy = curl_easy_init();
+ if(!easy)
+ return CURLE_OUT_OF_MEMORY;
+ return res;
}
static void unit_stop(void)
{
+ curl_easy_cleanup(easy);
+ curl_global_cleanup();
}
-static int runawhile(struct Curl_easy *easy,
- long time_limit,
+static int runawhile(long time_limit,
long speed_limit,
curl_off_t speed,
int dec)
@@ -66,25 +75,16 @@ static int runawhile(struct Curl_easy *easy,
}
UNITTEST_START
-{
- struct Curl_easy *easy = curl_easy_init();
- abort_unless(easy, "out of memory");
-
- fail_unless(runawhile(easy, 41, 41, 40, 0) == 41,
+ fail_unless(runawhile(41, 41, 40, 0) == 41,
"wrong low speed timeout");
- fail_unless(runawhile(easy, 21, 21, 20, 0) == 21,
+ fail_unless(runawhile(21, 21, 20, 0) == 21,
"wrong low speed timeout");
- fail_unless(runawhile(easy, 60, 60, 40, 0) == 60,
+ fail_unless(runawhile(60, 60, 40, 0) == 60,
"wrong log speed timeout");
- fail_unless(runawhile(easy, 50, 50, 40, 0) == 50,
+ fail_unless(runawhile(50, 50, 40, 0) == 50,
"wrong log speed timeout");
- fail_unless(runawhile(easy, 40, 40, 40, 0) == 99,
+ fail_unless(runawhile(40, 40, 40, 0) == 99,
"should not time out");
- fail_unless(runawhile(easy, 10, 50, 100, 2) == 36,
+ fail_unless(runawhile(10, 50, 100, 2) == 36,
"bad timeout");
-
- curl_easy_cleanup(easy);
-
- return 0;
-}
UNITTEST_STOP
diff --git a/winbuild/MakefileBuild.vc b/winbuild/MakefileBuild.vc
index 36ad4681c..524926a02 100644
--- a/winbuild/MakefileBuild.vc
+++ b/winbuild/MakefileBuild.vc
@@ -267,7 +267,7 @@ GEN_PDB = true
!IFDEF EMBED_MANIFEST
-MANIFESTTOOL = mt -manifest $(DIRDIST)\$(PROGRAM_NAME).manifest -outputresource:$(DIRDIST)\$(PROGRAM_NAME);1
+MANIFESTTOOL = mt -manifest $(DIRDIST)\bin\$(PROGRAM_NAME).manifest -outputresource:$(DIRDIST)\bin\$(PROGRAM_NAME);1
!ENDIF
# Runtime library configuration